Qt QSettings::applicationName()とは?設定管理の基本を徹底解説

2025-05-27

QSettings::applicationName()とは

QSettings::applicationName()は、QtのQSettingsクラスのメンバー関数の一つで、アプリケーションの名前を返します。

QSettingsクラスは、アプリケーション固有の設定情報を保存・読み込みするために使われます。Windowsではレジストリ、macOSではplistファイル、Unix系システムではINIファイルのような形式で設定を保存するのが一般的です。

QSettingsが設定を保存する際に、どのアプリケーションの設定であるかを識別するために、組織名 (organizationName)アプリケーション名 (applicationName) が必要になります。applicationName()はこのアプリケーション名をプログラムから取得するための関数です。

どのように使われるか

通常、QSettingsのインスタンスを作成する際に、コンストラクタで組織名とアプリケーション名を指定します。

QSettings settings("MyCompany", "MyApp");

この例では、"MyCompany"が組織名、"MyApp"がアプリケーション名として設定されます。

その後、プログラムのどこかで現在のQSettingsオブジェクトが認識しているアプリケーション名を取得したい場合に、settings.applicationName()を呼び出すことで、"MyApp"という文字列が返されます。

QString appName = settings.applicationName(); // appName には "MyApp" が格納される
  • デバッグやログ
    現在の設定がどのアプリケーションに紐付いているのかをデバッグ情報やログに出力する際に、applicationName()で取得した文字列を利用することができます。
  • 移植性
    OSによって設定ファイルの保存場所や形式が異なる中で、QSettingsはこれらの違いを抽象化し、開発者がアプリケーション名と組織名だけを指定すれば、適切な場所に設定を保存できるようにします。applicationName()はそのアプリケーション名をプログラム側で確認するために使えます。
  • 設定の識別
    QSettingsは、複数のアプリケーションが同じシステム上で動作している場合でも、それぞれの設定が混同しないように、組織名とアプリケーション名を使って設定を識別します。


QSettings::applicationName()自体は、設定オブジェクトに設定されたアプリケーション名を返すだけのシンプルな関数なので、この関数自体が直接エラーを引き起こすことは稀です。しかし、QSettingsの他の機能との連携や、設定の保存・読み込みにおける問題の兆候として、アプリケーション名の設定ミスが原因となることがあります。

設定が保存・読み込みされない (最も多いケース)

エラーの兆候

  • 設定ファイル(INIファイルなど)が期待する場所に生成されていない、または内容が更新されていない。
  • QSettings::value()で値を取得しようとしても、常にデフォルト値が返されるか、空のQVariantが返される。
  • アプリケーションを再起動しても、以前の設定(ウィンドウの位置、サイズ、ユーザー設定など)が反映されない。

原因
QSettingsが設定を保存・読み込みする際に、正しい「組織名」と「アプリケーション名」が設定されていないことが最も一般的な原因です。

  • QCoreApplication::setOrganizationName() / setApplicationName() の呼び出し忘れまたは順序ミス
    QSettingsのデフォルトコンストラクタ(引数なしのコンストラクタ)を使用する場合、QCoreApplication::setOrganizationName()QCoreApplication::setApplicationName()で事前に組織名とアプリケーション名を設定しておく必要があります。

    // main.cpp 内 (推奨される方法)
    int main(int argc, char *argv[]) {
        QApplication a(argc, argv);
    
        // **これらをQSettingsインスタンス作成の前に呼び出すこと**
        QCoreApplication::setOrganizationName("MyCompany");
        QCoreApplication::setApplicationName("MyApp");
    
        // これでQSettingsは上記で設定された名前を使用する
        QSettings settings;
        // ...
        return a.exec();
    }
    
    // 誤った例: QSettingsの後に設定
    int main(int argc, char *argv[]) {
        QApplication a(argc, argv);
        QSettings settings; // この時点では組織名/アプリ名が未設定 or デフォルト
    
        QCoreApplication::setOrganizationName("MyCompany");
        QCoreApplication::setApplicationName("MyApp"); // 遅すぎる!
        // ...
        return a.exec();
    }
    

    アプリケーション名の設定が遅れると、QSettingsオブジェクトが作成された時点では正しいアプリケーション名が認識されておらず、結果として意図しない場所に設定が保存されたり、既存の設定が読み込まれなかったりします。

  • QSettingsコンストラクタでの指定ミス

    // 誤った例: アプリケーション名が間違っている
    QSettings settings("MyCompany", "MyWrongApp"); // 別のアプリ名
    

    この場合、設定は"MyWrongApp"という名前で保存され、後で"MyApp"という名前でQSettingsインスタンスを作成しても、"MyWrongApp"の設定は読み込まれません。

トラブルシューティング

  1. コードレビュー
    QSettingsオブジェクトが作成される場所、およびQCoreApplication::setOrganizationName()QCoreApplication::setApplicationName()が呼び出される場所を確認します。これらがQSettingsオブジェクトの作成よりも前に、かつ正しい文字列で呼び出されていることを確認してください。
  2. デバッグ出力
    QSettings::applicationName()QSettings::organizationName()を呼び出して、実際にQSettingsが認識している名前をqDebug()で出力し、期待する値と一致しているか確認します。
    QSettings settings; // または QSettings settings("MyCompany", "MyApp");
    qDebug() << "Organization Name:" << settings.organizationName();
    qDebug() << "Application Name:" << settings.applicationName();
    qDebug() << "Settings File:" << settings.fileName(); // どのファイルに設定が保存されるか確認
    
  3. 設定ファイルの場所を確認
    QSettings::fileName()で返されるパスを確認し、実際にその場所に設定ファイルが存在するかどうか、またその内容が正しいか(手動でINIファイルなどを開いて)確認します。OSによって保存場所が異なります。
    • Windows
      レジストリ (HKEY_CURRENT_USER\Software\<OrganizationName>\<ApplicationName>) または INI ファイル
    • macOS
      .plist ファイル (~/Library/Preferences/<OrganizationName>.<ApplicationName>.plist または ~/Library/Preferences/com.<OrganizationName>.<ApplicationName>.plist)
    • Linux/Unix
      INI ファイル (~/.config/<OrganizationName>/<ApplicationName>.conf または ~/.local/share/<OrganizationName>/<ApplicationName>.confなど)

アプリケーション名がOSの慣例に合わない (macOSでの注意)

エラーの兆候

  • macOS上で設定が正しく機能しない、または他のアプリケーションと設定が混同する。

原因
macOSでは、慣例としてバンドル識別子(Bundle Identifier)が設定の識別に使われます。これは通常、逆引きドメイン形式(例: com.mycompany.myapp)で表現されます。QSettingsは、組織名がドメイン名形式でない場合、自動的に.comを付加したり、スペースをハイフンに変換したりして、偽のドメイン名を生成しようとしますが、これが期待通りに機能しない場合があります。

トラブルシューティング

  • バンドル識別子に合わせる
    macOSで配布するアプリケーションの場合、QCoreApplication::setOrganizationDomain()QCoreApplication::setApplicationName()を組み合わせるか、Info.plistで設定されるバンドル識別子に合わせた組織名とアプリケーション名をQSettingsに渡すことを検討します。
    QCoreApplication::setOrganizationDomain("com.mycompany"); // ドメイン形式
    QCoreApplication::setApplicationName("MyApp");
    

異なるQSettingsインスタンス間での整合性問題

エラーの兆候

  • アプリケーション内の異なる場所でQSettingsを扱う際に、一方で行った変更がもう一方に反映されない、または意図しない設定が読み込まれる。

原因

  • シングルトンパターンの不採用
    QSettingsは軽量なクラスですが、アプリケーション全体で共通の設定を扱う場合、アプリケーション名と組織名を一貫して設定し、できれば同じQSettingsインスタンス(または同じ設定を参照するインスタンス)を使用することが望ましいです。
  • 異なるアプリケーション名/組織名でQSettingsインスタンスを作成している
    アプリケーション内で複数のQSettingsインスタンスを作成する際に、異なるアプリケーション名や組織名を指定してしまうと、それぞれが別の設定セットを参照することになります。

トラブルシューティング

  • QSettingsのライフサイクル
    QSettingsオブジェクトの生成と破棄は非常に高速です。必要に応じてローカルでインスタンスを作成しても問題ありませんが、前述の通り、組織名とアプリケーション名の一貫性が重要です。
  • 一貫した名前の使用
    アプリケーション全体で、QCoreApplication::setOrganizationName()QCoreApplication::setApplicationName()をアプリケーション起動時に一度だけ設定し、その後は引数なしのQSettingsコンストラクタを使用することを強く推奨します。
    // main.cpp で一度だけ設定
    int main(int argc, char *argv[]) {
        QApplication a(argc, argv);
        QCoreApplication::setOrganizationName("MyCompany");
        QCoreApplication::setApplicationName("MyApp");
        // ...
    }
    
    // 他の場所で設定を読み書きする場合
    void MyClass::saveSettings() {
        QSettings settings; // 引数なしで、設定された組織名/アプリ名を使用
        settings.setValue("windowGeometry", saveGeometry());
    }
    
    void MyClass::loadSettings() {
        QSettings settings; // 引数なしで、設定された組織名/アプリ名を使用
        restoreGeometry(settings.value("windowGeometry").toByteArray());
    }
    

特殊文字や空白を含むアプリケーション名

エラーの兆候

  • アプリケーション名に特殊文字やスペースが含まれる場合、設定ファイルやレジストリパスの生成で問題が発生することがある。

原因
OSによっては、ファイル名やレジストリキーに使用できる文字に制限がある場合があります。QSettingsはこれらの違いを吸収しようとしますが、予期せぬ問題が発生する可能性はゼロではありません。

  • シンプルな名前の使用
    アプリケーション名には、英数字とハイフンのみを使用するなど、シンプルでOS間の互換性の高い文字列を使用することを推奨します。


アプリケーション起動時に組織名とアプリケーション名を設定する(推奨される方法)

この方法は、アプリケーション全体で一貫した設定を使用する際に最も推奨されます。QCoreApplication::setOrganizationName()QCoreApplication::setApplicationName()(GUIアプリケーションの場合はQApplicationも同様)をmain関数内で設定することで、その後引数なしでQSettingsオブジェクトを作成した際に、これらの設定が自動的に適用されます。

main.cpp

#include <QApplication> // GUIアプリケーションの場合
// #include <QCoreApplication> // GUIがないアプリケーションの場合
#include <QSettings>
#include <QDebug>
#include "mainwindow.h" // GUIアプリケーションの場合

int main(int argc, char *argv[])
{
    QApplication a(argc, argv); // QApplicationのインスタンスを作成

    // **重要: QSettingsオブジェクトを作成する前に、組織名とアプリケーション名を設定する**
    QCoreApplication::setOrganizationName("MyCompany"); // 組織名を設定
    QCoreApplication::setApplicationName("MyAwesomeApp"); // アプリケーション名を設定
    QCoreApplication::setApplicationVersion("1.0.0"); // オプション: アプリケーションバージョンも設定可能

    // QSettingsオブジェクトを作成
    // 引数なしで作成すると、QCoreApplicationで設定された組織名とアプリケーション名が使われる
    QSettings settings;

    // 現在のアプリケーション名と組織名を取得し、デバッグ出力
    qDebug() << "QSettings Organization Name:" << settings.organizationName();
    qDebug() << "QSettings Application Name:" << settings.applicationName();

    // 設定ファイルのパスを確認
    qDebug() << "Settings file path:" << settings.fileName();

    // 設定の保存例
    settings.setValue("mainWindow/geometry", QByteArray("...")); // 例: ウィンドウのジオメトリ
    settings.setValue("user/name", "Alice"); // 例: ユーザー名
    settings.setValue("user/rememberLogin", true); // 例: ログイン情報を記憶するか

    qDebug() << "Settings saved.";

    // アプリケーションのメインウィンドウを表示 (GUIアプリケーションの場合)
    MainWindow w;
    w.show();

    return a.exec(); // イベントループを開始
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSettings> // QSettingsを使用するためにインクルード

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    void closeEvent(QCloseEvent *event) override; // ウィンドウクローズイベントをオーバーライド

private:
    Ui::MainWindow *ui;

    void loadSettings(); // 設定を読み込む関数
    void saveSettings(); // 設定を保存する関数
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QCloseEvent>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    loadSettings(); // ウィンドウ初期化時に設定を読み込む
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::loadSettings()
{
    QSettings settings; // QCoreApplicationで設定された名前を使用

    // ウィンドウのジオメトリを読み込む
    QByteArray geometry = settings.value("mainWindow/geometry").toByteArray();
    if (!geometry.isEmpty()) {
        restoreGeometry(geometry);
    } else {
        // 設定がない場合のデフォルト値
        resize(800, 600);
        move(100, 100);
    }

    // ユーザー名を読み込む
    QString userName = settings.value("user/name", "Guest").toString();
    ui->statusBar->showMessage("Welcome, " + userName + "!");

    qDebug() << "Settings loaded.";
}

void MainWindow::saveSettings()
{
    QSettings settings; // QCoreApplicationで設定された名前を使用

    // ウィンドウのジオメトリを保存
    settings.setValue("mainWindow/geometry", saveGeometry());

    // その他の設定も保存(例として、ここではハードコード)
    settings.setValue("user/name", "User123");
    settings.setValue("user/rememberLogin", false);

    // 設定を強制的にディスクに書き込む (通常は不要、QSettingsが自動的に処理)
    settings.sync();

    qDebug() << "Settings saved from MainWindow.";
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    saveSettings(); // ウィンドウを閉じる前に設定を保存
    QMainWindow::closeEvent(event);
}

解説

  • settings.fileName()は、実際に設定が保存されるファイルパス(またはレジストリパスのヒント)を返します。OSによってそのパスは異なります。
  • settings.organizationName()settings.applicationName()を呼び出すことで、現在のQSettingsオブジェクトがどの組織とアプリケーション名で設定を管理しているかを確認できます。これはデバッグ時に特に役立ちます。
  • その後、QSettings settings;のように引数なしでQSettingsオブジェクトを作成すると、自動的に上記の識別子が使用されます。
  • main.cppQCoreApplication::setOrganizationName()QCoreApplication::setApplicationName()を呼び出している点が重要です。これにより、アプリケーションの起動時に設定の「識別子」が確立されます。

QSettingsコンストラクタで直接組織名とアプリケーション名を指定する

この方法は、特定の状況下でQCoreApplicationの設定とは異なる設定を使用したい場合や、アプリケーションの起動時にQCoreApplicationの情報を設定できない場合に利用できます。ただし、アプリケーション全体で一貫した設定を扱うには、この方法を頻繁に使うのは複雑になる可能性があります。

#include <QCoreApplication>
#include <QSettings>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // QCoreApplication::setApplicationName() を呼ばなくても、QSettingsで直接指定
    // QCoreApplication::setOrganizationName("AnotherCompany"); // こちらは使われない
    // QCoreApplication::setApplicationName("AnotherApp");    // こちらも使われない

    // QSettingsのコンストラクタで直接、組織名とアプリケーション名を指定
    QSettings settings("MySpecificCompany", "MySpecificApp");

    qDebug() << "QSettings Organization Name:" << settings.organizationName();
    qDebug() << "QSettings Application Name:" << settings.applicationName();

    settings.setValue("lastOpenedFile", "/path/to/document.txt");
    qDebug() << "Setting saved: lastOpenedFile";

    // 別のQSettingsインスタンスを作成(デフォルトコンストラクタ)
    // この場合、QCoreApplicationで設定されていなければ、実行ファイル名などがデフォルトになる
    QSettings defaultSettings;
    qDebug() << "Default QSettings Organization Name:" << defaultSettings.organizationName();
    qDebug() << "Default QSettings Application Name:" << defaultSettings.applicationName();

    // 異なるQSettingsインスタンスなので、設定も異なる
    qDebug() << "Value from MySpecificApp:" << settings.value("lastOpenedFile").toString();
    qDebug() << "Value from DefaultApp:" << defaultSettings.value("lastOpenedFile").toString();

    return a.exec();
}
  • 複数のQSettingsインスタンスが異なる識別子を持つ場合、それぞれが独立した設定セットを管理することになります。
  • この場合、QCoreApplication::setOrganizationName()QCoreApplication::setApplicationName()で設定された値は、このQSettingsインスタンスには影響しません。
  • QSettings settings("MySpecificCompany", "MySpecificApp");のように、コンストラクタの引数で組織名とアプリケーション名を直接渡しています。


QtのQSettings::applicationName()自体は、設定の保存先を決定するために使用されるアプリケーションの名前を取得する関数です。これに代わるプログラミング上のアプローチとは、通常、QSettings以外の方法でアプリケーションの設定を管理することを指します。

QSettingsはクロスプラットフォームで設定を管理するための便利な抽象化レイヤーですが、特定のユースケースや要件によっては、他の方法が適している場合もあります。

以下に、QSettingsの代替となる一般的な方法と、それぞれの簡単な説明を挙げます。

JSONファイル、XMLファイルなどの汎用データフォーマットを使用する

メリット

  • 他言語との互換性
    他のプログラミング言語で書かれたアプリケーションとの間で設定ファイルを共有しやすい。
  • 柔軟なデータ構造
    階層的なデータを表現しやすく、複雑な設定も管理しやすい。
  • 高い移植性
    OSに依存しないファイル形式なので、異なるOS間での設定ファイルの移行が容易。
  • 人間が読みやすい
    テキストファイルなので、設定を直接開いて確認・編集しやすい。

デメリット

  • ファイルIOの直接管理
    ファイルの読み書き、エラーハンドリングなどを自分で実装する必要がある(QSettingsはこれを抽象化してくれる)。
  • 手動でのパス管理
    設定ファイルをどこに保存するか(例: ユーザーのドキュメントフォルダ、アプリケーションデータフォルダ)を自分で決定し、管理する必要がある。
  • プラットフォームネイティブな機能の欠如
    レジストリ(Windows)やplist(macOS)などのOSネイティブな設定管理メカニズムを利用しないため、OSの標準的な設定ツールからは見えない。

関連するQtクラス

  • QStandardPaths: OSごとの標準的なディレクトリ(アプリケーションデータ、ドキュメントなど)のパスを取得するために非常に便利。
  • QFile, QTextStream, QDataStream: ファイルI/O全般。
  • QXmlStreamReader, QXmlStreamWriter: XMLデータの読み書き。
  • QJsonDocument, QJsonObject, QJsonArray: JSONデータの読み書き。

コードの概念

// JSONファイルの読み書きの概念
#include <QApplication>
#include <QJsonDocument>
#include <QJsonObject>
#include <QFile>
#include <QStandardPaths>
#include <QDebug>

void saveSettingsToJson() {
    QString appDataLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    QDir dir(appDataLocation);
    if (!dir.exists()) {
        dir.mkpath("."); // ディレクトリが存在しない場合は作成
    }
    QString filePath = appDataLocation + "/my_app_settings.json";

    QJsonObject settingsObject;
    settingsObject["userName"] = "John Doe";
    settingsObject["lastOpenedFile"] = "/home/user/document.txt";
    settingsObject["windowWidth"] = 1024;
    settingsObject["rememberMe"] = true;

    QJsonDocument doc(settingsObject);
    QFile file(filePath);
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        file.write(doc.toJson());
        file.close();
        qDebug() << "Settings saved to:" << filePath;
    } else {
        qWarning() << "Failed to save settings to:" << filePath;
    }
}

void loadSettingsFromJson() {
    QString appDataLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    QString filePath = appDataLocation + "/my_app_settings.json";

    QFile file(filePath);
    if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QByteArray jsonData = file.readAll();
        file.close();

        QJsonDocument doc = QJsonDocument::fromJson(jsonData);
        if (!doc.isNull()) {
            QJsonObject settingsObject = doc.object();
            QString userName = settingsObject["userName"].toString();
            QString lastOpenedFile = settingsObject["lastOpenedFile"].toString();
            int windowWidth = settingsObject["windowWidth"].toInt();
            bool rememberMe = settingsObject["rememberMe"].toBool();

            qDebug() << "Settings loaded:";
            qDebug() << "  User Name:" << userName;
            qDebug() << "  Last Opened File:" << lastOpenedFile;
            qDebug() << "  Window Width:" << windowWidth;
            qDebug() << "  Remember Me:" << rememberMe;
        } else {
            qWarning() << "Failed to parse JSON from:" << filePath;
        }
    } else {
        qWarning() << "Failed to open settings file for reading:" << filePath;
    }
}

int main(int argc, char *argv[]) {
    QApplication a(argc, argv); // QApplicationのインスタンスを作成
    // JSONファイルの場合は、QCoreApplication::setApplicationName() は直接関係しませんが
    // QStandardPaths::AppDataLocation を使う場合、QCoreApplication::setApplicationName() を
    // 設定しておくことで、アプリケーション名に基づいてパスが自動的に構築されます。
    QCoreApplication::setOrganizationName("MyCompany");
    QCoreApplication::setApplicationName("MyManualApp");

    saveSettingsToJson();
    loadSettingsFromJson();

    // 通常のQtアプリケーションではGUIを表示したりイベントループを実行したりします
    // return a.exec();
    return 0; // 簡単な例なので即座に終了
}

SQLiteなどの埋め込みデータベースを使用する

メリット

  • 大規模な設定にも対応
    QSettingsよりも大量のデータや複雑なデータ関係を扱うのに適している。
  • 堅牢性
    トランザクション処理などにより、データの一貫性と信頼性が高い。
  • クエリ機能
    SQLを使用して柔軟にデータを検索、フィルタリング、更新できる。
  • 構造化されたデータ管理
    複雑な設定や関連するデータをリレーショナルな形式で管理できる。

デメリット

  • デバッグの複雑さ
    設定ファイルを手動で開いて確認するようにはいかない。
  • 学習曲線
    SQLやデータベースの概念の知識が必要になる。
  • オーバーヘッド
    設定のためだけにデータベースを使用するのは、セットアップと管理のオーバーヘッドがある。

関連するQtクラス

  • QSqlDatabase, QSqlQuery: データベース操作。

カスタムバイナリ形式で保存する

メリット

  • データ保護(限定的)
    簡単には人間が読めないため、設定内容をある程度隠蔽できる。
  • コンパクトなファイルサイズ
    テキスト形式に比べてファイルサイズを小さくできる。
  • 高速な読み書き
    テキスト形式に比べて解析のオーバーヘッドが少ないため、高速に読み書きできる。

デメリット

  • 手動での実装
    シリアライズ(オブジェクトをバイナリに変換)とデシリアライズ(バイナリをオブジェクトに変換)のロジックをすべて自分で実装する必要がある。
  • デバッグの困難さ
    人間が内容を読み取れないため、デバッグや手動での編集が非常に困難。
  • 移植性の問題
    異なるOSやCPUアーキテクチャ間でバイナリ形式の互換性を確保するのが難しい場合がある。

関連するQtクラス

  • QFile: ファイルI/O。
  • QDataStream: Qtの型をバイナリ形式で効率的に読み書きするためのクラス。

メリット

  • 一貫性の確保
    設定がメモリ上に一元管理されるため、アプリケーション全体で常に最新かつ一貫した設定を参照できる。
  • シンプルなAPI
    独自のgetter/setterメソッドを定義することで、アプリケーション固有の使いやすいAPIを提供できる。
  • 高速なアクセス
    メモリ上のデータに直接アクセスするため、設定の読み書きが非常に高速。

デメリット

  • スレッドセーフティ
    マルチスレッド環境で設定を更新する場合、排他制御(ミューテックスなど)を考慮する必要がある。
  • 永続化の責任
    起動時と終了時のファイルI/Oのロジックを自分で実装する必要がある。
  • クラッシュ時のデータ損失
    アプリケーションが予期せず終了した場合、最後にファイルに保存された以降の変更は失われる可能性がある。
// シングルトン設定マネージャーの概念
#include <QApplication>
#include <QSettings> // 例として、QSettingsを内部的に使う場合
#include <QDebug>
#include <QMutex> // スレッドセーフティのため

class AppSettings {
public:
    static AppSettings* instance() {
        if (!s_instance) {
            s_instance = new AppSettings();
        }
        return s_instance;
    }

    void load() {
        QSettings settings; // QCoreApplication::setApplicationName() を使って設定
        m_userName = settings.value("user/name", "Default User").toString();
        m_autoSaveInterval = settings.value("app/autoSaveInterval", 5).toInt();
        qDebug() << "Settings loaded into memory.";
    }

    void save() {
        QSettings settings;
        settings.setValue("user/name", m_userName);
        settings.setValue("app/autoSaveInterval", m_autoSaveInterval);
        settings.sync(); // 強制的にディスクに書き込む
        qDebug() << "Settings saved from memory to disk.";
    }

    QString userName() const { return m_userName; }
    void setUserName(const QString& name) { m_userName = name; }

    int autoSaveInterval() const { return m_autoSaveInterval; }
    void setAutoSaveInterval(int interval) { m_autoSaveInterval = interval; }

private:
    AppSettings() {} // コンストラクタをprivateにしてシングルトンを強制
    ~AppSettings() {} // デストラクタもprivateにすることでdeleteできないようにする

    static AppSettings* s_instance;
    QString m_userName;
    int m_autoSaveInterval;
    // QMutex m_mutex; // マルチスレッド対応が必要なら追加
};

AppSettings* AppSettings::s_instance = nullptr;

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    QCoreApplication::setOrganizationName("MyCompany");
    QCoreApplication::setApplicationName("MyAppSingleton");

    // アプリケーション起動時に設定を読み込む
    AppSettings::instance()->load();

    // メモリ上の設定値を変更
    qDebug() << "Current user name:" << AppSettings::instance()->userName();
    AppSettings::instance()->setUserName("New User");
    qDebug() << "New user name:" << AppSettings::instance()->userName();

    // アプリケーション終了時に設定を保存する(例として)
    // 通常はQApplication::aboutToQuit()シグナルに接続するなどして呼び出す
    AppSettings::instance()->save();

    return 0;
}