diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp
index a0ef97ff9..245665421 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
@@ -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();
@@ -306,10 +299,10 @@ 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));
+ msgBox.setText(tr("Are you sure you want to delete %1?").arg(text));
QAbstractButton *deleteButton =
msgBox.addButton(tr("Delete"), QMessageBox::ActionRole);
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 5422e7957..ace8f4310 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)));
@@ -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)
{
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: