Запретить QSettings от добавления имени организации к пути, установленному QSettings :: setPath () - PullRequest
0 голосов
/ 02 марта 2019

Есть ли способ установить фактический путь по умолчанию для 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 для сохранения настроек в определенном месте.Пользовательский код не должен знать об изменении места хранения.В идеале установите QSettings в main и используйте объекты, созданные в дальнейшем с помощью конструктора по умолчанию.

Я обнаружил, что только конструктор 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 подвержено ошибкам, потому что Qt добавляет некоторую «магию», такую ​​как имя организации, к «путь к производному fileName, и это «волшебство» на самом деле не задокументировано).

Итак, единственное решение, которое я придумал, это:

  1. Создание фабрики, которая знаетпереносимость приложения, создает объект QSettings в куче с соответствующим конструктором и возвращает указатель на него.У этого есть обратная сторона необходимости управлять памятью этого динамически сконструированного объекта, следовательно, необоснованно добавленная сложность.Кроме того, он добавляет еще одну сущность, которая зависит от переносимости приложения.
  2. Делаем, как указано выше, но с одиночным.Это также добавляет лишнюю сложность при решении очень простой проблемы.Также в этом случае объект QSettings будет существовать в течение всего времени жизни приложения.

Так что у меня есть ощущение, что я определенно что-то здесь упускаю, и мне интересно, есть ли более простое решение для этогопроблема.

Примечание: в настоящее время я решил эту проблему, установив название своей организации на «настройки», если приложение переносное, поэтому настройки приложения хранятся в файле APP_FOLDER / settings / APP_NAME.ini.Грязный хак, но спасает много сложности.Во всяком случае, я нигде не использую название организации.

1 Ответ

0 голосов
/ 02 марта 2019

Насколько я понимаю, вы, по сути, хотите, чтобы 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]
...