防止QSettings将组织名称添加到QSettings :: setPath()

时间:2019-03-02 08:43:02

标签: c++ qt qt5 qsettings

是否可以设置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设置为默认路径(如果尚未设置)的情况,因为无法获得默认的{ {1}}存储路径(有QSettings,但没有setPath;有getPath,没有getFileName;从fileName派生“路径”很容易出错,因为Qt将一些“魔术”(如组织名称)添加到“路径”以派生fileName,而该“魔术”并未真正记录下来。)

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

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

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

旁注:当前,我通过将组织名称设置为“ settings”(如果应用程序是便携式的)来解决此问题,因此应用程序设置存储在APP_FOLDER / settings / APP_NAME.ini中。肮脏的hack,但可以节省很多复杂性。我真的没有在任何地方使用组织名称。

1 个答案:

答案 0 :(得分: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]