From 35b68a3c400ed79762338835ef77b48b5bde95b0 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Tue, 19 Feb 2013 15:58:01 +0100 Subject: [PATCH] Fixed accidental profile deletion and added sorting by date --- apps/launcher/CMakeLists.txt | 6 ++ apps/launcher/datafilespage.cpp | 71 +++++++++++-------- apps/launcher/datafilespage.hpp | 4 +- apps/launcher/maindialog.cpp | 2 - apps/launcher/model/pluginsproxymodel.cpp | 17 +++++ apps/launcher/model/pluginsproxymodel.hpp | 18 +++++ apps/launcher/settings/gamesettings.cpp | 55 ++++++++------ apps/launcher/settings/launchersettings.cpp | 17 ++--- apps/launcher/settings/settingsbase.hpp | 2 - .../fileorderlist/model/datafilesmodel.cpp | 21 +++++- 10 files changed, 146 insertions(+), 67 deletions(-) create mode 100644 apps/launcher/model/pluginsproxymodel.cpp create mode 100644 apps/launcher/model/pluginsproxymodel.hpp diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 2c17e06b40..59cccad5fa 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -5,6 +5,8 @@ set(LAUNCHER maindialog.cpp playpage.cpp + model/pluginsproxymodel.cpp + settings/gamesettings.cpp settings/graphicssettings.cpp settings/launchersettings.cpp @@ -22,6 +24,8 @@ set(LAUNCHER_HEADER maindialog.hpp playpage.hpp + model/pluginsproxymodel.hpp + settings/gamesettings.hpp settings/graphicssettings.hpp settings/launchersettings.hpp @@ -39,6 +43,8 @@ set(LAUNCHER_HEADER_MOC maindialog.hpp playpage.hpp + model/pluginsproxymodel.hpp + utils/comboboxlineedit.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index e0ebefa589..4ecb67e4e8 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -9,6 +9,8 @@ #include #include +#include "model/pluginsproxymodel.hpp" + #include "settings/gamesettings.hpp" #include "settings/launchersettings.hpp" @@ -63,7 +65,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mMastersProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); mMastersProxyModel->setSourceModel(mDataFilesModel); - mPluginsProxyModel = new QSortFilterProxyModel(); + mPluginsProxyModel = new PluginsProxyModel(); mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp")); mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); mPluginsProxyModel->setSourceModel(mDataFilesModel); @@ -97,6 +99,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mMastersTable = new QTableView(this); mMastersTable->setModel(mMastersProxyModel); mMastersTable->setObjectName("MastersTable"); + mMastersTable->setSortingEnabled(false); mMastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); mMastersTable->setSelectionMode(QAbstractItemView::SingleSelection); mMastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers); @@ -108,19 +111,12 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mMastersTable->verticalHeader()->setDefaultSectionSize(height); mMastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); mMastersTable->verticalHeader()->hide(); - mMastersTable->setColumnHidden(1, true); - mMastersTable->setColumnHidden(2, true); - mMastersTable->setColumnHidden(3, true); - mMastersTable->setColumnHidden(4, true); - mMastersTable->setColumnHidden(5, true); - mMastersTable->setColumnHidden(6, true); - mMastersTable->setColumnHidden(7, true); - mMastersTable->setColumnHidden(8, true); mPluginsTable = new QTableView(this); mPluginsTable->setModel(mFilterProxyModel); mPluginsTable->setObjectName("PluginsTable"); mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); + mPluginsTable->setSortingEnabled(false); mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); mPluginsTable->setSelectionMode(QAbstractItemView::SingleSelection); mPluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); @@ -131,14 +127,6 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mPluginsTable->verticalHeader()->setDefaultSectionSize(height); mPluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); - mPluginsTable->setColumnHidden(1, true); - mPluginsTable->setColumnHidden(2, true); - mPluginsTable->setColumnHidden(3, true); - mPluginsTable->setColumnHidden(4, true); - mPluginsTable->setColumnHidden(5, true); - mPluginsTable->setColumnHidden(6, true); - mPluginsTable->setColumnHidden(7, true); - mPluginsTable->setColumnHidden(8, true); // Add both tables to a splitter mSplitter = new QSplitter(this); @@ -185,12 +173,11 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam connect(mMastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); connect(mPluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); + + connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews())); connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); - connect(mProfilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString))); - connect(mProfilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString))); - connect(mSplitter, SIGNAL(splitterMoved(int,int)), this, SLOT(updateSplitter())); createActions(); @@ -250,9 +237,13 @@ void DataFilesPage::setupDataFiles() mDataFilesModel->addFiles(dataLocal); } + // Sort by date accessed for now + mDataFilesModel->sort(3); + QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + mProfilesComboBox->setCurrentIndex(-1); mProfilesComboBox->addItems(profiles); // Add the current profile if empty @@ -262,12 +253,18 @@ void DataFilesPage::setupDataFiles() if (mProfilesComboBox->findText(QString("Default")) == -1) mProfilesComboBox->addItem(QString("Default")); - if (profile.isEmpty()) { + + if (profile.isEmpty() || profile == QLatin1String("Default")) { mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(QString("Default"))); } else { + mProfilesComboBox->setEditEnabled(true); mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(profile)); } + // We do this here to prevent deletion of profiles when initializing the combobox + connect(mProfilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString))); + connect(mProfilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString))); + loadSettings(); } @@ -301,10 +298,8 @@ void DataFilesPage::saveSettings() { QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); - if (profile.isEmpty()) { - profile = mProfilesComboBox->currentText(); - mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), profile); - } + if (profile.isEmpty()) + return; mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); @@ -360,6 +355,28 @@ void DataFilesPage::updateSplitter() mLauncherSettings.setValue(QString("General/PluginsTable/width"), QString::number(sizes.at(1))); } +void DataFilesPage::updateViews() +{ + // Ensure the columns are hidden because sort() re-enables them + mMastersTable->setColumnHidden(1, true); + mMastersTable->setColumnHidden(2, true); + mMastersTable->setColumnHidden(3, true); + mMastersTable->setColumnHidden(4, true); + mMastersTable->setColumnHidden(5, true); + mMastersTable->setColumnHidden(6, true); + mMastersTable->setColumnHidden(7, true); + mMastersTable->setColumnHidden(8, true); + + mPluginsTable->setColumnHidden(1, true); + mPluginsTable->setColumnHidden(2, true); + mPluginsTable->setColumnHidden(3, true); + mPluginsTable->setColumnHidden(4, true); + mPluginsTable->setColumnHidden(5, true); + mPluginsTable->setColumnHidden(6, true); + mPluginsTable->setColumnHidden(7, true); + mPluginsTable->setColumnHidden(8, true); +} + void DataFilesPage::deleteProfile() { QString profile = mProfilesComboBox->currentText(); @@ -441,7 +458,7 @@ void DataFilesPage::uncheck() void DataFilesPage::refresh() { - mDataFilesModel->sort(0); +// mDataFilesModel->sort(0); // Refresh the plugins table mPluginsTable->scrollToTop(); @@ -512,7 +529,6 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre saveSettings(); mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), current); - mDataFilesModel->uncheckAll(); loadSettings(); } @@ -532,7 +548,6 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre // Remove the profile from the combobox mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous)); - mDataFilesModel->uncheckAll(); loadSettings(); } diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index e6b4194bdc..2561aa3d17 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -18,6 +18,7 @@ class TextInputDialog; class ProfilesComboBox; class GameSettings; class LauncherSettings; +class PluginsProxyModel; namespace Files { struct ConfigurationManager; } @@ -43,6 +44,7 @@ public slots: void profileRenamed(const QString &previous, const QString ¤t); void updateOkButton(const QString &text); void updateSplitter(); + void updateViews(); // Action slots void newProfile(); @@ -58,7 +60,7 @@ public slots: private: DataFilesModel *mDataFilesModel; - QSortFilterProxyModel *mPluginsProxyModel; + PluginsProxyModel *mPluginsProxyModel; QSortFilterProxyModel *mMastersProxyModel; QSortFilterProxyModel *mFilterProxyModel; diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 7b453671c7..15f2690dad 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -206,8 +206,6 @@ void MainDialog::saveSettings() mLauncherSettings.setValue(QString("General/MainWindow/posx"), posX); mLauncherSettings.setValue(QString("General/MainWindow/posy"), posY); - - qDebug() << "size: " << width << height; } void MainDialog::writeSettings() diff --git a/apps/launcher/model/pluginsproxymodel.cpp b/apps/launcher/model/pluginsproxymodel.cpp new file mode 100644 index 0000000000..6be152b555 --- /dev/null +++ b/apps/launcher/model/pluginsproxymodel.cpp @@ -0,0 +1,17 @@ +#include "pluginsproxymodel.hpp" + +PluginsProxyModel::PluginsProxyModel(QObject *parent) : + QSortFilterProxyModel(parent) +{ +} + +PluginsProxyModel::~PluginsProxyModel() +{ +} + +QVariant PluginsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation != Qt::Vertical || role != Qt::DisplayRole) + return QSortFilterProxyModel::headerData(section, orientation, role); + return section + 1; +} diff --git a/apps/launcher/model/pluginsproxymodel.hpp b/apps/launcher/model/pluginsproxymodel.hpp new file mode 100644 index 0000000000..8fde732361 --- /dev/null +++ b/apps/launcher/model/pluginsproxymodel.hpp @@ -0,0 +1,18 @@ +#ifndef PLUGINSPROXYMODEL_HPP +#define PLUGINSPROXYMODEL_HPP + +#include + +class QVariant; + +class PluginsProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + explicit PluginsProxyModel(QObject *parent = 0); + ~PluginsProxyModel(); + + QVariant headerData(int section, Qt::Orientation orientation, int role) const; +}; + +#endif // PLUGINSPROXYMODEL_HPP diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index f87937228a..fcf6f8b8a7 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -21,8 +21,6 @@ GameSettings::~GameSettings() void GameSettings::validatePaths() { - qDebug() << "validate paths!"; - if (mSettings.isEmpty()) return; @@ -35,9 +33,6 @@ void GameSettings::validatePaths() // Parse the data dirs to convert the tokenized paths mCfgMgr.processPaths(dataDirs); - -// // Replace the existing data paths with valid untokenized ones -// mSettings.remove(QString("data")); mDataDirs.clear(); for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { @@ -59,7 +54,6 @@ void GameSettings::validatePaths() dataDirs.push_back(Files::PathContainer::value_type(local.toStdString())); mCfgMgr.processPaths(dataDirs); -// mSettings.remove(QString("data-local")); if (!dataDirs.empty()) { QString path = QString::fromStdString(dataDirs.front().string()); @@ -92,23 +86,21 @@ bool GameSettings::readFile(QTextStream &stream) if (line.isEmpty() || line.startsWith("#")) continue; - qDebug() << "line: " << line; if (keyRe.indexIn(line) != -1) { QString key = keyRe.cap(1).simplified(); QString value = keyRe.cap(2).simplified(); - qDebug() << "key: " << key; - // There can be multiple data keys - if (key == QLatin1String("data")) { + // There can be multiple keys + if (key == QLatin1String("data") || + key == QLatin1String("master") || + key == QLatin1String("plugin")) + { // Remove keys from previous config and overwrite them mSettings.remove(key); QStringList values = cache.values(key); - if (!values.contains(value)) { - // Do not insert duplicate values - qDebug() << "values does not contain: " << value << values; + if (!values.contains(value)) // Do not insert duplicate values cache.insertMulti(key, value); - } } else { cache.insert(key, value); } @@ -137,23 +129,42 @@ bool GameSettings::readFile(QTextStream &stream) // Merge the changed keys with those which didn't mSettings.unite(cache); validatePaths(); - qDebug() << mSettings; + return true; } bool GameSettings::writeFile(QTextStream &stream) { + // Iterate in reverse order to preserve insertion order QMapIterator i(mSettings); - while (i.hasNext()) { - i.next(); + i.toBack(); - // Quote values with spaces - if (i.value().contains(" ")) { - stream << i.key() << "=\"" << i.value() << "\"\n"; - } else { - stream << i.key() << "=" << i.value() << "\n"; + while (i.hasPrevious()) { + i.previous(); + + if (i.key() == QLatin1String("master") || i.key() == QLatin1String("plugin")) + continue; + + // Quote paths with spaces + if (i.key() == QLatin1String("data") || i.key() == QLatin1String("data")) { + if (i.value().contains(" ")) { + stream << i.key() << "=\"" << i.value() << "\"\n"; + continue; + } } + stream << i.key() << "=" << i.value() << "\n"; + + } + + QStringList masters = mSettings.values(QString("master")); + for (int i = masters.count(); i--;) { + stream << "master=" << masters.at(i) << "\n"; + } + + QStringList plugins = mSettings.values(QString("plugin")); + for (int i = plugins.count(); i--;) { + stream << "plugin=" << plugins.at(i) << "\n"; } return true; diff --git a/apps/launcher/settings/launchersettings.cpp b/apps/launcher/settings/launchersettings.cpp index 07502ea027..e9730c2357 100644 --- a/apps/launcher/settings/launchersettings.cpp +++ b/apps/launcher/settings/launchersettings.cpp @@ -26,7 +26,6 @@ QStringList LauncherSettings::values(const QString &key, Qt::MatchFlags flags) QStringList keys = settings.keys(); foreach (const QString ¤tKey, keys) { - qDebug() << "key is: " << currentKey << "value: " << settings.value(currentKey); if (currentKey.startsWith(key)) result.append(settings.value(currentKey)); } @@ -38,16 +37,15 @@ QStringList LauncherSettings::values(const QString &key, Qt::MatchFlags flags) QStringList LauncherSettings::subKeys(const QString &key) { QMap settings = SettingsBase::getSettings(); - QStringList keys = settings.keys(); + QStringList keys = settings.uniqueKeys(); QRegExp keyRe("(.+)/"); QStringList result; foreach (const QString ¤tKey, keys) { - qDebug() << "key is: " << currentKey; + if (keyRe.indexIn(currentKey) != -1) { - qDebug() << "text: " << keyRe.cap(1) << keyRe.cap(2); QString prefixedKey = keyRe.cap(1); if(prefixedKey.startsWith(key)) { @@ -55,16 +53,11 @@ QStringList LauncherSettings::subKeys(const QString &key) QString subKey = prefixedKey.remove(key); if (!subKey.isEmpty()) result.append(subKey); - //qDebug() << keyRe.cap(2).simplified(); } - } else { - qDebug() << "no match"; } } result.removeDuplicates(); - qDebug() << result; - return result; } @@ -75,8 +68,10 @@ bool LauncherSettings::writeFile(QTextStream &stream) QMap settings = SettingsBase::getSettings(); QMapIterator i(settings); - while (i.hasNext()) { - i.next(); + i.toBack(); + + while (i.hasPrevious()) { + i.previous(); QString prefix; QString key; diff --git a/apps/launcher/settings/settingsbase.hpp b/apps/launcher/settings/settingsbase.hpp index e70bc0d721..321426eed8 100644 --- a/apps/launcher/settings/settingsbase.hpp +++ b/apps/launcher/settings/settingsbase.hpp @@ -75,7 +75,6 @@ public: QStringList values = mCache.values(key); if (!values.contains(value)) { - // QMap will replace the value if key exists, QMultiMap creates a new one mCache.insertMulti(key, value); } } @@ -96,7 +95,6 @@ public: // Merge the changed keys with those which didn't mSettings.unite(mCache); - qDebug() << mSettings; return true; } diff --git a/components/fileorderlist/model/datafilesmodel.cpp b/components/fileorderlist/model/datafilesmodel.cpp index 036394800a..4e9b69dc27 100644 --- a/components/fileorderlist/model/datafilesmodel.cpp +++ b/components/fileorderlist/model/datafilesmodel.cpp @@ -229,10 +229,29 @@ bool lessThanEsmFile(const EsmFile *e1, const EsmFile *e2) return e1->fileName().toLower() < e2->fileName().toLower(); } +bool lessThanDate(const EsmFile *e1, const EsmFile *e2) +{ + if (e1->modified().toString(Qt::ISODate) < e2->modified().toString(Qt::ISODate)) { + return true; + } else { + return false; + } +// if (!e1->fileName().endsWith(".esm") && e2->fileName().endsWith(".esm")) +// return false; + +// return e1->fileName().toLower() < e2->fileName().toLower(); +} + void DataFilesModel::sort(int column, Qt::SortOrder order) { emit layoutAboutToBeChanged(); - qSort(mFiles.begin(), mFiles.end(), lessThanEsmFile); + + if (column == 3) { + qSort(mFiles.begin(), mFiles.end(), lessThanDate); + } else { + qSort(mFiles.begin(), mFiles.end(), lessThanEsmFile); + } + emit layoutChanged(); }