From cf753632903fd15817b12750b6f1e34a90603224 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 8 Jan 2023 19:02:03 +0100 Subject: [PATCH] Typed launcher settings QMultiMap is not clear about what settings exist and it's not efficient way to access them after they are loaded. --- apps/launcher/datafilespage.cpp | 5 +- apps/launcher/maindialog.cpp | 35 +-- apps/wizard/mainwizard.cpp | 2 +- components/CMakeLists.txt | 1 - components/config/gamesettings.cpp | 15 +- components/config/launchersettings.cpp | 411 ++++++++++++++++--------- components/config/launchersettings.hpp | 99 ++++-- components/config/settingsbase.hpp | 110 ------- 8 files changed, 355 insertions(+), 323 deletions(-) delete mode 100644 components/config/settingsbase.hpp diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index bd674c9fd7..eb7917613f 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -202,8 +202,7 @@ bool Launcher::DataFilesPage::loadSettings() if (!currentProfile.isEmpty()) addProfile(currentProfile, true); - QString language(mLauncherSettings.value(QLatin1String("Settings/language"))); - int index = mSelector->languageBox()->findText(language); + const int index = mSelector->languageBox()->findText(mLauncherSettings.getLanguage()); if (index != -1) mSelector->languageBox()->setCurrentIndex(index); @@ -352,7 +351,7 @@ void Launcher::DataFilesPage::saveSettings(const QString& profile) QString language(mSelector->languageBox()->currentText()); - mLauncherSettings.setValue(QLatin1String("Settings/language"), language); + mLauncherSettings.setLanguage(language); if (language == QLatin1String("Polish")) { diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index c7ae2cc588..8e0754e999 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -132,7 +132,7 @@ Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog() } } - if (mLauncherSettings.value(QString("General/firstrun"), QString("true")) == QLatin1String("true")) + if (mLauncherSettings.isFirstRun()) { QMessageBox msgBox; msgBox.setWindowTitle(tr("First run")); @@ -289,8 +289,6 @@ bool Launcher::MainDialog::setupLauncherSettings() { mLauncherSettings.clear(); - mLauncherSettings.setMultiValueEnabled(true); - const QString path = Files::pathToQString(mCfgMgr.getUserConfigPath() / Config::LauncherSettings::sLauncherConfigFileName); @@ -438,31 +436,20 @@ bool Launcher::MainDialog::setupGraphicsSettings() void Launcher::MainDialog::loadSettings() { - int width = mLauncherSettings.value(QString("General/MainWindow/width")).toInt(); - int height = mLauncherSettings.value(QString("General/MainWindow/height")).toInt(); - - int posX = mLauncherSettings.value(QString("General/MainWindow/posx")).toInt(); - int posY = mLauncherSettings.value(QString("General/MainWindow/posy")).toInt(); - - resize(width, height); - move(posX, posY); + const auto& mainWindow = mLauncherSettings.getMainWindow(); + resize(mainWindow.mWidth, mainWindow.mHeight); + move(mainWindow.mPosX, mainWindow.mPosY); } void Launcher::MainDialog::saveSettings() { - QString width = QString::number(this->width()); - QString height = QString::number(this->height()); - - mLauncherSettings.setValue(QString("General/MainWindow/width"), width); - mLauncherSettings.setValue(QString("General/MainWindow/height"), height); - - QString posX = QString::number(this->pos().x()); - QString posY = QString::number(this->pos().y()); - - mLauncherSettings.setValue(QString("General/MainWindow/posx"), posX); - mLauncherSettings.setValue(QString("General/MainWindow/posy"), posY); - - mLauncherSettings.setValue(QString("General/firstrun"), QString("false")); + mLauncherSettings.setMainWindow(Config::LauncherSettings::MainWindow{ + .mWidth = width(), + .mHeight = height(), + .mPosX = pos().x(), + .mPosY = pos().y(), + }); + mLauncherSettings.resetFirstRun(); } bool Launcher::MainDialog::writeSettings() diff --git a/apps/wizard/mainwizard.cpp b/apps/wizard/mainwizard.cpp index c0fd1b16e1..9abb61cfd7 100644 --- a/apps/wizard/mainwizard.cpp +++ b/apps/wizard/mainwizard.cpp @@ -393,7 +393,7 @@ void Wizard::MainWizard::writeSettings() { // Write the encoding and language settings QString language(field(QLatin1String("installation.language")).toString()); - mLauncherSettings.setValue(QLatin1String("Settings/language"), language); + mLauncherSettings.setLanguage(language); if (language == QLatin1String("Polish")) { diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 405c36b18e..2357351d6e 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -370,7 +370,6 @@ if (USE_QT) add_component_qt_dir (config gamesettings launchersettings - settingsbase ) add_component_qt_dir (process diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index 67b4ed173f..00329aaa0c 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -12,6 +12,15 @@ const char Config::GameSettings::sArchiveKey[] = "fallback-archive"; const char Config::GameSettings::sContentKey[] = "content"; const char Config::GameSettings::sDirectoryKey[] = "data"; +namespace +{ + QStringList reverse(QStringList values) + { + std::reverse(values.begin(), values.end()); + return values; + } +} + Config::GameSettings::GameSettings(Files::ConfigurationManager& cfg) : mCfgMgr(cfg) { @@ -501,19 +510,19 @@ void Config::GameSettings::setContentList( QStringList Config::GameSettings::getDataDirs() const { - return Config::LauncherSettings::reverse(mDataDirs); + return reverse(mDataDirs); } QStringList Config::GameSettings::getArchiveList() const { // QMap returns multiple rows in LIFO order, so need to reverse - return Config::LauncherSettings::reverse(values(sArchiveKey)); + return reverse(values(sArchiveKey)); } QStringList Config::GameSettings::getContentList() const { // QMap returns multiple rows in LIFO order, so need to reverse - return Config::LauncherSettings::reverse(values(sContentKey)); + return reverse(values(sContentKey)); } void Config::GameSettings::clear() diff --git a/components/config/launchersettings.cpp b/components/config/launchersettings.cpp index 02a5202857..0239f2d334 100644 --- a/components/config/launchersettings.cpp +++ b/components/config/launchersettings.cpp @@ -4,104 +4,220 @@ #include #include #include +#include #include +#include #include -const char Config::LauncherSettings::sCurrentContentListKey[] = "Profiles/currentprofile"; -const char Config::LauncherSettings::sLauncherConfigFileName[] = "launcher.cfg"; -const char Config::LauncherSettings::sContentListsSectionPrefix[] = "Profiles/"; -const char Config::LauncherSettings::sDirectoryListSuffix[] = "/data"; -const char Config::LauncherSettings::sArchiveListSuffix[] = "/fallback-archive"; -const char Config::LauncherSettings::sContentListSuffix[] = "/content"; +#include "gamesettings.hpp" -QStringList Config::LauncherSettings::subKeys(const QString& key) +namespace Config { - QMultiMap settings = SettingsBase::getSettings(); - QStringList keys = settings.uniqueKeys(); - - QRegularExpression keyRe("(.+)/"); - - QStringList result; - - for (const QString& currentKey : keys) + namespace { - QRegularExpressionMatch match = keyRe.match(currentKey); - if (match.hasMatch()) - { - QString prefixedKey = match.captured(1); + constexpr char sSettingsSection[] = "Settings"; + constexpr char sGeneralSection[] = "General"; + constexpr char sProfilesSection[] = "Profiles"; + constexpr char sLanguageKey[] = "language"; + constexpr char sCurrentProfileKey[] = "currentprofile"; + constexpr char sDataKey[] = "data"; + constexpr char sArchiveKey[] = "fallback-archive"; + constexpr char sContentKey[] = "content"; + constexpr char sFirstRunKey[] = "firstrun"; + constexpr char sMainWindowWidthKey[] = "MainWindow/width"; + constexpr char sMainWindowHeightKey[] = "MainWindow/height"; + constexpr char sMainWindowPosXKey[] = "MainWindow/posx"; + constexpr char sMainWindowPosYKey[] = "MainWindow/posy"; - if (prefixedKey.startsWith(key)) + QString makeNewContentListName() + { + // basically, use date and time as the name e.g. YYYY-MM-DDThh:mm:ss + const std::time_t rawtime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + tm timeinfo{}; +#ifdef _WIN32 + (void)localtime_s(&timeinfo, &rawtime); +#else + (void)localtime_r(&rawtime, &timeinfo); +#endif + constexpr int base = 10; + QChar zeroPad('0'); + return QString("%1-%2-%3T%4:%5:%6") + .arg(timeinfo.tm_year + 1900, 4) + .arg(timeinfo.tm_mon + 1, 2, base, zeroPad) + .arg(timeinfo.tm_mday, 2, base, zeroPad) + .arg(timeinfo.tm_hour, 2, base, zeroPad) + .arg(timeinfo.tm_min, 2, base, zeroPad) + .arg(timeinfo.tm_sec, 2, base, zeroPad); + } + + bool parseBool(const QString& value, bool& out) + { + if (value == "false") { - QString subKey = prefixedKey.remove(key); - if (!subKey.isEmpty()) - result.append(subKey); + out = false; + return true; + } + if (value == "true") + { + out = true; + return true; + } + + return false; + } + + bool parseInt(const QString& value, int& out) + { + bool ok = false; + const int converted = value.toInt(&ok); + if (ok) + out = converted; + return ok; + } + + bool parseProfilePart( + const QString& key, const QString& value, std::map& profiles) + { + const int separator = key.lastIndexOf('/'); + if (separator == -1) + return false; + + const QString profileName = key.mid(0, separator); + + if (key.endsWith(sArchiveKey)) + { + profiles[profileName].mArchives.append(value); + return true; + } + if (key.endsWith(sDataKey)) + { + profiles[profileName].mData.append(value); + return true; + } + if (key.endsWith(sContentKey)) + { + profiles[profileName].mContent.append(value); + return true; + } + + return false; + } + + bool parseSettingsSection(const QString& key, const QString& value, LauncherSettings::Settings& settings) + { + if (key == sLanguageKey) + { + settings.mLanguage = value; + return true; + } + + return false; + } + + bool parseProfilesSection(const QString& key, const QString& value, LauncherSettings::Profiles& profiles) + { + if (key == sCurrentProfileKey) + { + profiles.mCurrentProfile = value; + return true; + } + + return parseProfilePart(key, value, profiles.mValues); + } + + bool parseGeneralSection(const QString& key, const QString& value, LauncherSettings::General& general) + { + if (key == sFirstRunKey) + return parseBool(value, general.mFirstRun); + if (key == sMainWindowWidthKey) + return parseInt(value, general.mMainWindow.mWidth); + if (key == sMainWindowHeightKey) + return parseInt(value, general.mMainWindow.mHeight); + if (key == sMainWindowPosXKey) + return parseInt(value, general.mMainWindow.mPosX); + if (key == sMainWindowPosYKey) + return parseInt(value, general.mMainWindow.mPosY); + + return false; + } + + template + void writeSectionHeader(const char (&name)[size], QTextStream& stream) + { + stream << "\n[" << name << "]\n"; + } + + template + void writeKeyValue(const char (&key)[size], const QString& value, QTextStream& stream) + { + stream << key << '=' << value << '\n'; + } + + template + void writeKeyValue(const char (&key)[size], bool value, QTextStream& stream) + { + stream << key << '=' << (value ? "true" : "false") << '\n'; + } + + template + void writeKeyValue(const char (&key)[size], int value, QTextStream& stream) + { + stream << key << '=' << value << '\n'; + } + + template + void writeKeyValues( + const QString& prefix, const char (&suffix)[size], const QStringList& values, QTextStream& stream) + { + for (const auto& v : values) + stream << prefix << '/' << suffix << '=' << v << '\n'; + } + + void writeSettings(const LauncherSettings::Settings& value, QTextStream& stream) + { + writeSectionHeader(sSettingsSection, stream); + writeKeyValue(sLanguageKey, value.mLanguage, stream); + } + + void writeProfiles(const LauncherSettings::Profiles& value, QTextStream& stream) + { + writeSectionHeader(sProfilesSection, stream); + writeKeyValue(sCurrentProfileKey, value.mCurrentProfile, stream); + for (auto it = value.mValues.rbegin(); it != value.mValues.rend(); ++it) + { + writeKeyValues(it->first, sArchiveKey, it->second.mArchives, stream); + writeKeyValues(it->first, sDataKey, it->second.mData, stream); + writeKeyValues(it->first, sContentKey, it->second.mContent, stream); } } - } - result.removeDuplicates(); - return result; + void writeGeneral(const LauncherSettings::General& value, QTextStream& stream) + { + writeSectionHeader(sGeneralSection, stream); + writeKeyValue(sFirstRunKey, value.mFirstRun, stream); + writeKeyValue(sMainWindowWidthKey, value.mMainWindow.mWidth, stream); + writeKeyValue(sMainWindowPosYKey, value.mMainWindow.mPosY, stream); + writeKeyValue(sMainWindowPosXKey, value.mMainWindow.mPosX, stream); + writeKeyValue(sMainWindowHeightKey, value.mMainWindow.mHeight, stream); + } + } } -bool Config::LauncherSettings::writeFile(QTextStream& stream) +void Config::LauncherSettings::writeFile(QTextStream& stream) const { - QString sectionPrefix; - QRegularExpression sectionRe("^([^/]+)/(.+)$"); - QMultiMap settings = SettingsBase::getSettings(); - - auto i = settings.end(); - while (i != settings.begin()) - { - i--; - - QString prefix; - QString key; - - QRegularExpressionMatch match = sectionRe.match(i.key()); - if (match.hasMatch()) - { - prefix = match.captured(1); - key = match.captured(2); - } - - // Get rid of legacy settings - if (key.contains(QChar('\\'))) - continue; - - if (key == QLatin1String("CurrentProfile")) - continue; - - if (sectionPrefix != prefix) - { - sectionPrefix = prefix; - stream << "\n[" << prefix << "]\n"; - } - - stream << key << "=" << i.value() << "\n"; - } - - return true; + writeSettings(mSettings, stream); + writeProfiles(mProfiles, stream); + writeGeneral(mGeneral, stream); } QStringList Config::LauncherSettings::getContentLists() { - return subKeys(QString(sContentListsSectionPrefix)); -} - -QString Config::LauncherSettings::makeDirectoryListKey(const QString& contentListName) -{ - return QString(sContentListsSectionPrefix) + contentListName + QString(sDirectoryListSuffix); -} - -QString Config::LauncherSettings::makeArchiveListKey(const QString& contentListName) -{ - return QString(sContentListsSectionPrefix) + contentListName + QString(sArchiveListSuffix); -} - -QString Config::LauncherSettings::makeContentListKey(const QString& contentListName) -{ - return QString(sContentListsSectionPrefix) + contentListName + QString(sContentListSuffix); + QStringList result; + result.reserve(mProfiles.mValues.size()); + for (const auto& [k, v] : mProfiles.mValues) + result.push_back(k); + return result; } void Config::LauncherSettings::setContentList(const GameSettings& gameSettings) @@ -126,8 +242,8 @@ void Config::LauncherSettings::setContentList(const GameSettings& gameSettings) // if any existing profile in launcher matches the content list, make that profile the default for (const QString& listName : getContentLists()) { - if (isEqual(files, getContentListFiles(listName)) && isEqual(archives, getArchiveList(listName)) - && isEqual(dirs, getDataDirectoryList(listName))) + if (files == getContentListFiles(listName) && archives == getArchiveList(listName) + && dirs == getDataDirectoryList(listName)) { setCurrentContentListName(listName); return; @@ -140,99 +256,98 @@ void Config::LauncherSettings::setContentList(const GameSettings& gameSettings) setContentList(newContentListName, dirs, archives, files); } -void Config::LauncherSettings::removeContentList(const QString& contentListName) -{ - remove(makeDirectoryListKey(contentListName)); - remove(makeArchiveListKey(contentListName)); - remove(makeContentListKey(contentListName)); -} - -void Config::LauncherSettings::setCurrentContentListName(const QString& contentListName) -{ - remove(QString(sCurrentContentListKey)); - setValue(QString(sCurrentContentListKey), contentListName); -} - void Config::LauncherSettings::setContentList(const QString& contentListName, const QStringList& dirNames, const QStringList& archiveNames, const QStringList& fileNames) { - auto const assign = [this](const QString key, const QStringList& list) { - for (auto const& item : list) - setMultiValue(key, item); - }; - - removeContentList(contentListName); - assign(makeDirectoryListKey(contentListName), dirNames); - assign(makeArchiveListKey(contentListName), archiveNames); - assign(makeContentListKey(contentListName), fileNames); -} - -QString Config::LauncherSettings::getCurrentContentListName() const -{ - return value(QString(sCurrentContentListKey)); + Profile& profile = mProfiles.mValues[contentListName]; + profile.mData = dirNames; + profile.mArchives = archiveNames; + profile.mContent = fileNames; } QStringList Config::LauncherSettings::getDataDirectoryList(const QString& contentListName) const { - // QMap returns multiple rows in LIFO order, so need to reverse - return reverse(getSettings().values(makeDirectoryListKey(contentListName))); + const Profile* profile = findProfile(contentListName); + if (profile == nullptr) + return {}; + return profile->mData; } QStringList Config::LauncherSettings::getArchiveList(const QString& contentListName) const { - // QMap returns multiple rows in LIFO order, so need to reverse - return reverse(getSettings().values(makeArchiveListKey(contentListName))); + const Profile* profile = findProfile(contentListName); + if (profile == nullptr) + return {}; + return profile->mArchives; } + QStringList Config::LauncherSettings::getContentListFiles(const QString& contentListName) const { - // QMap returns multiple rows in LIFO order, so need to reverse - return reverse(getSettings().values(makeContentListKey(contentListName))); + const Profile* profile = findProfile(contentListName); + if (profile == nullptr) + return {}; + return profile->mContent; } -QStringList Config::LauncherSettings::reverse(const QStringList& toReverse) +bool Config::LauncherSettings::setValue(const QString& sectionPrefix, const QString& key, const QString& value) { - QStringList result; - result.reserve(toReverse.size()); - std::reverse_copy(toReverse.begin(), toReverse.end(), std::back_inserter(result)); - return result; + if (sectionPrefix == sSettingsSection) + return parseSettingsSection(key, value, mSettings); + if (sectionPrefix == sProfilesSection) + return parseProfilesSection(key, value, mProfiles); + if (sectionPrefix == sGeneralSection) + return parseGeneralSection(key, value, mGeneral); + + return false; } -bool Config::LauncherSettings::isEqual(const QStringList& list1, const QStringList& list2) +void Config::LauncherSettings::readFile(QTextStream& stream) { - if (list1.count() != list2.count()) - { - return false; - } + const QRegExp sectionRe("^\\[([^]]+)\\]"); + const QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); - for (int i = 0; i < list1.count(); ++i) + QString section; + + while (!stream.atEnd()) { - if (list1.at(i) != list2.at(i)) + const QString line = stream.readLine(); + + if (line.isEmpty() || line.startsWith("#")) + continue; + + if (sectionRe.exactMatch(line)) { - return false; + section = sectionRe.cap(1); + continue; } + + if (section.isEmpty()) + continue; + + if (keyRe.indexIn(line) == -1) + continue; + + const QString key = keyRe.cap(1).trimmed(); + const QString value = keyRe.cap(2).trimmed(); + + if (!setValue(section, key, value)) + Log(Debug::Warning) << "Unsupported setting in the launcher config file: section: " + << section.toUtf8().constData() << " key: " << key.toUtf8().constData() + << " value: " << value.toUtf8().constData(); } - - // if get here, lists are same - return true; } -QString Config::LauncherSettings::makeNewContentListName() +const Config::LauncherSettings::Profile* Config::LauncherSettings::findProfile(const QString& name) const { - // basically, use date and time as the name e.g. YYYY-MM-DDThh:mm:ss - auto rawtime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); - tm timeinfo{}; -#ifdef _WIN32 - (void)localtime_s(&timeinfo, &rawtime); -#else - (void)localtime_r(&rawtime, &timeinfo); -#endif - int base = 10; - QChar zeroPad('0'); - return QString("%1-%2-%3T%4:%5:%6") - .arg(timeinfo.tm_year + 1900, 4) - .arg(timeinfo.tm_mon + 1, 2, base, zeroPad) - .arg(timeinfo.tm_mday, 2, base, zeroPad) - .arg(timeinfo.tm_hour, 2, base, zeroPad) - .arg(timeinfo.tm_min, 2, base, zeroPad) - .arg(timeinfo.tm_sec, 2, base, zeroPad); + const auto it = mProfiles.mValues.find(name); + if (it == mProfiles.mValues.end()) + return nullptr; + return &it->second; +} + +void Config::LauncherSettings::clear() +{ + mSettings = Settings{}; + mGeneral = General{}; + mProfiles = Profiles{}; } diff --git a/components/config/launchersettings.hpp b/components/config/launchersettings.hpp index 8c2dc0d545..09f2218549 100644 --- a/components/config/launchersettings.hpp +++ b/components/config/launchersettings.hpp @@ -1,15 +1,59 @@ #ifndef LAUNCHERSETTINGS_HPP #define LAUNCHERSETTINGS_HPP -#include "gamesettings.hpp" -#include "settingsbase.hpp" +#include +#include + +#include + +class QTextStream; namespace Config { - class LauncherSettings : public SettingsBase> + class GameSettings; + + class LauncherSettings { public: - bool writeFile(QTextStream& stream); + static constexpr char sLauncherConfigFileName[] = "launcher.cfg"; + + struct Settings + { + QString mLanguage; + }; + + struct MainWindow + { + int mWidth = 0; + int mHeight = 0; + int mPosX = 0; + int mPosY = 0; + }; + + struct General + { + bool mFirstRun = true; + MainWindow mMainWindow; + }; + + struct Profile + { + QStringList mArchives; + QStringList mData; + QStringList mContent; + }; + + struct Profiles + { + QString mCurrentProfile; + std::map mValues; + }; + + void readFile(QTextStream& stream); + + void clear(); + + void writeFile(QTextStream& stream) const; /// \return names of all Content Lists in the launcher's .cfg file. QStringList getContentLists(); @@ -21,47 +65,36 @@ namespace Config void setContentList(const QString& contentListName, const QStringList& dirNames, const QStringList& archiveNames, const QStringList& fileNames); - void removeContentList(const QString& contentListName); + void removeContentList(const QString& value) { mProfiles.mValues.erase(value); } - void setCurrentContentListName(const QString& contentListName); + void setCurrentContentListName(const QString& value) { mProfiles.mCurrentProfile = value; } - QString getCurrentContentListName() const; + QString getCurrentContentListName() const { return mProfiles.mCurrentProfile; } QStringList getDataDirectoryList(const QString& contentListName) const; QStringList getArchiveList(const QString& contentListName) const; QStringList getContentListFiles(const QString& contentListName) const; - /// \return new list that is reversed order of input - static QStringList reverse(const QStringList& toReverse); + bool isFirstRun() const { return mGeneral.mFirstRun; } - static const char sLauncherConfigFileName[]; + void resetFirstRun() { mGeneral.mFirstRun = false; } + + QString getLanguage() const { return mSettings.mLanguage; } + + void setLanguage(const QString& value) { mSettings.mLanguage = value; } + + MainWindow getMainWindow() const { return mGeneral.mMainWindow; } + + void setMainWindow(const MainWindow& value) { mGeneral.mMainWindow = value; } private: - /// \return key to use to get/set the files in the specified data Directory List - static QString makeDirectoryListKey(const QString& contentListName); + Settings mSettings; + Profiles mProfiles; + General mGeneral; - /// \return key to use to get/set the files in the specified Archive List - static QString makeArchiveListKey(const QString& contentListName); + bool setValue(const QString& sectionPrefix, const QString& key, const QString& value); - /// \return key to use to get/set the files in the specified Content List - static QString makeContentListKey(const QString& contentListName); - - /// \return true if both lists are same - static bool isEqual(const QStringList& list1, const QStringList& list2); - - static QString makeNewContentListName(); - - QStringList subKeys(const QString& key); - - /// name of entry in launcher.cfg that holds name of currently selected Content List - static const char sCurrentContentListKey[]; - - /// section of launcher.cfg holding the Content Lists - static const char sContentListsSectionPrefix[]; - - static const char sDirectoryListSuffix[]; - static const char sArchiveListSuffix[]; - static const char sContentListSuffix[]; + const Profile* findProfile(const QString& name) const; }; } #endif // LAUNCHERSETTINGS_HPP diff --git a/components/config/settingsbase.hpp b/components/config/settingsbase.hpp deleted file mode 100644 index 068fc68d91..0000000000 --- a/components/config/settingsbase.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef SETTINGSBASE_HPP -#define SETTINGSBASE_HPP - -#include -#include -#include -#include - -namespace Config -{ - template - class SettingsBase - { - - public: - SettingsBase() { mMultiValue = false; } - ~SettingsBase() = default; - - inline QString value(const QString& key, const QString& defaultValue = QString()) const - { - return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key); - } - - inline void setValue(const QString& key, const QString& value) { mSettings.replace(key, value); } - - inline void setMultiValue(const QString& key, const QString& value) - { - QStringList values = mSettings.values(key); - if (!values.contains(value)) - mSettings.insert(key, value); - } - - inline void setMultiValueEnabled(bool enable) { mMultiValue = enable; } - - inline void remove(const QString& key) { mSettings.remove(key); } - - Map getSettings() const { return mSettings; } - - bool readFile(QTextStream& stream) - { - Map cache; - - QString sectionPrefix; - - QRegularExpression sectionRe("^\\[([^]]+)\\]$"); - QRegularExpression keyRe("^([^=]+)\\s*=\\s*(.+)$"); - - while (!stream.atEnd()) - { - QString line = stream.readLine(); - - if (line.isEmpty() || line.startsWith("#")) - continue; - - QRegularExpressionMatch sectionMatch = sectionRe.match(line); - if (sectionMatch.hasMatch()) - { - sectionPrefix = sectionMatch.captured(1); - sectionPrefix.append("/"); - continue; - } - - QRegularExpressionMatch match = keyRe.match(line); - if (match.hasMatch()) - { - QString key = match.captured(1).trimmed(); - QString value = match.captured(2).trimmed(); - - if (!sectionPrefix.isEmpty()) - key.prepend(sectionPrefix); - - mSettings.remove(key); - - QStringList values = cache.values(key); - - if (!values.contains(value)) - { - if (mMultiValue) - { - cache.insert(key, value); - } - else - { - cache.remove(key); - cache.insert(key, value); - } - } - } - } - - if (mSettings.isEmpty()) - { - mSettings = cache; // This is the first time we read a file - return true; - } - - // Merge the changed keys with those which didn't - mSettings.unite(cache); - return true; - } - - void clear() { mSettings.clear(); } - - private: - Map mSettings; - - bool mMultiValue; - }; -} -#endif // SETTINGSBASE_HPP