【问题标题】:Prevent QSettings from adding organization name to the path set by QSettings::setPath()防止 QSettings 将组织名称添加到 QSettings::setPath() 设置的路径中
【发布时间】:2019-03-02 08:43:01
【问题描述】:

有没有办法设置QSettings 存储的实际默认路径(带或不带文件名),并防止QSettings 将组织名称等内容附加到该路径?这要求QSettings 的进一步用法保持不变并且不知道设置存储路径。

考虑用例。在我的主要我有以下代码:

QApplication a(argc, argv);

...

QCoreApplication::setApplicationName(APP_NAME);
QCoreApplication::setOrganizationDomain(MY_DOMAIN);
QCoreApplication::setOrganizationName(MY_ORGANIZATION);
QCoreApplication::setApplicationVersion(APP_VERSION);

...

a.exec();

在我的整个项目中,我都像这样使用QSettings

QSettings settings;

settings.setValue(somePath, someValue);

someOtherValue = settings.value(someOtherPath, someDefault);

现在我需要使应用程序可移植。所以我将 main 中的代码更改为:

QApplication a(argc, argv);

...

QCoreApplication::setApplicationName(APP_NAME);
QCoreApplication::setOrganizationDomain(MY_DOMAIN);
QCoreApplication::setOrganizationName(MY_ORGANIZATION);
QCoreApplication::setApplicationVersion(APP_VERSION);

if (PORTABLE) {
    QSettings::setDefaultFormat(QSettings::IniFormat);
    QString settingsPath = a.applicationDirPath() + "/settings";
    QSettings::setPath(QSettings::defaultFormat(), QSettings::UserScope, settingsPath);
    QSettings::setPath(QSettings::defaultFormat(), QSettings::SystemScope, settingsPath);
}

...

a.exec();

但是设置不是写入APP_PATH/settings/,实际位置变成APP_PATH/settings/ORGANIZATION_NAME/,在我看来这有点太丑了。

我想设置QSettings 将设置存储在特定位置。用户代码必须不知道存储位置的变化。理想情况下,在 main 中设置 QSettings,并使用对象,进一步使用默认构造函数构造。

我发现只有QSettings(const QString &fileName, QSettings::Format format, QObject *parent = nullptr)构造函数才能真正设置存储位置。所有其他构造函数不断向路径添加内容。由于我不希望用户代码了解应用程序的可移植性,因此每次都使用不同的构造函数不是一种选择。

我想过子类化QSettings 有点像这样来修复setPath()

class Settings : public QSettings {
private:
    static QString mPath = "";

public:
    Settings(QObject *parent = nullptr) :
        QSettings(
            mPath.isEmpty() ? 
            QSettings() : 
            QSettings(mPath, Settings::defaultFormat, parent)
        )
    {}

    static void setPath(QSettings::Format format, QSettings::Scope scope, const QString &path)
    {
        mPath = path;
        QSettings::setPath(format, scope, path);
    }
} 

但这是不可能的,因为QSettings 没有复制构造函数。在每种情况下都使用QSettings(mPath, Settings::defaultFormat, parent) 构建基础,但是将mPath 设置为默认路径以防它尚未设置,也不能这样做,因为没有方法获得默认的QSettings 存储路径(有setPath,但没有getPath;有getFileName,没有setFileName;从文件名派生“路径”容易出错,因为Qt在“路径”来派生文件名,而“魔法”并没有真正记录下来)。

所以我想出的唯一解决方案是:

  1. 创建了解应用程序可移植性的工厂, 在堆上构造一个 QSettings 对象,并使用适当的 构造函数,并返回一个指向它的指针。这有一个缺点 必须管理该动态构造对象的内存, 因此不合理地增加了复杂性。它还添加了另一个实体 这取决于应用程序的可移植性。
  2. 如上所述,但使用单例。这也增加了多余的 复杂性,同时解决简单的问题。同样在这种情况下 QSettings 对象将存在于整个应用程序生命周期中。

所以我有一种感觉,我肯定在这里遗漏了一些东西,我想知道是否有更简单的解决方案来解决这个问题。

旁注:目前,如果应用程序是可移植的,我通过将组织名称设置为“设置”来解决此问题,因此应用程序设置存储在 APP_FOLDER/settings/APP_NAME.ini 中。一个肮脏的黑客,但节省了很多复杂性。无论如何,我实际上并没有在任何地方使用组织名称。

【问题讨论】:

  • 你不能只使用QSettings 构造函数来指定full path and format吗?
  • 如果工厂返回std::unique_ptr,你也不必关心内存管理......
  • @G.M.我在我的问题中提到了那个构造函数。这是一个可能的解决方案,但它要求使用设置的每一段代码都知道将它们保存在哪里。当一段代码保存到一个地方,而另一个保存到不同的地方时,它就有可能出错。此外,由于有很多地方使用了设置,它添加了很多重复的代码,例如:if (Globals::appIsPortable) {QSettings s(Globals::settingsPath, QSettings::defaultFormat); /* use settings */ } else {QSettiings s; /*use settings*/};。这可以使用宏来简化,但我不喜欢这个想法。

标签: c++ qt qt5 qsettings


【解决方案1】:

我的理解是,您本质上希望QSettings 根据是否设置了特定路径以两种方式之一构建。

您可以创建一个类,而不是从QSettings 继承,该类具有指向成员-> 运算符的重载指针,该运算符返回指向QSettings 实例的指针。这样,QSettings 的初始化可以推迟到需要时,并利用已设置的任何信息。

class settings {
public:
  static void set_path (QSettings::Format format, QSettings::Scope scope, const QString &path)
    {
      s_path = path;
      QSettings::setPath(format, scope, path);
    }
  QSettings *operator-> ()
    {
      return get_settings();
    }
private:
  QSettings *get_settings ()
    {
      if (!m_settings) {
        if (s_path.isEmpty()) {
          m_settings = std::make_unique<QSettings>();
        } else {
          m_settings = std::make_unique<QSettings>(s_path, QSettings::defaultFormat());
        }
      }
      return m_settings.get();
    }
  static QString             s_path;
  std::unique_ptr<QSettings> m_settings;
};

QString settings::s_path = "";

与默认设置/值一起使用时...

settings settings;
std::cout << "\nsettings file path is [" << settings->fileName() << "]";

上面给出了类似...

settings file path is [/home/<user>/.config/Unknown Organization/appname.conf]

使用...显式设置所需路径

settings::set_path(QSettings::defaultFormat(), QSettings::SystemScope, app.applicationDirPath() + "/settings.ini");
settings settings;
std::cout << "\nsettings file path is [" << settings->fileName() << "]";

给...

settings file path is [/home/<user>/scratch/settings.ini]

【讨论】:

    猜你喜欢
    • 2013-06-23
    • 1970-01-01
    • 2023-03-10
    • 2012-05-27
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多