【Qtプログラミング】QFileDialogのdefaultSuffix代替案!柔軟なファイル名制御を実現

2025-05-27

QFileDialog::defaultSuffix とは

QFileDialog::defaultSuffix は、Qtのファイルダイアログ(ファイルを開いたり保存したりする際に表示されるウィンドウ)において、ユーザーがファイル名に拡張子を入力しなかった場合に、自動的に追加されるデフォルトの拡張子を設定するためのプロパティです。

たとえば、「文書を保存」するダイアログで、ユーザーがファイル名を「MyDocument」とだけ入力して保存ボタンをクリックした場合に、自動的に「MyDocument.txt」のように「.txt」が追加されるように設定することができます。

使い方

defaultSuffix は、主に QFileDialog::AcceptSave (保存ダイアログ) のモードで使用されます。

設定するには、setDefaultSuffix() メソッドを使用します。

#include <QApplication>
#include <QFileDialog>
#include <QString>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QFileDialog dialog;
    dialog.setAcceptMode(QFileDialog::AcceptSave); // 保存ダイアログとして設定
    dialog.setDefaultSuffix("txt"); // デフォルトの拡張子を "txt" に設定
    dialog.setNameFilter("Text files (*.txt);;All files (*)"); // ファイルフィルターを設定

    if (dialog.exec()) {
        QString fileName = dialog.selectedFiles().first();
        qDebug() << "保存するファイル名: " << fileName;
        // ここでファイルにデータを保存する処理を行う
    }

    return app.exec();
}

この例では、以下のようになります。

  1. QFileDialog オブジェクトを作成します。
  2. setAcceptMode(QFileDialog::AcceptSave) で保存ダイアログとして動作するように設定します。
  3. setDefaultSuffix("txt") で、ユーザーが拡張子を入力しなかった場合に「.txt」が自動的に追加されるように設定します。
  4. setNameFilter() で、ダイアログに表示されるファイルの種類のフィルターを設定します。ここでは「Text files (.txt)」と「All files ()」を設定しています。
  5. exec() を呼び出してダイアログを表示し、ユーザーがファイルを選択して「保存」ボタンをクリックするのを待ちます。
  6. dialog.selectedFiles().first() で、ユーザーが選択したファイル名を取得します。ユーザーが拡張子を入力しなかった場合でも、defaultSuffix で指定された拡張子が自動的に付加されたファイル名が返されます。
  • 上書き確認: defaultSuffix は、ファイル名が確定する際の拡張子の自動付加を制御するものです。既存のファイルを上書きする際の確認ダイアログの表示・非表示には影響しません。上書き確認については、QFileDialog::DontConfirmOverwrite オプションなどを参照してください。
  • 静的メソッドとの連携: QFileDialog::getSaveFileName() のような静的メソッドを使う場合、setDefaultSuffix() を直接呼び出すことはできません。これは、静的メソッドが特定の QFileDialog インスタンスに依存しないためです。静的メソッドでデフォルトの拡張子を制御したい場合は、ファイルフィルターの指定方法を工夫するか、明示的に取得したファイル名に拡張子が付加されているかを確認し、必要に応じて手動で追加するなどの処理が必要になることがあります。ただし、Qtのバージョンによっては静的メソッドでもフィルターから自動的にデフォルト拡張子が適用される場合があります。
  • ドット(.)の扱い: setDefaultSuffix() に渡す文字列の先頭にドット(.)があっても、Qtが自動的に削除してくれます。例えば、".txt" と指定しても txt と同じように扱われます。


QFileDialog::defaultSuffix は便利な機能ですが、いくつか注意すべき点や、予期せぬ挙動につながる可能性のある落とし穴があります。

静的メソッド (getSaveFileName など) との組み合わせ

エラー/問題: QFileDialog::getSaveFileName()QFileDialog::getOpenFileName() といった静的メソッドを使用した場合、QFileDialog のインスタンスに対して setDefaultSuffix() を呼び出しても、その設定が反映されないことがあります。

原因: 静的メソッドは、QFileDialog の内部で一時的なダイアログインスタンスを作成して表示するため、開発者が明示的に作成した QFileDialog インスタンスのプロパティ(defaultSuffix など)を参照しません。

トラブルシューティング:

  • ファイルフィルターによる代替: 静的メソッドを使用せざるを得ない場合、defaultSuffix の機能と全く同じではありませんが、ファイルフィルターによってある程度代替できます。例えば、"Text files (*.txt)" のようにフィルターを設定すると、多くのOSのネイティブダイアログでは、ユーザーが拡張子なしでファイル名を入力した場合に、そのフィルターの拡張子をデフォルトで付加しようとします。ただし、これはOSのネイティブダイアログの挙動に依存するため、すべての環境で一貫した動作が保証されるわけではありません。

    QString fileName = QFileDialog::getSaveFileName(
        this,
        tr("Save File"),
        "", // デフォルトディレクトリ
        tr("Text files (*.txt);;All files (*.*)") // フィルター
    );
    // ユーザーが拡張子を入力しなかった場合、OSによっては .txt が自動付加される可能性がある
    
  • インスタンスメソッドの使用: setDefaultSuffix() の設定を反映させたい場合は、静的メソッドではなく、QFileDialog のインスタンスを作成し、そのインスタンスに対して setAcceptMode(QFileDialog::AcceptSave)exec() を呼び出すようにします。

    QFileDialog dialog;
    dialog.setAcceptMode(QFileDialog::AcceptSave);
    dialog.setDefaultSuffix("txt"); // これが反映される
    dialog.setNameFilter("Text files (*.txt)");
    if (dialog.exec() == QDialog::Accepted) {
        QString fileName = dialog.selectedFiles().first();
        // ...
    }
    

ネイティブダイアログとQtのビルトインダイアログの挙動の違い

エラー/問題: 特定のOS(Windows, macOS, Linux)では、Qtがネイティブのファイルダイアログを使用します。このネイティブダイアログの挙動は、Qtが提供するビルトインダイアログ(QFileDialog::DontUseNativeDialog オプションを指定した場合に表示されるもの)と異なる場合があります。特に defaultSuffix の挙動は、OSによって異なることがあります。

原因: 各OSのファイルダイアログの実装は、Qtのコントロール外であり、defaultSuffix の解釈や適用方法が異なるためです。

トラブルシューティング:

  • QFileDialog::DontUseNativeDialog の利用: どうしても特定の挙動を強制したい場合は、QFileDialog::DontUseNativeDialog オプションを使用して、Qtが提供するビルトインダイアログを強制的に使用することができます。これにより、すべてのプラットフォームで一貫した defaultSuffix の挙動が期待できます。ただし、ネイティブダイアログに比べて、UIの一貫性が損なわれる可能性があります。

    QFileDialog dialog;
    dialog.setAcceptMode(QFileDialog::AcceptSave);
    dialog.setDefaultSuffix("txt");
    dialog.setOption(QFileDialog::DontUseNativeDialog); // ビルトインダイアログを使用
    dialog.setNameFilter("Text files (*.txt)");
    if (dialog.exec() == QDialog::Accepted) {
        QString fileName = dialog.selectedFiles().first();
        // ...
    }
    
  • 動作確認: 開発中のアプリケーションを異なるOSでテストし、defaultSuffix が意図通りに機能するかを確認することが重要です。

既存のファイルに拡張子が付加される問題(まれなケース)

エラー/問題: ユーザーが既に拡張子を持つ既存のファイル名を選択した場合でも、defaultSuffix が再度付加されてしまう、といった予期せぬ挙動が報告されることがあります。(これは非常にまれなケースであり、通常はQtが適切に処理します。)

原因: これはQtのバグであるか、または特定のOSのネイティブダイアログの挙動によるものです。

トラブルシューティング:

  • ファイル名の事後処理: ダイアログからファイル名を取得した後、プログラム側で拡張子の重複をチェックし、必要に応じて修正するロジックを追加することを検討します。

    QString fileName = dialog.selectedFiles().first();
    // 拡張子が二重に付加されていないか確認する簡単なロジック
    if (fileName.endsWith(".txt.txt")) {
        fileName.chop(4); // ".txt" を削除
    }
    

    ただし、この方法は汎用性に欠けるため、できるだけQtの標準機能で解決できるか確認することが望ましいです。

  • Qtのバージョン確認: 最新のQtバージョンに更新することで、既知のバグが修正されている可能性があります。

ファイルパスにドットを含む場合の挙動 (既知のバグ)

エラー/問題: ファイルパス自体にドットが含まれる場合 (例: C:/My.Folder/document)、defaultSuffix が正しく適用されない、または予期せぬ場所に拡張子が付加されるという報告が、過去のQtバージョンでなされていました ( など)。

原因: パス解析のロジックに問題があったり、ネイティブダイアログとの連携がうまくいかない場合に発生します。

トラブルシューティング:

  • テストと回避策: もしアップデートが難しい場合や、特定の環境で問題が再現する場合は、ドットを含むパスでの動作を十分にテストし、必要に応じてファイル名の後処理で対応するなどの回避策を検討します。
  • Qtのバージョンアップ: この手の問題は、多くの場合、Qtの新しいバージョンで修正されています。使用しているQtのバージョンが古い場合は、アップデートを検討してください。

QFileDialog::defaultSuffix を使用する際の主なポイントは以下の通りです。

  • Qtのバージョンを最新に保つ:バグ修正や機能改善が継続的に行われているため、最新の安定版を使用することが推奨されます。
  • ネイティブダイアログとビルトインダイアログの挙動の違いを理解する:特にクロスプラットフォーム開発を行う場合は、各OSでの動作確認が重要です。一貫性を重視する場合は QFileDialog::DontUseNativeDialog を検討します。
  • 静的メソッドではなくインスタンスメソッドを使用するsetDefaultSuffix() の設定を確実に反映させるには、QFileDialog のインスタンスを生成して使用するのが最も確実です。


例1: 基本的な保存ダイアログでの defaultSuffix の設定

この例では、ユーザーがファイル名を拡張子なしで入力した場合に、自動的に.txtが付加されるように設定します。

#include <QApplication>
#include <QFileDialog>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QDebug> // デバッグ出力用

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QPushButton *saveButton = new QPushButton("ファイルを保存", &window);
    layout->addWidget(saveButton);

    QObject::connect(saveButton, &QPushButton::clicked, [&]() {
        QFileDialog dialog(&window); // 親ウィジェットを指定
        dialog.setAcceptMode(QFileDialog::AcceptSave); // 保存ダイアログとして設定
        dialog.setDefaultSuffix("txt"); // デフォルトの拡張子を "txt" に設定
        dialog.setNameFilter("テキストファイル (*.txt);;すべてのファイル (*.*)"); // ファイルフィルターを設定
        dialog.setWindowTitle("テキストファイルを保存"); // ダイアログのタイトル

        if (dialog.exec() == QDialog::Accepted) {
            QString selectedFileName = dialog.selectedFiles().first();
            qDebug() << "選択されたファイル名: " << selectedFileName;

            // ここでファイルにデータを保存する処理を実装
            // 例: QTextStream でファイルに書き込む
            QFile file(selectedFileName);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QTextStream out(&file);
                out << "これはサンプルテキストです。\n";
                file.close();
                qDebug() << "ファイルが保存されました: " << selectedFileName;
            } else {
                qDebug() << "ファイルの保存に失敗しました: " << file.errorString();
            }
        } else {
            qDebug() << "ファイル保存がキャンセルされました。";
        }
    });

    window.show();
    return app.exec();
}

解説

  1. QFileDialog dialog(&window);QFileDialog のインスタンスを作成し、親ウィジェットとしてwindowを指定します。これにより、ダイアログがアプリケーションのメインウィンドウにアタッチされます。
  2. dialog.setAcceptMode(QFileDialog::AcceptSave); で、このダイアログがファイルを「保存」するためのものであることを指定します。defaultSuffix はこのモードで最も効果を発揮します。
  3. dialog.setDefaultSuffix("txt"); が今回の主役です。ユーザーがファイル名に拡張子を入力しなかった場合(例: MyDocument と入力)、最終的なファイル名は自動的に MyDocument.txt となります。
  4. dialog.setNameFilter("テキストファイル (*.txt);;すべてのファイル (*.*)"); は、ファイルの種類を選択するためのフィルターを設定します。ユーザーが「テキストファイル」を選択すると、拡張子.txtを持つファイルが優先的に表示されます。
  5. dialog.exec() == QDialog::Accepted は、ユーザーがダイアログで「保存」ボタンをクリックしたかどうかをチェックします。
  6. dialog.selectedFiles().first() で、ユーザーが選択した(または自動的に拡張子が付加された)ファイルパスを取得します。

例2: defaultSuffixDontConfirmOverwrite オプションの組み合わせ

この例では、デフォルト拡張子を設定しつつ、既存のファイルを上書きする際に確認ダイアログを表示しないように設定します。

#include <QApplication>
#include <QFileDialog>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QDebug>
#include <QFile>
#include <QTextStream>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QPushButton *saveButton = new QPushButton("ログファイルを保存 (上書き確認なし)", &window);
    layout->addWidget(saveButton);

    QObject::connect(saveButton, &QPushButton::clicked, [&]() {
        QFileDialog dialog(&window);
        dialog.setAcceptMode(QFileDialog::AcceptSave);
        dialog.setDefaultSuffix("log"); // デフォルト拡張子を "log" に
        dialog.setNameFilter("ログファイル (*.log);;すべてのファイル (*.*)");
        dialog.setWindowTitle("ログファイルを保存");

        // 既存ファイルを上書きする際に確認ダイアログを表示しない
        dialog.setOption(QFileDialog::DontConfirmOverwrite, true);

        if (dialog.exec() == QDialog::Accepted) {
            QString selectedFileName = dialog.selectedFiles().first();
            qDebug() << "選択されたファイル名: " << selectedFileName;

            // ここでファイルにデータを保存する処理
            QFile file(selectedFileName);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) { // Appendで追記も可能
                QTextStream out(&file);
                out << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << ": これはログエントリです。\n";
                file.close();
                qDebug() << "ログが保存されました: " << selectedFileName;
            } else {
                qDebug() << "ログの保存に失敗しました: " << file.errorString();
            }
        } else {
            qDebug() << "ログ保存がキャンセルされました。";
        }
    });

    window.show();
    return app.exec();
}

解説

  1. dialog.setOption(QFileDialog::DontConfirmOverwrite, true); を追加することで、ユーザーが既に存在するファイル名を選択した場合でも、「ファイルを上書きしますか?」といった確認ダイアログが表示されなくなります。これは、ログファイルのように頻繁に上書き・追記される可能性があるファイルに適しています。

ネイティブダイアログの挙動が期待と異なる場合に、Qt独自のビルトインダイアログを強制的に使用する例です。

#include <QApplication>
#include <QFileDialog>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QDebug>
#include <QFile>
#include <QTextStream>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QPushButton *saveButton = new QPushButton("データを保存 (非ネイティブダイアログ)", &window);
    layout->addWidget(saveButton);

    QObject::connect(saveButton, &QPushButton::clicked, [&]() {
        QFileDialog dialog(&window);
        dialog.setAcceptMode(QFileDialog::AcceptSave);
        dialog.setDefaultSuffix("dat"); // デフォルト拡張子を "dat" に
        dialog.setNameFilter("データファイル (*.dat);;すべてのファイル (*.*)");
        dialog.setWindowTitle("データファイルを保存 (Qtダイアログ)");

        // ネイティブダイアログではなく、Qtのビルトインダイアログを使用する
        dialog.setOption(QFileDialog::DontUseNativeDialog, true);

        if (dialog.exec() == QDialog::Accepted) {
            QString selectedFileName = dialog.selectedFiles().first();
            qDebug() << "選択されたファイル名: " << selectedFileName;

            // ここでファイルにデータを保存する処理
            QFile file(selectedFileName);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QTextStream out(&file);
                out << "データ: " << selectedFileName << "\n";
                file.close();
                qDebug() << "データファイルが保存されました: " << selectedFileName;
            } else {
                qDebug() << "データファイルの保存に失敗しました: " << file.errorString();
            }
        } else {
            qDebug() << "データ保存がキャンセルされました。";
        }
    });

    window.show();
    return app.exec();
}
  1. dialog.setOption(QFileDialog::DontUseNativeDialog, true); を設定することで、OSのネイティブファイルダイアログではなく、Qtが提供する標準の(Qtウィジェットベースの)ファイルダイアログが表示されます。これにより、プラットフォーム間の defaultSuffix の挙動の一貫性をより保証できます。ただし、UIの見た目は各OSのネイティブダイアログとは異なります。


ファイルフィルターによる「暗黙の」デフォルト拡張子

これは厳密には defaultSuffix の代替というよりも、多くのネイティブファイルダイアログが持つ挙動を利用する方法です。ファイルフィルターに特定の拡張子だけを指定すると、ユーザーがそのフィルターを選択した場合、ネイティブダイアログがその拡張子をデフォルトとして扱うことがあります。

方法
setNameFilter() メソッドで、単一の拡張子を持つフィルターを設定します。

#include <QApplication>
#include <QFileDialog>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QPushButton *saveButton = new QPushButton("ファイルを保存 (フィルターで拡張子推奨)", &window);
    layout->addWidget(saveButton);

    QObject::connect(saveButton, &QPushButton::clicked, [&]() {
        // 静的メソッドを使用
        QString fileName = QFileDialog::getSaveFileName(
            &window,
            "ファイルを保存",
            "", // デフォルトディレクトリ
            "XMLファイル (*.xml);;すべてのファイル (*.*)" // フィルター
        );

        if (!fileName.isEmpty()) {
            qDebug() << "選択されたファイル名: " << fileName;
            // ユーザーが拡張子を入力しなかった場合、OSによっては .xml が自動付加される可能性がある
            // ただし、これは保証されない。次の「事後処理」を参照。
        } else {
            qDebug() << "ファイル保存がキャンセルされました。";
        }
    });

    window.show();
    return app.exec();
}

利点

  • 多くのネイティブダイアログで自然な挙動を提供します。
  • defaultSuffix を明示的に設定する必要がないため、コードが簡潔になる場合があります。

欠点

  • ユーザーが別のフィルターを選択した場合でも、常に特定の拡張子を付加したい場合には適しません。
  • ネイティブダイアログの挙動に依存するため、すべてのOSで確実に動作するわけではありません。特に複数のフィルターがある場合、どのフィルターの拡張子が優先されるかはOSによって異なります。

ファイル名の事後処理 (Post-processing)

これは最も確実で柔軟な方法であり、QFileDialog が返したファイル名に対して、プログラム側で拡張子の有無をチェックし、必要に応じて追加または修正します。

方法
QFileDialog::selectedFiles() から取得したファイル名(または静的メソッドの戻り値)を QFileInfoQString のメソッドで解析し、拡張子の有無を確認して処理します。

#include <QApplication>
#include <QFileDialog>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QDebug>
#include <QFileInfo> // ファイル情報の取得用

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QPushButton *saveButton = new QPushButton("ファイルを保存 (事後処理で拡張子追加)", &window);
    layout->addWidget(saveButton);

    QObject::connect(saveButton, &QPushButton::clicked, [&]() {
        QString initialFileName = "新しいドキュメント"; // ユーザーに提案するファイル名(拡張子なし)

        QFileDialog dialog(&window);
        dialog.setAcceptMode(QFileDialog::AcceptSave);
        dialog.setNameFilter("テキストファイル (*.txt);;すべてのファイル (*.*)");
        dialog.setWindowTitle("テキストファイルを保存");
        // 初期ファイル名を設定 (デフォルトのディレクトリ + 初期ファイル名)
        // QFileDialog::selectFile()は既存のファイルパスにのみ機能する場合があります。
        // 未設定の場合、空欄または最後に開いたディレクトリのファイル名になります。
        // 初期ファイル名を完全に制御したい場合は、getSaveFileNameの引数 `dir` に `QDir::homePath() + "/" + initialFileName` のように指定すると便利です。
        dialog.selectFile(initialFileName); // 初期ファイル名を設定。ただし、これはディレクトリパスがないと期待通りに動作しない場合がある。

        QString finalFileName;
        if (dialog.exec() == QDialog::Accepted) {
            QString selectedFileName = dialog.selectedFiles().first();
            QFileInfo fileInfo(selectedFileName);

            // 拡張子が付いていない場合、または意図しない拡張子の場合に付加する
            if (fileInfo.suffix().isEmpty()) {
                finalFileName = selectedFileName + ".txt";
                qDebug() << "拡張子なし -> .txt を付加: " << finalFileName;
            } else if (fileInfo.suffix() != "txt" && fileInfo.suffix() != "TXT") { // 大文字小文字も考慮
                qDebug() << "既存の拡張子を保持: " << selectedFileName;
                finalFileName = selectedFileName; // ユーザーが入力した拡張子を尊重
            } else {
                finalFileName = selectedFileName; // 既に正しい拡張子が付いている
            }

            qDebug() << "最終的なファイル名: " << finalFileName;
            // ここでファイルにデータを保存する処理を実装
            // 例: QTextStream でファイルに書き込む
            QFile file(finalFileName);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QTextStream out(&file);
                out << "これは事後処理で保存されたテキストです。\n";
                file.close();
                qDebug() << "ファイルが保存されました: " << finalFileName;
            } else {
                qDebug() << "ファイルの保存に失敗しました: " << file.errorString();
            }
        } else {
            qDebug() << "ファイル保存がキャンセルされました。";
        }
    });

    window.show();
    return app.exec();
}

利点

  • QFileDialog::getSaveFileName() などの静的メソッドと組み合わせても機能します。
  • defaultSuffix では不可能な、より複雑な拡張子のロジック(例: ユーザーが特定の拡張子を入力した場合にそれを尊重し、それ以外の場合にのみデフォルトを付加する)を実装できます。
  • 最も確実で、クロスプラットフォームで一貫した動作が期待できます。

欠点

  • ファイルダイアログからファイル名が返された後に、追加の処理ロジックが必要になります。

静的メソッドの dir 引数にデフォルトファイル名を含める

QFileDialog::getSaveFileName()dir 引数(デフォルトディレクトリ)に、ファイル名まで含めて指定することで、ダイアログのファイル名入力欄に初期値を表示させることができます。ユーザーがこの初期値をそのまま使用すれば、拡張子も含まれることになります。

#include <QApplication>
#include <QFileDialog>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QDebug>
#include <QDir> // QDir::homePath() 用

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QPushButton *saveButton = new QPushButton("ファイルを保存 (初期ファイル名指定)", &window);
    layout->addWidget(saveButton);

    QObject::connect(saveButton, &QPushButton::clicked, [&]() {
        QString defaultPath = QDir::homePath() + "/MyReport.xlsx"; // デフォルトのパスとファイル名

        QString fileName = QFileDialog::getSaveFileName(
            &window,
            "レポートを保存",
            defaultPath, // デフォルトのディレクトリとファイル名を指定
            "Excelファイル (*.xlsx);;すべてのファイル (*.*)"
        );

        if (!fileName.isEmpty()) {
            qDebug() << "選択されたファイル名: " << fileName;
            // ここでファイル保存処理
        } else {
            qDebug() << "ファイル保存がキャンセルされました。";
        }
    });

    window.show();
    return app.exec();
}

利点

  • defaultSuffix とは異なり、ファイル名全体(パスと拡張子を含む)をデフォルトとして指定できます。
  • ユーザーに具体的なファイル名を提案できるため、利便性が高いです。

欠点

  • dir 引数にファイル名を含める方法は、OSのネイティブダイアログの挙動に依存する場合があります。
  • ユーザーがファイル名を変更した場合、その変更を尊重します。拡張子を常に強制したい場合には、上記の「事後処理」と組み合わせる必要があります。

QFileDialog::defaultSuffix は、基本的なケースでは非常に便利ですが、より複雑な要件やクロスプラットフォームでの一貫性を求める場合には、上記の代替方法が有効です。

  • ユーザーに具体的なファイル名を提案したい: 静的メソッドの dir 引数にデフォルトファイル名を含める。
  • 最も確実で柔軟な制御が必要: ファイル名の事後処理。
  • 簡単なケース、ネイティブダイアログの挙動に任せたい: ファイルフィルターによる「暗黙の」デフォルト拡張子。