From 063388e0eb6113d617a437ec5ef0f52fb601cdc1 Mon Sep 17 00:00:00 2001 From: dteviot Date: Sat, 10 Jan 2015 15:04:45 +1300 Subject: [PATCH 1/3] Change "Profile" to "Content List" in user visible strings in Launcher. (Fixes #810) --- apps/launcher/datafilespage.cpp | 10 +++++----- apps/launcher/settingspage.cpp | 2 +- files/ui/datafilespage.ui | 18 +++++++++--------- files/ui/playpage.ui | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index a0ef97ff9..8fca73c89 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -30,7 +30,7 @@ Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config: setObjectName ("DataFilesPage"); mSelector = new ContentSelectorView::ContentSelector (ui.contentSelectorWidget); - mProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this); + mProfileDialog = new TextInputDialog(tr("New Content List"), tr("Content List name:"), this); connect(mProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString))); @@ -44,12 +44,12 @@ void Launcher::DataFilesPage::buildView() ui.verticalLayout->insertWidget (0, mSelector->uiWidget()); //tool buttons - ui.newProfileButton->setToolTip ("Create a new profile"); - ui.deleteProfileButton->setToolTip ("Delete an existing profile"); + ui.newProfileButton->setToolTip ("Create a new Content List"); + ui.deleteProfileButton->setToolTip ("Delete an existing Content List"); //combo box ui.profilesComboBox->addItem ("Default"); - ui.profilesComboBox->setPlaceholderText (QString("Select a profile...")); + ui.profilesComboBox->setPlaceholderText (QString("Select a Content List...")); ui.profilesComboBox->setCurrentIndex(ui.profilesComboBox->findText(QLatin1String("Default"))); // Add the actions to the toolbuttons @@ -306,7 +306,7 @@ void Launcher::DataFilesPage::checkForDefaultProfile() bool Launcher::DataFilesPage::showDeleteMessageBox (const QString &text) { QMessageBox msgBox(this); - msgBox.setWindowTitle(tr("Delete Profile")); + msgBox.setWindowTitle(tr("Delete Content List")); msgBox.setIcon(QMessageBox::Warning); msgBox.setStandardButtons(QMessageBox::Cancel); msgBox.setText(tr("Are you sure you want to delete %0?").arg(text)); diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp index 5422e7957..26908746b 100644 --- a/apps/launcher/settingspage.cpp +++ b/apps/launcher/settingspage.cpp @@ -51,7 +51,7 @@ Launcher::SettingsPage::SettingsPage(Files::ConfigurationManager &cfg, connect(mImporterInvoker->getProcess(), SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(importerFinished(int,QProcess::ExitStatus))); - mProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this); + mProfileDialog = new TextInputDialog(tr("New Content List"), tr("Content List name:"), this); connect(mProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString))); diff --git a/files/ui/datafilespage.ui b/files/ui/datafilespage.ui index eb5ebc61d..5a6b7265a 100644 --- a/files/ui/datafilespage.ui +++ b/files/ui/datafilespage.ui @@ -29,7 +29,7 @@ Qt::NoFocus - Profile + Content List false @@ -69,10 +69,10 @@ - New Profile + New Content List - &New Profile + &New Content List true @@ -82,10 +82,10 @@ - Delete Profile + Delete Content List - Delete Profile + Delete Content List Ctrl+D @@ -106,10 +106,10 @@ - New Profile + New Content List - New Profile + New Content List Ctrl+N @@ -125,10 +125,10 @@ - Delete Profile + Delete Content List - Delete Profile + Delete Content List diff --git a/files/ui/playpage.ui b/files/ui/playpage.ui index bf883b96e..1d529e2d7 100644 --- a/files/ui/playpage.ui +++ b/files/ui/playpage.ui @@ -101,7 +101,7 @@ - Current Profile: + Current Content List: From 05b89be8bfc19a653287a90b05eb54f63b8a5609 Mon Sep 17 00:00:00 2001 From: dteviot Date: Sat, 10 Jan 2015 18:46:47 +1300 Subject: [PATCH 2/3] Launcher sets content list to match values in openmw.cfg (Fixes #811) I took the liberty to add accessor & mutator functions for classes ContentListsGameSettings and LauncherSettings , as existing code can reverse order of entries. Also replaced some "magic strings" with named constants. --- apps/launcher/datafilespage.cpp | 31 +++--- apps/launcher/maindialog.cpp | 10 +- apps/launcher/settingspage.cpp | 17 +--- apps/wizard/mainwizard.cpp | 4 +- components/config/gamesettings.cpp | 30 ++++-- components/config/gamesettings.hpp | 7 +- components/config/launchersettings.cpp | 134 +++++++++++++++++++++---- components/config/launchersettings.hpp | 45 ++++++++- components/config/settingsbase.hpp | 4 +- 9 files changed, 208 insertions(+), 74 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 8fca73c89..8429aaadc 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -82,8 +82,8 @@ bool Launcher::DataFilesPage::loadSettings() paths.insert (0, mDataLocal); PathIterator pathIterator (paths); - QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); - QString currentProfile = mLauncherSettings.getSettings().value("Profiles/currentprofile"); + QStringList profiles = mLauncherSettings.getContentLists(); + QString currentProfile = mLauncherSettings.getCurrentContentListName(); qDebug() << "current profile is: " << currentProfile; @@ -101,15 +101,12 @@ bool Launcher::DataFilesPage::loadSettings() QStringList Launcher::DataFilesPage::filesInProfile(const QString& profileName, PathIterator& pathIterator) { - QStringList files = mLauncherSettings.values(QString("Profiles/") + profileName + QString("/content"), Qt::MatchExactly); + QStringList files = mLauncherSettings.getContentListFiles(profileName); QStringList filepaths; - // mLauncherSettings.values() returns the files in reverse load order - QListIterator i(files); - i.toBack(); - while (i.hasPrevious()) + foreach(const QString& file, files) { - QString filepath = pathIterator.findFirstPath(i.previous()); + QString filepath = pathIterator.findFirstPath(file); if (!filepath.isEmpty()) filepaths << filepath; @@ -128,24 +125,20 @@ void Launcher::DataFilesPage::saveSettings(const QString &profile) //retrieve the files selected for the profile ContentSelectorModel::ContentFileList items = mSelector->selectedFiles(); - removeProfile (profileName); - - mGameSettings.remove(QString("content")); - //set the value of the current profile (not necessarily the profile being saved!) - mLauncherSettings.setValue(QString("Profiles/currentprofile"), ui.profilesComboBox->currentText()); + mLauncherSettings.setCurrentContentListName(ui.profilesComboBox->currentText()); + QStringList fileNames; foreach(const ContentSelectorModel::EsmFile *item, items) { - mLauncherSettings.setMultiValue(QString("Profiles/") + profileName + QString("/content"), item->fileName()); - mGameSettings.setMultiValue(QString("content"), item->fileName()); + fileNames.append(item->fileName()); } - + mLauncherSettings.setContentList(profileName, fileNames); + mGameSettings.setContentList(fileNames); } void Launcher::DataFilesPage::removeProfile(const QString &profile) { - mLauncherSettings.remove(QString("Profiles/") + profile); - mLauncherSettings.remove(QString("Profiles/") + profile + QString("/content")); + mLauncherSettings.removeContentList(profile); } QAbstractItemModel *Launcher::DataFilesPage::profilesModel() const @@ -233,7 +226,7 @@ void Launcher::DataFilesPage::on_newProfileAction_triggered() saveSettings(); - mLauncherSettings.setValue(QString("Profiles/currentprofile"), profile); + mLauncherSettings.setCurrentContentListName(profile); addProfile(profile, true); mSelector->clearCheckStates(); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 975958d7a..00c549969 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -209,6 +209,8 @@ bool Launcher::MainDialog::setup() if (!setupGameSettings()) return false; + mLauncherSettings.setContentList(mGameSettings); + if (!setupGraphicsSettings()) return false; @@ -232,6 +234,8 @@ bool Launcher::MainDialog::reloadSettings() if (!setupGameSettings()) return false; + mLauncherSettings.setContentList(mGameSettings); + if (!setupGraphicsSettings()) return false; @@ -280,8 +284,8 @@ bool Launcher::MainDialog::setupLauncherSettings() QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); QStringList paths; - paths.append(QString("launcher.cfg")); - paths.append(userPath + QString("launcher.cfg")); + paths.append(QString(Config::LauncherSettings::sLauncherConfigFileName)); + paths.append(userPath + QString(Config::LauncherSettings::sLauncherConfigFileName)); foreach (const QString &path, paths) { qDebug() << "Loading config file:" << qPrintable(path); @@ -562,7 +566,7 @@ bool Launcher::MainDialog::writeSettings() file.close(); // Launcher settings - file.setFileName(userPath + QString("launcher.cfg")); + file.setFileName(userPath + QString(Config::LauncherSettings::sLauncherConfigFileName)); if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { // File cannot be opened or created diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp index 26908746b..ace8f4310 100644 --- a/apps/launcher/settingspage.cpp +++ b/apps/launcher/settingspage.cpp @@ -207,18 +207,9 @@ void Launcher::SettingsPage::importerFinished(int exitCode, QProcess::ExitStatus if (mProfileDialog->exec() == QDialog::Accepted) { const QString profile(mProfileDialog->lineEdit()->text()); - const QStringList files(mGameSettings.values(QLatin1String("content"))); - - qDebug() << "Profile " << profile << files; - - // Doesn't quite work right now - mLauncherSettings.setValue(QLatin1String("Profiles/currentprofile"), profile); - - foreach (const QString &file, files) { - mLauncherSettings.setMultiValue(QLatin1String("Profiles/") + profile + QLatin1String("/content"), file); - } - - mGameSettings.remove(QLatin1String("content")); + const QStringList files(mGameSettings.getContentList()); + mLauncherSettings.setCurrentContentListName(profile); + mLauncherSettings.setContentList(profile, files); } } @@ -234,7 +225,7 @@ void Launcher::SettingsPage::updateOkButton(const QString &text) return; } - const QStringList profiles(mLauncherSettings.subKeys(QString("Profiles/"))); + const QStringList profiles(mLauncherSettings.getContentLists()); (profiles.contains(text)) ? mProfileDialog->setOkButtonEnabled(false) diff --git a/apps/wizard/mainwizard.cpp b/apps/wizard/mainwizard.cpp index e68070c4d..9a8ec2056 100644 --- a/apps/wizard/mainwizard.cpp +++ b/apps/wizard/mainwizard.cpp @@ -182,7 +182,7 @@ void Wizard::MainWizard::setupGameSettings() void Wizard::MainWizard::setupLauncherSettings() { QString path(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str())); - path.append(QLatin1String("launcher.cfg")); + path.append(QLatin1String(Config::LauncherSettings::sLauncherConfigFileName)); QString message(tr("

Could not open %1 for reading

\

Please make sure you have the right permissions \ @@ -427,7 +427,7 @@ void Wizard::MainWizard::writeSettings() file.close(); // Launcher settings - file.setFileName(userPath + QLatin1String("launcher.cfg")); + file.setFileName(userPath + QLatin1String(Config::LauncherSettings::sLauncherConfigFileName)); if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { // File cannot be opened or created diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index 1e7f716e2..0481235c7 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -1,4 +1,5 @@ #include "gamesettings.hpp" +#include "launchersettings.hpp" #include #include @@ -26,6 +27,7 @@ namespace boost } /* namespace boost */ #endif /* (BOOST_VERSION <= 104600) */ +const char Config::GameSettings::sContentKey[] = "content"; Config::GameSettings::GameSettings(Files::ConfigurationManager &cfg) : mCfgMgr(cfg) @@ -81,7 +83,7 @@ void Config::GameSettings::validatePaths() } } -QStringList Config::GameSettings::values(const QString &key, const QStringList &defaultValues) +QStringList Config::GameSettings::values(const QString &key, const QStringList &defaultValues) const { if (!mSettings.values(key).isEmpty()) return mSettings.values(key); @@ -149,9 +151,6 @@ bool Config::GameSettings::writeFile(QTextStream &stream) while (i.hasPrevious()) { i.previous(); - if (i.key() == QLatin1String("content")) - continue; - // Quote paths with spaces if (i.key() == QLatin1String("data") || i.key() == QLatin1String("data-local") @@ -171,18 +170,13 @@ bool Config::GameSettings::writeFile(QTextStream &stream) } - QStringList content = mUserSettings.values(QString("content")); - for (int i = content.count(); i--;) { - stream << "content=" << content.at(i) << "\n"; - } - return true; } bool Config::GameSettings::hasMaster() { bool result = false; - QStringList content = mSettings.values(QString("content")); + QStringList content = mSettings.values(QString(Config::GameSettings::sContentKey)); for (int i = 0; i < content.count(); ++i) { if (content.at(i).contains(".omwgame") || content.at(i).contains(".esm")) { result = true; @@ -192,3 +186,19 @@ bool Config::GameSettings::hasMaster() return result; } + +void Config::GameSettings::setContentList(const QStringList& fileNames) +{ + remove(sContentKey); + foreach(const QString& fileName, fileNames) + { + setMultiValue(sContentKey, fileName); + } +} + +QStringList Config::GameSettings::getContentList() const +{ + // QMap returns multiple rows in LIFO order, so need to reverse + return Config::LauncherSettings::reverse(values(sContentKey)); +} + diff --git a/components/config/gamesettings.hpp b/components/config/gamesettings.hpp index c4a6ead79..cc5033f35 100644 --- a/components/config/gamesettings.hpp +++ b/components/config/gamesettings.hpp @@ -59,7 +59,7 @@ namespace Config bool hasMaster(); - QStringList values(const QString &key, const QStringList &defaultValues = QStringList()); + QStringList values(const QString &key, const QStringList &defaultValues = QStringList()) const; bool readFile(QTextStream &stream); bool readFile(QTextStream &stream, QMap &settings); @@ -67,6 +67,9 @@ namespace Config bool writeFile(QTextStream &stream); + void setContentList(const QStringList& fileNames); + QStringList getContentList() const; + private: Files::ConfigurationManager &mCfgMgr; @@ -76,6 +79,8 @@ namespace Config QStringList mDataDirs; QString mDataLocal; + + static const char sContentKey[]; }; } #endif // GAMESETTINGS_HPP diff --git a/components/config/launchersettings.cpp b/components/config/launchersettings.cpp index c014579dc..66f05f691 100644 --- a/components/config/launchersettings.cpp +++ b/components/config/launchersettings.cpp @@ -7,6 +7,11 @@ #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::sContentListSuffix[] = "/content"; + Config::LauncherSettings::LauncherSettings() { } @@ -15,27 +20,6 @@ Config::LauncherSettings::~LauncherSettings() { } -QStringList Config::LauncherSettings::values(const QString &key, Qt::MatchFlags flags) -{ - QMap settings = SettingsBase::getSettings(); - - if (flags == Qt::MatchExactly) - return settings.values(key); - - QStringList result; - - if (flags == Qt::MatchStartsWith) { - QStringList keys = settings.keys(); - - foreach (const QString ¤tKey, keys) { - if (currentKey.startsWith(key)) - result.append(settings.value(currentKey)); - } - } - - return result; -} - QStringList Config::LauncherSettings::subKeys(const QString &key) { QMap settings = SettingsBase::getSettings(); @@ -66,6 +50,7 @@ QStringList Config::LauncherSettings::subKeys(const QString &key) return result; } + bool Config::LauncherSettings::writeFile(QTextStream &stream) { QString sectionPrefix; @@ -104,3 +89,110 @@ bool Config::LauncherSettings::writeFile(QTextStream &stream) return true; } + +QStringList Config::LauncherSettings::getContentLists() +{ + return subKeys(QString(sContentListsSectionPrefix)); +} + +QString Config::LauncherSettings::makeContentListKey(const QString& contentListName) +{ + return QString(sContentListsSectionPrefix) + contentListName + QString(sContentListSuffix); +} + +void Config::LauncherSettings::setContentList(const GameSettings& gameSettings) +{ + // obtain content list from game settings (if present) + const QStringList files(gameSettings.getContentList()); + + // if any existing profile in launcher matches the content list, make that profile the default + foreach(const QString &listName, getContentLists()) + { + if (isEqual(files, getContentListFiles(listName))) + { + setCurrentContentListName(listName); + return; + } + } + + // otherwise, add content list + QString newContentListName(makeNewContentListName()); + setCurrentContentListName(newContentListName); + setContentList(newContentListName, files); +} + +void Config::LauncherSettings::removeContentList(const QString &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& fileNames) +{ + removeContentList(contentListName); + QString key = makeContentListKey(contentListName); + foreach(const QString& fileName, fileNames) + { + setMultiValue(key, fileName); + } +} + +QString Config::LauncherSettings::getCurrentContentListName() const +{ + return value(QString(sCurrentContentListKey)); +} + +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))); +} + +QStringList Config::LauncherSettings::reverse(const QStringList& toReverse) +{ + QStringList result; + result.reserve(toReverse.size()); + std::reverse_copy(toReverse.begin(), toReverse.end(), std::back_inserter(result)); + return result; +} + +bool Config::LauncherSettings::isEqual(const QStringList& list1, const QStringList& list2) +{ + if (list1.count() != list2.count()) + { + return false; + } + + for (int i = 0; i < list1.count(); ++i) + { + if (list1.at(i) != list2.at(i)) + { + return false; + } + } + + // if get here, lists are same + return true; +} + +QString Config::LauncherSettings::makeNewContentListName() +{ + // basically, use date and time as the name e.g. YYYY-MM-DDThh:mm:ss + time_t rawtime; + struct tm * timeinfo; + + time(&rawtime); + timeinfo = localtime(&rawtime); + 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); +} + + diff --git a/components/config/launchersettings.hpp b/components/config/launchersettings.hpp index 042823ca9..cbe21c54a 100644 --- a/components/config/launchersettings.hpp +++ b/components/config/launchersettings.hpp @@ -2,6 +2,7 @@ #define LAUNCHERSETTINGS_HPP #include "settingsbase.hpp" +#include "gamesettings.hpp" namespace Config { @@ -11,11 +12,49 @@ namespace Config LauncherSettings(); ~LauncherSettings(); - QStringList subKeys(const QString &key); - QStringList values(const QString &key, Qt::MatchFlags flags = Qt::MatchExactly); - bool writeFile(QTextStream &stream); + /// \return names of all Content Lists in the launcher's .cfg file. + QStringList getContentLists(); + + /// Set initally selected content list to match values from openmw.cfg, creating if necessary + void setContentList(const GameSettings& gameSettings); + + /// Create a Content List (or replace if it already exists) + void setContentList(const QString& contentListName, const QStringList& fileNames); + + void removeContentList(const QString &contentListName); + + void setCurrentContentListName(const QString &contentListName); + + QString getCurrentContentListName() const; + + QStringList getContentListFiles(const QString& contentListName) const; + + /// \return new list that is reversed order of input + static QStringList reverse(const QStringList& toReverse); + + static const char sLauncherConfigFileName[]; + + private: + + /// \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 sContentListSuffix[]; }; } #endif // LAUNCHERSETTINGS_HPP diff --git a/components/config/settingsbase.hpp b/components/config/settingsbase.hpp index e6b0908e0..c798d2893 100644 --- a/components/config/settingsbase.hpp +++ b/components/config/settingsbase.hpp @@ -17,7 +17,7 @@ namespace Config SettingsBase() { mMultiValue = false; } ~SettingsBase() {} - inline QString value(const QString &key, const QString &defaultValue = QString()) + inline QString value(const QString &key, const QString &defaultValue = QString()) const { return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key); } @@ -46,7 +46,7 @@ namespace Config mSettings.remove(key); } - Map getSettings() {return mSettings;} + Map getSettings() const {return mSettings;} bool readFile(QTextStream &stream) { From fcbf7d7deb602456f7140ebe68be428903d9371f Mon Sep 17 00:00:00 2001 From: dteviot Date: Sun, 11 Jan 2015 08:33:33 +1300 Subject: [PATCH 3/3] Fixed string formatting minor error found by Mingun. --- apps/launcher/datafilespage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 8429aaadc..245665421 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -302,7 +302,7 @@ bool Launcher::DataFilesPage::showDeleteMessageBox (const QString &text) msgBox.setWindowTitle(tr("Delete Content List")); msgBox.setIcon(QMessageBox::Warning); msgBox.setStandardButtons(QMessageBox::Cancel); - msgBox.setText(tr("Are you sure you want to delete %0?").arg(text)); + msgBox.setText(tr("Are you sure you want to delete %1?").arg(text)); QAbstractButton *deleteButton = msgBox.addButton(tr("Delete"), QMessageBox::ActionRole);