防止 QSettings 将组织名称添加到 QSettings::setPath() 设置的路径中
Prevent QSettings from adding organization name to the path set by QSettings::setPath()
有没有办法设置 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
;从fileName导出"path"容易出错因为 Qt 添加了一些 "magic",比如那个组织名称,到 "path" 派生文件名,而 "magic" 并没有真正记录)。
所以我想到的唯一解决方案是:
- 创建一个了解应用程序可移植性的工厂,
使用适当的方法在堆上构造一个
QSettings
对象
构造函数,returns 指向它的指针。这有一个缺点
必须管理那个动态构造的对象的内存,
因此不合理地增加了复杂性。它还添加了另一个实体
这取决于应用程序的可移植性。
- 如上所述,但使用单例。这也增加了多余的
复杂性,同时解决简单的问题。同样在这种情况下
QSettings
对象将在整个应用程序生命周期内存在。
所以我觉得我肯定在这里遗漏了一些东西,我想知道是否有更简单的解决方案来解决这个问题。
旁注:目前我通过将我的组织名称设置为 "settings"(如果该应用程序是可移植的)来解决此问题,因此应用程序设置存储在 APP_FOLDER/settings/APP_NAME.ini 中。一个肮脏的黑客,但节省了很多复杂性。无论如何,我真的不会在任何地方使用组织名称。
我的理解是,您本质上希望 QSettings
根据是否已设置特定路径以两种方式之一构建。
您可以创建一个 class,而不是从 QSettings
继承,它带有指向成员 ->
运算符的重载指针,returns 指向 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/values...
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]
有没有办法设置 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
;从fileName导出"path"容易出错因为 Qt 添加了一些 "magic",比如那个组织名称,到 "path" 派生文件名,而 "magic" 并没有真正记录)。
所以我想到的唯一解决方案是:
- 创建一个了解应用程序可移植性的工厂,
使用适当的方法在堆上构造一个
QSettings
对象 构造函数,returns 指向它的指针。这有一个缺点 必须管理那个动态构造的对象的内存, 因此不合理地增加了复杂性。它还添加了另一个实体 这取决于应用程序的可移植性。 - 如上所述,但使用单例。这也增加了多余的
复杂性,同时解决简单的问题。同样在这种情况下
QSettings
对象将在整个应用程序生命周期内存在。
所以我觉得我肯定在这里遗漏了一些东西,我想知道是否有更简单的解决方案来解决这个问题。
旁注:目前我通过将我的组织名称设置为 "settings"(如果该应用程序是可移植的)来解决此问题,因此应用程序设置存储在 APP_FOLDER/settings/APP_NAME.ini 中。一个肮脏的黑客,但节省了很多复杂性。无论如何,我真的不会在任何地方使用组织名称。
我的理解是,您本质上希望 QSettings
根据是否已设置特定路径以两种方式之一构建。
您可以创建一个 class,而不是从 QSettings
继承,它带有指向成员 ->
运算符的重载指针,returns 指向 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/values...
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]