From 6faf6f57e1c64870f8bd954679fb16352d2219f4 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Fri, 25 Jan 2013 05:19:06 +0100 Subject: [PATCH 01/37] Added settings file reader/writers for openmw.cfg and settings.cfg --- apps/launcher/CMakeLists.txt | 7 ++ apps/launcher/settings/gamesettings.cpp | 34 ++++++++ apps/launcher/settings/gamesettings.hpp | 15 ++++ apps/launcher/settings/graphicssettings.cpp | 46 +++++++++++ apps/launcher/settings/graphicssettings.hpp | 16 ++++ apps/launcher/settings/settingsbase.hpp | 88 +++++++++++++++++++++ 6 files changed, 206 insertions(+) create mode 100644 apps/launcher/settings/gamesettings.cpp create mode 100644 apps/launcher/settings/gamesettings.hpp create mode 100644 apps/launcher/settings/graphicssettings.cpp create mode 100644 apps/launcher/settings/graphicssettings.hpp create mode 100644 apps/launcher/settings/settingsbase.hpp diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 09beaf59de..2895b6345f 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -9,6 +9,9 @@ set(LAUNCHER model/modelitem.cpp model/esm/esmfile.cpp + settings/gamesettings.cpp + settings/graphicssettings.cpp + utils/filedialog.cpp utils/naturalsort.cpp utils/lineedit.cpp @@ -28,6 +31,10 @@ set(LAUNCHER_HEADER model/modelitem.hpp model/esm/esmfile.hpp + settings/gamesettings.hpp + settings/graphicssettings.hpp + settings/settingsbase.hpp + utils/lineedit.hpp utils/filedialog.hpp utils/naturalsort.hpp diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp new file mode 100644 index 0000000000..32f03ddbe3 --- /dev/null +++ b/apps/launcher/settings/gamesettings.cpp @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +#include + +#include "gamesettings.hpp" + +GameSettings::GameSettings() +{ +} + +GameSettings::~GameSettings() +{ +} + +bool GameSettings::writeFile(QTextStream &stream) +{ + QMap settings = SettingsBase::getSettings(); + + QMapIterator i(settings); + while (i.hasNext()) { + i.next(); + + // Quote values with spaces + if (i.value().contains(" ")) { + stream << i.key() << "=\"" << i.value() << "\"\n"; + } else { + stream << i.key() << "=" << i.value() << "\n"; + } + + } +} diff --git a/apps/launcher/settings/gamesettings.hpp b/apps/launcher/settings/gamesettings.hpp new file mode 100644 index 0000000000..c81c67d978 --- /dev/null +++ b/apps/launcher/settings/gamesettings.hpp @@ -0,0 +1,15 @@ +#ifndef GAMESETTINGS_HPP +#define GAMESETTINGS_HPP + +#include "settingsbase.hpp" + +class GameSettings : public SettingsBase> +{ +public: + GameSettings(); + ~GameSettings(); + + bool writeFile(QTextStream &stream); +}; + +#endif // GAMESETTINGS_HPP diff --git a/apps/launcher/settings/graphicssettings.cpp b/apps/launcher/settings/graphicssettings.cpp new file mode 100644 index 0000000000..fd70917b5d --- /dev/null +++ b/apps/launcher/settings/graphicssettings.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +#include + +#include "graphicssettings.hpp" + +GraphicsSettings::GraphicsSettings() +{ +} + +GraphicsSettings::~GraphicsSettings() +{ +} + +bool GraphicsSettings::writeFile(QTextStream &stream) +{ + QString sectionPrefix; + QRegExp sectionRe("([^/]+)/(.+)$"); + QMap settings = SettingsBase::getSettings(); + + QMapIterator i(settings); + while (i.hasNext()) { + i.next(); + + QString prefix; + QString key; + + if (sectionRe.exactMatch(i.key())) { + prefix = sectionRe.cap(1); + key = sectionRe.cap(2); + } + + if (sectionPrefix != prefix) { + sectionPrefix = prefix; + stream << "\n[" << prefix << "]\n"; + } + + stream << key << " = " << i.value() << "\n"; + } + + return true; + +} diff --git a/apps/launcher/settings/graphicssettings.hpp b/apps/launcher/settings/graphicssettings.hpp new file mode 100644 index 0000000000..8c690ebc5f --- /dev/null +++ b/apps/launcher/settings/graphicssettings.hpp @@ -0,0 +1,16 @@ +#ifndef GRAPHICSSETTINGS_HPP +#define GRAPHICSSETTINGS_HPP + +#include "settingsbase.hpp" + +class GraphicsSettings : public SettingsBase> +{ +public: + GraphicsSettings(); + ~GraphicsSettings(); + + bool writeFile(QTextStream &stream); + +}; + +#endif // GRAPHICSSETTINGS_HPP diff --git a/apps/launcher/settings/settingsbase.hpp b/apps/launcher/settings/settingsbase.hpp new file mode 100644 index 0000000000..6b8b52762d --- /dev/null +++ b/apps/launcher/settings/settingsbase.hpp @@ -0,0 +1,88 @@ +#ifndef SETTINGSBASE_HPP +#define SETTINGSBASE_HPP + +#include +#include +#include +#include + +#include + +template +class SettingsBase +{ + +public: + SettingsBase() {} + ~SettingsBase() {} + + inline QString value(const QString &key, const QString &defaultValue = QString()) + { + return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key); + } + + inline void setValue(const QString &key, const QString &value) + { + mSettings.insert(key, value); + } + + Map getSettings() {return mSettings;} + + bool readFile(QTextStream &stream) + { + mCache.clear(); + + QString sectionPrefix; + QRegExp sectionRe("^\\[([^]]+)\\]"); + QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); + + while (!stream.atEnd()) { + QString line = stream.readLine().simplified(); + + if (line.isEmpty() || line.startsWith("#")) + continue; + + if (sectionRe.exactMatch(line)) { + sectionPrefix = sectionRe.cap(1); + sectionPrefix.append("/"); + continue; + } + + if (keyRe.indexIn(line) != -1) { + + QString key = keyRe.cap(1).simplified(); + QString value = keyRe.cap(2).simplified(); + + if (!sectionPrefix.isEmpty()) + key.prepend(sectionPrefix); + + // QMap will replace the value if key exists, QMultiMap creates a new one + mCache.insert(key, value); + } + } + + if (mSettings.isEmpty()) { + mSettings = mCache; // This is the first time we read a file + return true; + } + + // Replace values from previous settings + QMapIterator i(mCache); + while (i.hasNext()) { + i.next(); + if (mSettings.contains(i.key())) + mSettings.remove(i.key()); + } + + // Merge the changed keys with those which didn't + mSettings.unite(mCache); + qDebug() << mSettings; + return true; + } + +private: + Map mSettings; + Map mCache; +}; + +#endif // SETTINGSBASE_HPP From 5579df30ff260c48861040350c9c8b7d509d6573 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sat, 26 Jan 2013 18:19:04 +0100 Subject: [PATCH 02/37] Implemented data/data-local support and added settingshandlers to main.cpp --- apps/launcher/main.cpp | 144 +++++++++++++++++++++++- apps/launcher/settings/gamesettings.cpp | 125 +++++++++++++++++++- apps/launcher/settings/gamesettings.hpp | 43 ++++++- 3 files changed, 300 insertions(+), 12 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 7c4cb5f7e8..3fef62bc65 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -1,8 +1,22 @@ #include +#include +#include +#include #include +#include +#include +#include +#include #include +#include + +#include + #include "maindialog.hpp" +#include "settings/gamesettings.hpp" +#include "settings/graphicssettings.hpp" + int main(int argc, char *argv[]) { @@ -30,14 +44,136 @@ int main(int argc, char *argv[]) QDir::setCurrent(dir.absolutePath()); - MainDialog mainWin; + // Create setting file handlers - if (mainWin.setup()) { + Files::ConfigurationManager cfgMgr; + QString userPath = QString::fromStdString(cfgMgr.getUserPath().string()); + QString globalPath = QString::fromStdString(cfgMgr.getGlobalPath().string()); - mainWin.show(); - return app.exec(); + GameSettings gameSettings(cfgMgr); + GraphicsSettings graphicsSettings; + + QStringList paths; + paths.append(userPath + QString("openmw.cfg")); + paths.append(QString("openmw.cfg")); + paths.append(globalPath + QString("openmw.cfg")); + + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error opening OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return 0; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + gameSettings.readFile(stream); + } + file.close(); } + if (gameSettings.getDataDirs().isEmpty()) + { + QMessageBox msgBox; + msgBox.setWindowTitle("Error detecting Morrowind installation"); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Cancel); + msgBox.setText(QObject::tr("
Could not find the Data Files location

\ + The directory containing the data files was not found.

\ + Press \"Browse...\" to specify the location manually.
")); + + QAbstractButton *dirSelectButton = + msgBox.addButton(QObject::tr("B&rowse..."), QMessageBox::ActionRole); + + msgBox.exec(); + + QString selectedFile; + if (msgBox.clickedButton() == dirSelectButton) { + selectedFile = QFileDialog::getOpenFileName( + NULL, + QObject::tr("Select master file"), + QDir::currentPath(), + QString("Morrowind master file (*.esm)")); + } + + if (selectedFile.isEmpty()) + return 0; // Cancel was clicked; + + qDebug() << selectedFile; + QFileInfo info(selectedFile); + + // Add the new dir to the settings file and to the data dir container + gameSettings.setValue(QString("data"), info.absolutePath()); + gameSettings.addDataDir(info.absolutePath()); + + } + + // On to the graphics settings + qDebug() << userPath; + + QFile localDefault(QString("settings-default.cfg")); + QFile globalDefault(globalPath + QString("settings-default.cfg")); + + if (!localDefault.exists() && !globalDefault.exists()) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error reading OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not find settings-default.cfg

\ + The problem may be due to an incomplete installation of OpenMW.
\ + Reinstalling OpenMW may resolve the problem.")); + msgBox.exec(); + return 0; + } + + paths.clear(); + paths.append(globalPath + QString("settings-default.cfg")); + paths.append(QString("settings-default.cfg")); + + paths.append(userPath + QString("settings.cfg")); + paths.append(QString("settings.cfg")); + + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error opening OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return 0; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + graphicsSettings.readFile(stream); + } + file.close(); + } + + + MainDialog mainWin; + mainWin.setup(); + + mainWin.show(); + QCoreApplication::processEvents(); + return app.exec(); + + return 0; } diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 32f03ddbe3..2420c1e6c0 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -1,13 +1,17 @@ #include +#include #include #include #include #include +#include + #include "gamesettings.hpp" -GameSettings::GameSettings() +GameSettings::GameSettings(Files::ConfigurationManager &cfg) + : mCfgMgr(cfg) { } @@ -15,11 +19,124 @@ GameSettings::~GameSettings() { } +void GameSettings::validatePaths() +{ + qDebug() << "validate paths!"; + + if (mSettings.isEmpty()) + return; + + QStringList paths = mSettings.values(QString("data")); + Files::PathContainer dataDirs; + + foreach (const QString &path, paths) { + dataDirs.push_back(Files::PathContainer::value_type(path.toStdString())); + } + + // 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) { + QString path = QString::fromStdString(it->string()); + path.remove(QChar('\"')); + + QDir dir(path); + if (dir.exists()) + mDataDirs.append(path); + } + + // Do the same for data-local + QString local = mSettings.value(QString("data-local")); + + if (local.isEmpty()) + return; + + dataDirs.clear(); + 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()); + path.remove(QChar('\"')); + + QDir dir(path); + if (dir.exists()) + mDataLocal = path; + } + qDebug() << mSettings; + + +} + +QStringList GameSettings::values(const QString &key, const QStringList &defaultValues) +{ + if (!mSettings.values(key).isEmpty()) + return mSettings.values(key); + return defaultValues; +} + +bool GameSettings::readFile(QTextStream &stream) +{ + QMap cache; + QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); + + while (!stream.atEnd()) { + QString line = stream.readLine().simplified(); + + 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")) { + cache.insertMulti(key, value); + } else { + cache.insert(key, value); + } + } + } + + if (mSettings.isEmpty()) { + mSettings = cache; // This is the first time we read a file + validatePaths(); + return true; + } + + // Replace values from previous settings + QMapIterator i(cache); + while (i.hasNext()) { + i.next(); + + // Don't remove existing data entries + if (i.key() == QLatin1String("data")) + continue; + + if (mSettings.contains(i.key())) + mSettings.remove(i.key()); + } + + // Merge the changed keys with those which didn't + mSettings.unite(cache); + validatePaths(); + qDebug() << mSettings; + return true; +} + bool GameSettings::writeFile(QTextStream &stream) { - QMap settings = SettingsBase::getSettings(); - - QMapIterator i(settings); + QMapIterator i(mSettings); while (i.hasNext()) { i.next(); diff --git a/apps/launcher/settings/gamesettings.hpp b/apps/launcher/settings/gamesettings.hpp index c81c67d978..717ce6e877 100644 --- a/apps/launcher/settings/gamesettings.hpp +++ b/apps/launcher/settings/gamesettings.hpp @@ -1,15 +1,50 @@ #ifndef GAMESETTINGS_HPP #define GAMESETTINGS_HPP -#include "settingsbase.hpp" +#include -class GameSettings : public SettingsBase> +#include + +class QTextStream; +class QStringList; +class QString; + +namespace Files { typedef std::vector PathContainer; + struct ConfigurationManager;} + +class GameSettings { public: - GameSettings(); + GameSettings(Files::ConfigurationManager &cfg); ~GameSettings(); - bool writeFile(QTextStream &stream); + inline QString value(const QString &key, const QString &defaultValue = QString()) + { + return mSettings.value(key).isEmpty() ? defaultValue : mSettings.value(key); + } + + + inline void setValue(const QString &key, const QString &value) + { + mSettings.insert(key, value); + } + + inline QStringList getDataDirs() { return mDataDirs; } + inline void addDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.append(dir); } + inline QString getDataLocal() {return mDataLocal; } + + QStringList values(const QString &key, const QStringList &defaultValues = QStringList()); + bool readFile(QTextStream &stream); + bool writeFile(QTextStream &stream); + +private: + Files::ConfigurationManager &mCfgMgr; + + void validatePaths(); + QMap mSettings; + + QStringList mDataDirs; + QString mDataLocal; }; #endif // GAMESETTINGS_HPP From 25edba088754aec279b41e25d4b244722cd3d037 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 27 Jan 2013 16:39:51 +0100 Subject: [PATCH 03/37] Rewriting the config code of the pages to use the new settings classes --- apps/launcher/CMakeLists.txt | 3 - apps/launcher/datafilespage.cpp | 368 +++++++++++------------------ apps/launcher/datafilespage.hpp | 13 +- apps/launcher/graphicspage.cpp | 94 ++++---- apps/launcher/graphicspage.hpp | 14 +- apps/launcher/main.cpp | 16 +- apps/launcher/maindialog.cpp | 116 +++++---- apps/launcher/maindialog.hpp | 9 +- apps/launcher/utils/filedialog.cpp | 57 ----- apps/launcher/utils/filedialog.hpp | 28 --- 10 files changed, 290 insertions(+), 428 deletions(-) delete mode 100644 apps/launcher/utils/filedialog.cpp delete mode 100644 apps/launcher/utils/filedialog.hpp diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 2895b6345f..044a0a0b73 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -12,7 +12,6 @@ set(LAUNCHER settings/gamesettings.cpp settings/graphicssettings.cpp - utils/filedialog.cpp utils/naturalsort.cpp utils/lineedit.cpp utils/profilescombobox.cpp @@ -36,7 +35,6 @@ set(LAUNCHER_HEADER settings/settingsbase.hpp utils/lineedit.hpp - utils/filedialog.hpp utils/naturalsort.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp @@ -55,7 +53,6 @@ set(LAUNCHER_HEADER_MOC model/esm/esmfile.hpp utils/lineedit.hpp - utils/filedialog.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp ) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 6b0539c1dd..e253003940 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -6,8 +6,9 @@ #include "model/datafilesmodel.hpp" #include "model/esm/esmfile.hpp" +#include "settings/gamesettings.hpp" + #include "utils/profilescombobox.hpp" -#include "utils/filedialog.hpp" #include "utils/lineedit.hpp" #include "utils/naturalsort.hpp" #include "utils/textinputdialog.hpp" @@ -46,9 +47,10 @@ bool rowSmallerThan(const QModelIndex &index1, const QModelIndex &index2) return index1.row() <= index2.row(); } -DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent) - : QWidget(parent) - , mCfgMgr(cfg) +DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, QWidget *parent) + : mCfgMgr(cfg) + , mGameSettings(gameSettings) + , QWidget(parent) { // Models mMastersModel = new DataFilesModel(this); @@ -178,6 +180,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent) createActions(); setupConfig(); + setupDataFiles(); } void DataFilesPage::createActions() @@ -340,269 +343,176 @@ void DataFilesPage::readConfig() } -bool DataFilesPage::showDataFilesWarning() +void DataFilesPage::setupDataFiles() { + // Set the encoding to the one found in openmw.cfg or the default + mMastersModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252"))); + mPluginsModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252"))); - QMessageBox msgBox; - msgBox.setWindowTitle("Error detecting Morrowind installation"); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setStandardButtons(QMessageBox::Cancel); - msgBox.setText(tr("
Could not find the Data Files location

\ - The directory containing the data files was not found.

\ - Press \"Browse...\" to specify the location manually.
")); + QStringList paths = mGameSettings.getDataDirs(); - QAbstractButton *dirSelectButton = - msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole); - - msgBox.exec(); - - if (msgBox.clickedButton() == dirSelectButton) { - - // Show a custom dir selection dialog which only accepts valid dirs - QString selectedDir = FileDialog::getExistingDirectory( - this, tr("Select Data Files Directory"), - QDir::currentPath(), - QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - - // Add the user selected data directory - if (!selectedDir.isEmpty()) { - mDataDirs.push_back(Files::PathContainer::value_type(selectedDir.toStdString())); - mCfgMgr.processPaths(mDataDirs); - } else { - // Cancel from within the dir selection dialog - return false; - } - - } else { - // Cancel - return false; - } - - return true; -} - -bool DataFilesPage::setupDataFiles() -{ - // We use the Configuration Manager to retrieve the configuration values - boost::program_options::variables_map variables; - boost::program_options::options_description desc; - - desc.add_options() - ("data", boost::program_options::value()->default_value(Files::PathContainer(), "data")->multitoken()) - ("data-local", boost::program_options::value()->default_value("")) - ("fs-strict", boost::program_options::value()->implicit_value(true)->default_value(false)) - ("encoding", boost::program_options::value()->default_value("win1252")); - - boost::program_options::notify(variables); - - mCfgMgr.readConfiguration(variables, desc); - - if (variables["data"].empty()) { - if (!showDataFilesWarning()) - return false; - } else { - mDataDirs = Files::PathContainer(variables["data"].as()); - } - - std::string local = variables["data-local"].as(); - if (!local.empty()) { - mDataLocal.push_back(Files::PathContainer::value_type(local)); - } - - mCfgMgr.processPaths(mDataDirs); - mCfgMgr.processPaths(mDataLocal); - - // Second chance to display the warning, the data= entries are invalid - while (mDataDirs.empty()) { - if (!showDataFilesWarning()) - return false; - } - - // Set the charset for reading the esm/esp files - QString encoding = QString::fromStdString(variables["encoding"].as()); - if (!encoding.isEmpty() && encoding != QLatin1String("win1252")) { - mMastersModel->setEncoding(encoding); - mPluginsModel->setEncoding(encoding); - } - - // Add the paths to the respective models - for (Files::PathContainer::iterator it = mDataDirs.begin(); it != mDataDirs.end(); ++it) { - QString path = QString::fromStdString(it->string()); - path.remove(QChar('\"')); + foreach (const QString &path, paths) { mMastersModel->addMasters(path); mPluginsModel->addPlugins(path); } - // Same for the data-local paths - for (Files::PathContainer::iterator it = mDataLocal.begin(); it != mDataLocal.end(); ++it) { - QString path = QString::fromStdString(it->string()); - path.remove(QChar('\"')); - mMastersModel->addMasters(path); - mPluginsModel->addPlugins(path); + QString dataLocal = mGameSettings.getDataLocal(); + if (!dataLocal.isEmpty()) { + mMastersModel->addMasters(dataLocal); + mPluginsModel->addPlugins(dataLocal); } - mMastersModel->sort(0); - mPluginsModel->sort(0); -// mMastersTable->sortByColumn(3, Qt::AscendingOrder); -// mPluginsTable->sortByColumn(3, Qt::AscendingOrder); - - - readConfig(); - return true; } void DataFilesPage::writeConfig(QString profile) { - // Don't overwrite the config if no masters are found - if (mMastersModel->rowCount() < 1) - return; +// // Don't overwrite the config if no masters are found +// if (mMastersModel->rowCount() < 1) +// return; - QString pathStr = QString::fromStdString(mCfgMgr.getUserPath().string()); - QDir userPath(pathStr); +// QString pathStr = QString::fromStdString(mCfgMgr.getUserPath().string()); +// QDir userPath(pathStr); - if (!userPath.exists()) { - if (!userPath.mkpath(pathStr)) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error creating OpenMW configuration directory"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not create %0

\ - Please make sure you have the right permissions and try again.
").arg(pathStr)); - msgBox.exec(); +// if (!userPath.exists()) { +// if (!userPath.mkpath(pathStr)) { +// QMessageBox msgBox; +// msgBox.setWindowTitle("Error creating OpenMW configuration directory"); +// msgBox.setIcon(QMessageBox::Critical); +// msgBox.setStandardButtons(QMessageBox::Ok); +// msgBox.setText(tr("
Could not create %0

\ +// Please make sure you have the right permissions and try again.
").arg(pathStr)); +// msgBox.exec(); - qApp->quit(); - return; - } - } - // Open the OpenMW config as a QFile - QFile file(pathStr.append("openmw.cfg")); +// qApp->quit(); +// return; +// } +// } +// // Open the OpenMW config as a QFile +// QFile file(pathStr.append("openmw.cfg")); - if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { - // File cannot be opened or created - QMessageBox msgBox; - msgBox.setWindowTitle("Error writing OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not open or create %0

\ - Please make sure you have the right permissions and try again.
").arg(file.fileName())); - msgBox.exec(); +// if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { +// // File cannot be opened or created +// QMessageBox msgBox; +// msgBox.setWindowTitle("Error writing OpenMW configuration file"); +// msgBox.setIcon(QMessageBox::Critical); +// msgBox.setStandardButtons(QMessageBox::Ok); +// msgBox.setText(tr("
Could not open or create %0

\ +// Please make sure you have the right permissions and try again.
").arg(file.fileName())); +// msgBox.exec(); - qApp->quit(); - return; - } +// qApp->quit(); +// return; +// } - QTextStream in(&file); - QByteArray buffer; +// QTextStream in(&file); +// QByteArray buffer; - // Remove all previous entries from config - while (!in.atEnd()) { - QString line = in.readLine(); - if (!line.startsWith("master") && - !line.startsWith("plugin") && - !line.startsWith("data") && - !line.startsWith("data-local")) - { - buffer += line += "\n"; - } - } +// // Remove all previous entries from config +// while (!in.atEnd()) { +// QString line = in.readLine(); +// if (!line.startsWith("master") && +// !line.startsWith("plugin") && +// !line.startsWith("data") && +// !line.startsWith("data-local")) +// { +// buffer += line += "\n"; +// } +// } - file.close(); +// file.close(); - // Now we write back the other config entries - if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error writing OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not write to %0

\ - Please make sure you have the right permissions and try again.
").arg(file.fileName())); - msgBox.exec(); +// // Now we write back the other config entries +// if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { +// QMessageBox msgBox; +// msgBox.setWindowTitle("Error writing OpenMW configuration file"); +// msgBox.setIcon(QMessageBox::Critical); +// msgBox.setStandardButtons(QMessageBox::Ok); +// msgBox.setText(tr("
Could not write to %0

\ +// Please make sure you have the right permissions and try again.
").arg(file.fileName())); +// msgBox.exec(); - qApp->quit(); - return; - } +// qApp->quit(); +// return; +// } - if (!buffer.isEmpty()) { - file.write(buffer); - } +// if (!buffer.isEmpty()) { +// file.write(buffer); +// } - QTextStream gameConfig(&file); - - // First write the list of data dirs - mCfgMgr.processPaths(mDataDirs); - mCfgMgr.processPaths(mDataLocal); - - QString path; - - // data= directories - for (Files::PathContainer::iterator it = mDataDirs.begin(); it != mDataDirs.end(); ++it) { - path = QString::fromStdString(it->string()); - path.remove(QChar('\"')); - - // Make sure the string is quoted when it contains spaces - if (path.contains(" ")) { - gameConfig << "data=\"" << path << "\"" << endl; - } else { - gameConfig << "data=" << path << endl; - } - } - - // data-local directory - if (!mDataLocal.empty()) { - path = QString::fromStdString(mDataLocal.front().string()); - path.remove(QChar('\"')); - - if (path.contains(" ")) { - gameConfig << "data-local=\"" << path << "\"" << endl; - } else { - gameConfig << "data-local=" << path << endl; - } - } +// QTextStream gameConfig(&file); - if (profile.isEmpty()) - profile = mProfilesComboBox->currentText(); +// QString path; - if (profile.isEmpty()) - return; +// // data= directories +// for (Files::PathContainer::iterator it = mDataDirs.begin(); it != mDataDirs.end(); ++it) { +// path = QString::fromStdString(it->string()); +// path.remove(QChar('\"')); - // Make sure we have no groups open - while (!mLauncherConfig->group().isEmpty()) { - mLauncherConfig->endGroup(); - } +// // Make sure the string is quoted when it contains spaces +// if (path.contains(" ")) { +// gameConfig << "data=\"" << path << "\"" << endl; +// } else { +// gameConfig << "data=" << path << endl; +// } +// } - mLauncherConfig->beginGroup("Profiles"); - mLauncherConfig->setValue("CurrentProfile", profile); +// // data-local directory +// if (!mDataLocal.empty()) { +// path = QString::fromStdString(mDataLocal.front().string()); +// path.remove(QChar('\"')); - // Open the profile-name subgroup - mLauncherConfig->beginGroup(profile); - mLauncherConfig->remove(""); // Clear the subgroup +// if (path.contains(" ")) { +// gameConfig << "data-local=\"" << path << "\"" << endl; +// } else { +// gameConfig << "data-local=" << path << endl; +// } +// } - // Now write the masters to the configs - const QStringList masters = mMastersModel->checkedItems(); - // We don't use foreach because we need i - for (int i = 0; i < masters.size(); ++i) { - const QString currentMaster = masters.at(i); +// if (profile.isEmpty()) +// profile = mProfilesComboBox->currentText(); - mLauncherConfig->setValue(QString("Master%0").arg(i), currentMaster); - gameConfig << "master=" << currentMaster << endl; +// if (profile.isEmpty()) +// return; - } +// // Make sure we have no groups open +// while (!mLauncherConfig->group().isEmpty()) { +// mLauncherConfig->endGroup(); +// } - // And finally write all checked plugins - const QStringList plugins = mPluginsModel->checkedItems(); +// mLauncherConfig->beginGroup("Profiles"); +// mLauncherConfig->setValue("CurrentProfile", profile); - for (int i = 0; i < plugins.size(); ++i) { - const QString currentPlugin = plugins.at(i); - mLauncherConfig->setValue(QString("Plugin%1").arg(i), currentPlugin); - gameConfig << "plugin=" << currentPlugin << endl; - } +// // Open the profile-name subgroup +// mLauncherConfig->beginGroup(profile); +// mLauncherConfig->remove(""); // Clear the subgroup - file.close(); - mLauncherConfig->endGroup(); - mLauncherConfig->endGroup(); - mLauncherConfig->sync(); +// // Now write the masters to the configs +// const QStringList masters = mMastersModel->checkedItems(); + +// // We don't use foreach because we need i +// for (int i = 0; i < masters.size(); ++i) { +// const QString currentMaster = masters.at(i); + +// mLauncherConfig->setValue(QString("Master%0").arg(i), currentMaster); +// gameConfig << "master=" << currentMaster << endl; + +// } + +// // And finally write all checked plugins +// const QStringList plugins = mPluginsModel->checkedItems(); + +// for (int i = 0; i < plugins.size(); ++i) { +// const QString currentPlugin = plugins.at(i); +// mLauncherConfig->setValue(QString("Plugin%1").arg(i), currentPlugin); +// gameConfig << "plugin=" << currentPlugin << endl; +// } + +// file.close(); +// mLauncherConfig->endGroup(); +// mLauncherConfig->endGroup(); +// mLauncherConfig->sync(); } diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index 13668ec30e..e40d29d602 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -3,9 +3,6 @@ #include #include -#include "utils/profilescombobox.hpp" -#include - class QTableView; class QSortFilterProxyModel; @@ -17,6 +14,8 @@ class ProfilesComboBox; class DataFilesModel; class TextInputDialog; +class ProfilesComboBox; +class GameSettings; namespace Files { struct ConfigurationManager; } @@ -25,13 +24,11 @@ class DataFilesPage : public QWidget Q_OBJECT public: - DataFilesPage(Files::ConfigurationManager& cfg, QWidget *parent = 0); + DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, QWidget *parent = 0); ProfilesComboBox *mProfilesComboBox; void writeConfig(QString profile = QString()); - bool showDataFilesWarning(); - bool setupDataFiles(); public slots: void setCheckState(QModelIndex index); @@ -76,10 +73,9 @@ private: QAction *mUncheckAction; Files::ConfigurationManager &mCfgMgr; - Files::PathContainer mDataDirs; - Files::PathContainer mDataLocal; QSettings *mLauncherConfig; + GameSettings &mGameSettings; TextInputDialog *mNewProfileDialog; @@ -87,6 +83,7 @@ private: // const QStringList selectedMasters(); void createActions(); + void setupDataFiles(); void setupConfig(); void readConfig(); diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 2c4f3430c5..fa9d5d2547 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -3,12 +3,12 @@ #include #include -#include #include #include -#include +//#include +#include "settings/graphicssettings.hpp" #include "utils/naturalsort.hpp" #include "graphicspage.hpp" @@ -25,9 +25,10 @@ QString getAspect(int x, int y) return QString(QString::number(xaspect) + ":" + QString::number(yaspect)); } -GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent) - : QWidget(parent) - , mCfgMgr(cfg) +GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSetting, QWidget *parent) + : mCfgMgr(cfg) + , mGraphicsSettings(graphicsSetting) + , QWidget(parent) { QGroupBox *rendererGroup = new QGroupBox(tr("Renderer"), this); @@ -117,9 +118,8 @@ bool GraphicsPage::setupOgre() #endif } - boost::filesystem::path absPluginPath = boost::filesystem::absolute(boost::filesystem::path(pluginDir)); - - pluginDir = absPluginPath.string(); + QDir dir(QString::fromStdString(pluginDir)); + pluginDir = dir.absolutePath().toStdString(); Files::loadOgrePlugin(pluginDir, "RenderSystem_GL", *mOgre); Files::loadOgrePlugin(pluginDir, "RenderSystem_Direct3D9", *mOgre); @@ -154,20 +154,16 @@ bool GraphicsPage::setupOgre() msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not select a valid render system

\ - Please make sure the plugins.cfg file exists and contains a valid rendering plugin.
")); + Please make sure the plugins.cfg file exists and contains a valid rendering plugin.
")); msgBox.exec(); - return false; } // Now fill the GUI elements - int index = mRendererComboBox->findText(QString::fromStdString(Settings::Manager::getString("render system", "Video"))); - + int index = mRendererComboBox->findText(mGraphicsSettings.value(QString("Video/render system"))); if ( index != -1) { mRendererComboBox->setCurrentIndex(index); - } - else - { + } else { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 mRendererComboBox->setCurrentIndex(mRendererComboBox->findText(direct3DName)); #else @@ -180,45 +176,49 @@ bool GraphicsPage::setupOgre() mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); mResolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem)); - readConfig(); + // Load the rest of the values + loadSettings(); return true; } -void GraphicsPage::readConfig() +void GraphicsPage::loadSettings() { - if (Settings::Manager::getBool("vsync", "Video")) - mVSyncCheckBox->setCheckState(Qt::Checked); + if (mGraphicsSettings.value(QString("Video/vsync")) == QLatin1String("true")) + mVSyncCheckBox->setCheckState(Qt::Checked); - if (Settings::Manager::getBool("fullscreen", "Video")) - mFullScreenCheckBox->setCheckState(Qt::Checked); + if (mGraphicsSettings.value(QString("Video/fullscreen")) == QLatin1String("true")) + mFullScreenCheckBox->setCheckState(Qt::Checked); - int aaIndex = mAntiAliasingComboBox->findText(QString::fromStdString(Settings::Manager::getString("antialiasing", "Video"))); - if (aaIndex != -1) - mAntiAliasingComboBox->setCurrentIndex(aaIndex); + int aaIndex = mAntiAliasingComboBox->findText(mGraphicsSettings.value(QString("Video/antialiasing"))); + if (aaIndex != -1) + mAntiAliasingComboBox->setCurrentIndex(aaIndex); - QString resolution = QString::number(Settings::Manager::getInt("resolution x", "Video")); - resolution.append(" x " + QString::number(Settings::Manager::getInt("resolution y", "Video"))); + QString resolution = mGraphicsSettings.value(QString("Video/resolution x")); + resolution.append(QString(" x ") + mGraphicsSettings.value(QString("Video/resolution y"))); - int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith); - if (resIndex != -1) - mResolutionComboBox->setCurrentIndex(resIndex); + int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith); + qDebug() << "resolution from file: " << resolution; + if (resIndex != -1) + mResolutionComboBox->setCurrentIndex(resIndex); } -void GraphicsPage::writeConfig() +void GraphicsPage::saveSettings() { - Settings::Manager::setBool("vsync", "Video", mVSyncCheckBox->checkState()); - Settings::Manager::setBool("fullscreen", "Video", mFullScreenCheckBox->checkState()); - Settings::Manager::setString("antialiasing", "Video", mAntiAliasingComboBox->currentText().toStdString()); - Settings::Manager::setString("render system", "Video", mRendererComboBox->currentText().toStdString()); + mVSyncCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/vsync"), QString("true")) + : mGraphicsSettings.setValue(QString("Video/vsync"), QString("false")); - // Get the current resolution, but with the tabs replaced with a single space - QString resolution = mResolutionComboBox->currentText().simplified(); - QStringList tokens = resolution.split(" ", QString::SkipEmptyParts); + mFullScreenCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("true")) + : mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("false")); - int resX = tokens.at(0).toInt(); - int resY = tokens.at(2).toInt(); - Settings::Manager::setInt("resolution x", "Video", resX); - Settings::Manager::setInt("resolution y", "Video", resY); + mGraphicsSettings.setValue(QString("Video/antialiasing"), mAntiAliasingComboBox->currentText()); + mGraphicsSettings.setValue(QString("Video/render system"), mRendererComboBox->currentText()); + + QRegExp resolutionRe(QString("(\\d+) x (\\d+).*")); + + if (resolutionRe.exactMatch(mResolutionComboBox->currentText().simplified())) { + mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1)); + mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2)); + } } QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer) @@ -232,16 +232,14 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy { Ogre::StringVector::iterator opt_it; uint idx = 0; - for (opt_it = i->second.possibleValues.begin (); - opt_it != i->second.possibleValues.end (); opt_it++, idx++) - { - if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) - { + for (opt_it = i->second.possibleValues.begin(); + opt_it != i->second.possibleValues.end(); opt_it++, idx++) + { + if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) { result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified(); } } - } // Sort ascending @@ -258,7 +256,7 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer) { - QString key ("Video Mode"); + QString key("Video Mode"); QStringList result; uint row = 0; diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp index b8166f672a..48b9ff7854 100644 --- a/apps/launcher/graphicspage.hpp +++ b/apps/launcher/graphicspage.hpp @@ -5,8 +5,8 @@ #include #include -#include -#include +//#include +//#include // Static plugin headers #ifdef ENABLE_PLUGIN_GL @@ -21,6 +21,8 @@ class QCheckBox; class QStackedWidget; class QSettings; +class GraphicsSettings; + namespace Files { struct ConfigurationManager; } class GraphicsPage : public QWidget @@ -28,10 +30,10 @@ class GraphicsPage : public QWidget Q_OBJECT public: - GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent = 0); + GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSettings, QWidget *parent = 0); + void saveSettings(); bool setupOgre(); - void writeConfig(); public slots: void rendererChanged(const QString &renderer); @@ -58,12 +60,14 @@ private: QCheckBox *mFullScreenCheckBox; Files::ConfigurationManager &mCfgMgr; + GraphicsSettings &mGraphicsSettings; QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer); QStringList getAvailableResolutions(Ogre::RenderSystem *renderer); void createPages(); - void readConfig(); + void loadSettings(); + }; #endif diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 3fef62bc65..43bf50fbc7 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -138,9 +138,7 @@ int main(int argc, char *argv[]) paths.clear(); paths.append(globalPath + QString("settings-default.cfg")); paths.append(QString("settings-default.cfg")); - paths.append(userPath + QString("settings.cfg")); - paths.append(QString("settings.cfg")); foreach (const QString &path, paths) { qDebug() << "Loading: " << path; @@ -166,14 +164,14 @@ int main(int argc, char *argv[]) } - MainDialog mainWin; - mainWin.setup(); + MainDialog mainWin(gameSettings, graphicsSettings); + + if (mainWin.setup()) { + mainWin.show(); + } else { + return 0; + } - mainWin.show(); - QCoreApplication::processEvents(); return app.exec(); - - - return 0; } diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 674ccdf672..4d3d24bd91 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -1,11 +1,20 @@ #include +#include "settings/gamesettings.hpp" +#include "settings/graphicssettings.hpp" + +#include "utils/profilescombobox.hpp" + #include "maindialog.hpp" #include "playpage.hpp" #include "graphicspage.hpp" #include "datafilespage.hpp" -MainDialog::MainDialog() +MainDialog::MainDialog(GameSettings &gameSettings, + GraphicsSettings &graphicsSettings) + : mGameSettings(gameSettings) + , mGraphicsSettings(graphicsSettings) + { QWidget *centralWidget = new QWidget(this); setCentralWidget(centralWidget); @@ -122,8 +131,8 @@ void MainDialog::createIcons() void MainDialog::createPages() { mPlayPage = new PlayPage(this); - mGraphicsPage = new GraphicsPage(mCfgMgr, this); - mDataFilesPage = new DataFilesPage(mCfgMgr, this); + mGraphicsPage = new GraphicsPage(mCfgMgr, mGraphicsSettings, this); + mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, this); // Set the combobox of the play page to imitate the combobox on the datafilespage mPlayPage->mProfilesComboBox->setModel(mDataFilesPage->mProfilesComboBox->model()); @@ -152,46 +161,17 @@ void MainDialog::createPages() bool MainDialog::setup() { - // Create the settings manager and load default settings file - const std::string localdefault = (mCfgMgr.getLocalPath() / "settings-default.cfg").string(); - const std::string globaldefault = (mCfgMgr.getGlobalPath() / "settings-default.cfg").string(); - - // prefer local - if (boost::filesystem::exists(localdefault)) { - mSettings.loadDefault(localdefault); - } else if (boost::filesystem::exists(globaldefault)) { - mSettings.loadDefault(globaldefault); - } else { - QMessageBox msgBox; - msgBox.setWindowTitle("Error reading OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not find %0

\ - The problem may be due to an incomplete installation of OpenMW.
\ - Reinstalling OpenMW may resolve the problem.").arg(QString::fromStdString(globaldefault))); - msgBox.exec(); - return false; - } - - // load user settings if they exist, otherwise just load the default settings as user settings - const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string(); - - if (boost::filesystem::exists(settingspath)) - mSettings.loadUser(settingspath); - else if (boost::filesystem::exists(localdefault)) - mSettings.loadUser(localdefault); - else if (boost::filesystem::exists(globaldefault)) - mSettings.loadUser(globaldefault); - // Setup the Graphics page if (!mGraphicsPage->setupOgre()) { return false; } // Setup the Data Files page + /* if (!mDataFilesPage->setupDataFiles()) { return false; - } + }*/ + return true; } @@ -208,11 +188,67 @@ void MainDialog::closeEvent(QCloseEvent *event) { // Now write all config files mDataFilesPage->writeConfig(); - mGraphicsPage->writeConfig(); + mGraphicsPage->saveSettings(); - // Save user settings - const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string(); - mSettings.saveUser(settingspath); + QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string()); + QDir dir(userPath); + + if (!dir.exists()) { + if (!dir.mkpath(userPath)) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error creating OpenMW configuration directory"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not create %0

\ + Please make sure you have the right permissions \ + and try again.
").arg(userPath)); + msgBox.exec(); + event->accept(); + } + } + + // Game settings + QFile file(userPath + QString("openmw.cfg")); + + if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { + // File cannot be opened or created + QMessageBox msgBox; + msgBox.setWindowTitle("Error writing OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not open or create %0 for writing

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + event->accept(); + } + + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + mGameSettings.writeFile(stream); + file.close(); + + // Graphics settings + file.setFileName(userPath + QString("settings.cfg")); + + if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { + // File cannot be opened or created + QMessageBox msgBox; + msgBox.setWindowTitle("Error writing OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not open or create %0 for writing

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + event->accept(); + } + + stream.setDevice(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + mGraphicsSettings.writeFile(stream); event->accept(); } @@ -221,7 +257,7 @@ void MainDialog::play() { // First do a write of all the configs, just to be sure mDataFilesPage->writeConfig(); - mGraphicsPage->writeConfig(); + //mGraphicsPage->writeConfig(); // Save user settings const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string(); diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index bf98011cc4..c9654b874c 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -17,12 +17,15 @@ class PlayPage; class GraphicsPage; class DataFilesPage; +class GameSettings; +class GraphicsSettings; + class MainDialog : public QMainWindow { Q_OBJECT public: - MainDialog(); + MainDialog(GameSettings &gameSettings, GraphicsSettings &GraphicsSettings); public slots: void changePage(QListWidgetItem *current, QListWidgetItem *previous); @@ -43,6 +46,10 @@ private: Files::ConfigurationManager mCfgMgr; Settings::Manager mSettings; + + GameSettings &mGameSettings; + GraphicsSettings &mGraphicsSettings; + }; #endif diff --git a/apps/launcher/utils/filedialog.cpp b/apps/launcher/utils/filedialog.cpp deleted file mode 100644 index 16d6775331..0000000000 --- a/apps/launcher/utils/filedialog.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "filedialog.hpp" -#include -#include - -FileDialog::FileDialog(QWidget *parent) - : QFileDialog(parent) -{ - // Remove the default Choose button to prevent it being updated elsewhere - QDialogButtonBox *box = qFindChild(this); - Q_ASSERT(box); - box->removeButton(box->button(QDialogButtonBox::Open)); - - // Add our own button so we can disable/enable it - mChooseButton = new QPushButton(tr("&Choose")); - mChooseButton->setIcon(QIcon::fromTheme("document-open")); - mChooseButton->setEnabled(false); - box->addButton(mChooseButton, QDialogButtonBox::AcceptRole); - - connect(this, SIGNAL(directoryEntered(const QString&)), this, SLOT(updateChooseButton(const QString&))); - emit directoryEntered(QDir::currentPath()); -} - -QString FileDialog::getExistingDirectory(QWidget *parent, - const QString &caption, - const QString &dir, - Options options) -{ - // create a non-native file dialog - FileDialog dialog; - dialog.setFileMode(DirectoryOnly); - dialog.setOptions(options |= QFileDialog::DontUseNativeDialog | QFileDialog::ShowDirsOnly | QFileDialog::ReadOnly); - - if (!caption.isEmpty()) - dialog.setWindowTitle(caption); - - if (!dir.isEmpty()) - dialog.setDirectory(dir); - - if (dialog.exec() == QDialog::Accepted) { - return dialog.selectedFiles().value(0); - } - return QString(); -} - -void FileDialog::updateChooseButton(const QString &directory) -{ - QDir currentDir = QDir(directory); - currentDir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); - currentDir.setNameFilters(QStringList() << "*.esm" << "*.esp"); - - if (!currentDir.entryList().isEmpty()) { - // There are data files in the current dir - mChooseButton->setEnabled(true); - } else { - mChooseButton->setEnabled(false); - } -} diff --git a/apps/launcher/utils/filedialog.hpp b/apps/launcher/utils/filedialog.hpp deleted file mode 100644 index 7a161ecb96..0000000000 --- a/apps/launcher/utils/filedialog.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef FILEDIALOG_HPP -#define FILEDIALOG_HPP - -#include - -class QPushButton; - -class FileDialog : public QFileDialog -{ - Q_OBJECT - -public: - FileDialog(QWidget *parent = 0); - - static QString getExistingDirectory(QWidget *parent = 0, - const QString &caption = QString(), - const QString &dir = QString(), - Options options = ShowDirsOnly); - -private slots: - void updateChooseButton(const QString &directory); - -private: - QPushButton *mChooseButton; -}; - - -#endif // FILEDIALOG_HPP From e4ed397b2d35d77398a2d6596657b2a6eba67d74 Mon Sep 17 00:00:00 2001 From: Michal Sciubidlo Date: Sun, 10 Feb 2013 14:02:06 +0100 Subject: [PATCH 04/37] Merge plugins and masters list view in openDialog. Simplify datafilesmodel. --- components/fileorderlist/datafileslist.cpp | 68 +---------- components/fileorderlist/datafileslist.hpp | 2 - .../fileorderlist/model/datafilesmodel.cpp | 108 +++--------------- .../fileorderlist/model/datafilesmodel.hpp | 17 +-- 4 files changed, 28 insertions(+), 167 deletions(-) diff --git a/components/fileorderlist/datafileslist.cpp b/components/fileorderlist/datafileslist.cpp index d25060baaf..80d58b35f0 100644 --- a/components/fileorderlist/datafileslist.cpp +++ b/components/fileorderlist/datafileslist.cpp @@ -48,8 +48,7 @@ DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent) : QWidget(parent) , mCfgMgr(cfg) { - // Models - mMastersModel = new DataFilesModel(this); + // Model mPluginsModel = new DataFilesModel(this); mPluginsProxyModel = new QSortFilterProxyModel(); @@ -78,29 +77,6 @@ DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent) QCheckBox checkBox; unsigned int height = checkBox.sizeHint().height() + 4; - mMastersTable = new QTableView(this); - mMastersTable->setModel(mMastersModel); - mMastersTable->setObjectName("MastersTable"); - mMastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mMastersTable->setSelectionMode(QAbstractItemView::SingleSelection); - mMastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - mMastersTable->setAlternatingRowColors(true); - mMastersTable->horizontalHeader()->setStretchLastSection(true); - mMastersTable->horizontalHeader()->hide(); - - // Set the row height to the size of the checkboxes - 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(mPluginsProxyModel); mPluginsTable->setObjectName("PluginsTable"); @@ -124,26 +100,14 @@ DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent) mPluginsTable->setColumnHidden(7, true); mPluginsTable->setColumnHidden(8, true); - // Add both tables to a splitter - QSplitter *splitter = new QSplitter(this); - splitter->setOrientation(Qt::Horizontal); - splitter->addWidget(mMastersTable); - splitter->addWidget(mPluginsTable); - - // Adjust the default widget widths inside the splitter - QList sizeList; - sizeList << 175 << 200; - splitter->setSizes(sizeList); - QVBoxLayout *pageLayout = new QVBoxLayout(this); pageLayout->addWidget(filterToolBar); - pageLayout->addWidget(splitter); + pageLayout->addWidget(mPluginsTable); connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); - connect(mMastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); - - connect(mMastersModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mPluginsModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList))); + + connect(mPluginsModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mPluginsModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList))); connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); @@ -178,7 +142,6 @@ bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString { // Set the charset for reading the esm/esp files if (!encoding.isEmpty() && encoding != QLatin1String("win1252")) { - mMastersModel->setEncoding(encoding); mPluginsModel->setEncoding(encoding); } @@ -186,11 +149,9 @@ bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { QString path = QString::fromStdString(it->string()); path.remove(QChar('\"')); - mMastersModel->addMasters(path); - mPluginsModel->addPlugins(path); + mPluginsModel->addFiles(path); } - mMastersModel->sort(0); mPluginsModel->sort(0); // mMastersTable->sortByColumn(3, Qt::AscendingOrder); // mPluginsTable->sortByColumn(3, Qt::AscendingOrder); @@ -200,11 +161,6 @@ bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString void DataFilesList::selectedFiles(std::vector& paths) { - QStringList masterPaths = mMastersModel->checkedItemsPaths(); - foreach (const QString &path, masterPaths) - { - paths.push_back(path.toStdString()); - } QStringList pluginPaths = mPluginsModel->checkedItemsPaths(); foreach (const QString &path, pluginPaths) { @@ -281,19 +237,12 @@ void DataFilesList::setCheckState(QModelIndex index) : mPluginsModel->setCheckState(sourceIndex, Qt::Checked); } - if (object->objectName() == QLatin1String("MastersTable")) { - (mMastersModel->checkState(index) == Qt::Checked) - ? mMastersModel->setCheckState(index, Qt::Unchecked) - : mMastersModel->setCheckState(index, Qt::Checked); - } - return; } void DataFilesList::uncheckAll() { - mMastersModel->uncheckAll(); mPluginsModel->uncheckAll(); } @@ -338,14 +287,9 @@ void DataFilesList::setCheckState(const QString& element, Qt::CheckState state) { mPluginsModel->setCheckState(mPluginsModel->indexFromItem(file), Qt::Checked); } - else - { - file = mMastersModel->findItem(element); - mMastersModel->setCheckState(mMastersModel->indexFromItem(file), Qt::Checked); - } } QStringList DataFilesList::checkedFiles() { - return mMastersModel->checkedItems() + mPluginsModel->checkedItems(); + return mPluginsModel->checkedItems(); } \ No newline at end of file diff --git a/components/fileorderlist/datafileslist.hpp b/components/fileorderlist/datafileslist.hpp index 4b158d316d..64584d1fbc 100644 --- a/components/fileorderlist/datafileslist.hpp +++ b/components/fileorderlist/datafileslist.hpp @@ -49,12 +49,10 @@ public slots: void refresh(); private: - DataFilesModel *mMastersModel; DataFilesModel *mPluginsModel; QSortFilterProxyModel *mPluginsProxyModel; - QTableView *mMastersTable; QTableView *mPluginsTable; QMenu *mContextMenu; diff --git a/components/fileorderlist/model/datafilesmodel.cpp b/components/fileorderlist/model/datafilesmodel.cpp index 5bb1996791..4c33a555fa 100644 --- a/components/fileorderlist/model/datafilesmodel.cpp +++ b/components/fileorderlist/model/datafilesmodel.cpp @@ -159,7 +159,7 @@ Qt::ItemFlags DataFilesModel::flags(const QModelIndex &index) const if (!file) return Qt::NoItemFlags; - if (mAvailableFiles.contains(file->fileName())) { + if (canBeChecked(file)) { if (index.column() == 0) { return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable; } else { @@ -212,7 +212,6 @@ bool DataFilesModel::setData(const QModelIndex &index, const QVariant &value, in QString name = item(index.row())->fileName(); mCheckStates[name] = static_cast(value.toInt()); - emit checkedItemsChanged(checkedItems(), uncheckedItems()); emit layoutChanged(); return true; } @@ -263,73 +262,12 @@ void DataFilesModel::addFile(EsmFile *file) emit endInsertRows(); } -void DataFilesModel::addMasters(const QString &path) +void DataFilesModel::addFiles(const QString &path) { QDir dir(path); - dir.setNameFilters(QStringList(QLatin1String("*.esp"))); - - // Read the dependencies from the plugins - foreach (const QString &path, dir.entryList()) { - try { - ESM::ESMReader fileReader; - ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(mEncoding.toStdString())); - fileReader.setEncoder(&encoder); - fileReader.open(dir.absoluteFilePath(path).toStdString()); - - ESM::ESMReader::MasterList mlist = fileReader.getMasters(); - - for (unsigned int i = 0; i < mlist.size(); ++i) { - QString master = QString::fromStdString(mlist[i].name); - - // Add the plugin to the internal dependency map - mDependencies[master].append(path); - - // Don't add esps - if (master.endsWith(".esp", Qt::CaseInsensitive)) - continue; - - QFileInfo info(dir.absoluteFilePath(master)); - - EsmFile *file = new EsmFile(master); - file->setDates(info.lastModified(), info.lastRead()); - file->setPath(info.absoluteFilePath()); - - // Add the master to the table - if (findItem(master) == 0) - addFile(file); - - - } - - } catch(std::runtime_error &e) { - // An error occurred while reading the .esp - qWarning() << "Error reading esp: " << e.what(); - continue; - } - } - - // See if the masters actually exist in the filesystem - dir.setNameFilters(QStringList(QLatin1String("*.esm"))); - - foreach (const QString &path, dir.entryList()) { - QFileInfo info(dir.absoluteFilePath(path)); - - if (findItem(path) == 0) { - EsmFile *file = new EsmFile(path); - file->setDates(info.lastModified(), info.lastRead()); - - addFile(file); - } - - // Make the master selectable - mAvailableFiles.append(path); - } -} - -void DataFilesModel::addPlugins(const QString &path) -{ - QDir dir(path); - dir.setNameFilters(QStringList(QLatin1String("*.esp"))); + QStringList filters; + filters << "*.esp" << "*.esm"; + dir.setNameFilters(filters); foreach (const QString &path, dir.entryList()) { QFileInfo info(dir.absoluteFilePath(path)); @@ -347,9 +285,6 @@ void DataFilesModel::addPlugins(const QString &path) for (unsigned int i = 0; i < mlist.size(); ++i) { QString master = QString::fromStdString(mlist[i].name); masters.append(master); - - // Add the plugin to the internal dependency map - mDependencies[master].append(path); } file->setAuthor(QString::fromStdString(fileReader.getAuthor())); @@ -421,7 +356,7 @@ QStringList DataFilesModel::checkedItems() QString name = file->fileName(); // Only add the items that are in the checked list and available - if (mCheckStates[name] == Qt::Checked && mAvailableFiles.contains(name)) + if (mCheckStates[name] == Qt::Checked && canBeChecked(file)) list << name; } @@ -439,8 +374,8 @@ QStringList DataFilesModel::checkedItemsPaths() for (it = mFiles.constBegin(); it != itEnd; ++it) { EsmFile *file = item(i); ++i; - - if (mCheckStates[file->fileName()] == Qt::Checked && mAvailableFiles.contains(file->fileName())) + + if (mCheckStates[file->fileName()] == Qt::Checked && canBeChecked(file)) list << file->path(); } @@ -475,24 +410,17 @@ QStringList DataFilesModel::uncheckedItems() return list; } -void DataFilesModel::slotcheckedItemsChanged(const QStringList &checkedItems, const QStringList &unCheckedItems) +bool DataFilesModel::canBeChecked(EsmFile *file) const { - emit layoutAboutToBeChanged(); - - QStringList list; - - foreach (const QString &file, checkedItems) { - list << mDependencies[file]; - } - - foreach (const QString &file, unCheckedItems) { - foreach (const QString &remove, mDependencies[file]) { - list.removeAll(remove); + //element can be checked if all its dependencies are + bool canBeChecked = true; + foreach (const QString &master, file->masters()) + { + if (!mCheckStates.contains(master) || mCheckStates[master] != Qt::Checked) + { + canBeChecked = false; + break; } } - - mAvailableFiles.clear(); - mAvailableFiles.append(list); - - emit layoutChanged(); + return canBeChecked; } diff --git a/components/fileorderlist/model/datafilesmodel.hpp b/components/fileorderlist/model/datafilesmodel.hpp index adc80eac2a..0e5008abe1 100644 --- a/components/fileorderlist/model/datafilesmodel.hpp +++ b/components/fileorderlist/model/datafilesmodel.hpp @@ -34,10 +34,7 @@ public: void setEncoding(const QString &encoding); - void addFile(EsmFile *file); - - void addMasters(const QString &path); - void addPlugins(const QString &path); + void addFiles(const QString &path); void uncheckAll(); @@ -51,18 +48,12 @@ public: QModelIndex indexFromItem(EsmFile *item) const; EsmFile* findItem(const QString &name); EsmFile* item(int row) const; - -signals: - void checkedItemsChanged(const QStringList checkedItems, const QStringList unCheckedItems); - -public slots: - void slotcheckedItemsChanged(const QStringList &checkedItems, const QStringList &unCheckedItems); private: + bool canBeChecked(EsmFile *file) const; + void addFile(EsmFile *file); + QList mFiles; - QStringList mAvailableFiles; - - QHash mDependencies; QHash mCheckStates; QString mEncoding; From 0df7c7e5c17aff76fab9c4352a1904271c99c731 Mon Sep 17 00:00:00 2001 From: Michal Sciubidlo Date: Sun, 10 Feb 2013 14:08:54 +0100 Subject: [PATCH 05/37] Rename mPlugins* to mFiles* --- components/fileorderlist/datafileslist.cpp | 108 ++++++++++----------- components/fileorderlist/datafileslist.hpp | 6 +- 2 files changed, 57 insertions(+), 57 deletions(-) diff --git a/components/fileorderlist/datafileslist.cpp b/components/fileorderlist/datafileslist.cpp index 80d58b35f0..5ea2e051df 100644 --- a/components/fileorderlist/datafileslist.cpp +++ b/components/fileorderlist/datafileslist.cpp @@ -49,11 +49,11 @@ DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent) , mCfgMgr(cfg) { // Model - mPluginsModel = new DataFilesModel(this); + mFilesModel = new DataFilesModel(this); - mPluginsProxyModel = new QSortFilterProxyModel(); - mPluginsProxyModel->setDynamicSortFilter(true); - mPluginsProxyModel->setSourceModel(mPluginsModel); + mFilesProxyModel = new QSortFilterProxyModel(); + mFilesProxyModel->setDynamicSortFilter(true); + mFilesProxyModel->setSourceModel(mFilesModel); // Filter toolbar QLabel *filterLabel = new QLabel(tr("&Filter:"), this); @@ -77,41 +77,41 @@ DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent) QCheckBox checkBox; unsigned int height = checkBox.sizeHint().height() + 4; - mPluginsTable = new QTableView(this); - mPluginsTable->setModel(mPluginsProxyModel); - mPluginsTable->setObjectName("PluginsTable"); - mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); - mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mPluginsTable->setSelectionMode(QAbstractItemView::SingleSelection); - mPluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - mPluginsTable->setAlternatingRowColors(true); - mPluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); - mPluginsTable->horizontalHeader()->setStretchLastSection(true); - mPluginsTable->horizontalHeader()->hide(); + mFilesTable = new QTableView(this); + mFilesTable->setModel(mFilesProxyModel); + mFilesTable->setObjectName("PluginsTable"); + mFilesTable->setContextMenuPolicy(Qt::CustomContextMenu); + mFilesTable->setSelectionBehavior(QAbstractItemView::SelectRows); + mFilesTable->setSelectionMode(QAbstractItemView::SingleSelection); + mFilesTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + mFilesTable->setAlternatingRowColors(true); + mFilesTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); + mFilesTable->horizontalHeader()->setStretchLastSection(true); + mFilesTable->horizontalHeader()->hide(); - 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); + mFilesTable->verticalHeader()->setDefaultSectionSize(height); + mFilesTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); + mFilesTable->setColumnHidden(1, true); + mFilesTable->setColumnHidden(2, true); + mFilesTable->setColumnHidden(3, true); + mFilesTable->setColumnHidden(4, true); + mFilesTable->setColumnHidden(5, true); + mFilesTable->setColumnHidden(6, true); + mFilesTable->setColumnHidden(7, true); + mFilesTable->setColumnHidden(8, true); QVBoxLayout *pageLayout = new QVBoxLayout(this); pageLayout->addWidget(filterToolBar); - pageLayout->addWidget(mPluginsTable); + pageLayout->addWidget(mFilesTable); - connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + connect(mFilesTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); - connect(mPluginsModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mPluginsModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList))); + connect(mFilesModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mFilesModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList))); connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); - connect(mPluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); + connect(mFilesTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); createActions(); } @@ -142,17 +142,17 @@ bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString { // Set the charset for reading the esm/esp files if (!encoding.isEmpty() && encoding != QLatin1String("win1252")) { - mPluginsModel->setEncoding(encoding); + mFilesModel->setEncoding(encoding); } // Add the paths to the respective models for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { QString path = QString::fromStdString(it->string()); path.remove(QChar('\"')); - mPluginsModel->addFiles(path); + mFilesModel->addFiles(path); } - mPluginsModel->sort(0); + mFilesModel->sort(0); // mMastersTable->sortByColumn(3, Qt::AscendingOrder); // mPluginsTable->sortByColumn(3, Qt::AscendingOrder); @@ -161,7 +161,7 @@ bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString void DataFilesList::selectedFiles(std::vector& paths) { - QStringList pluginPaths = mPluginsModel->checkedItemsPaths(); + QStringList pluginPaths = mFilesModel->checkedItemsPaths(); foreach (const QString &path, pluginPaths) { paths.push_back(path.toStdString()); @@ -171,11 +171,11 @@ void DataFilesList::selectedFiles(std::vector& paths) void DataFilesList::check() { // Check the current selection - if (!mPluginsTable->selectionModel()->hasSelection()) { + if (!mFilesTable->selectionModel()->hasSelection()) { return; } - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + QModelIndexList indexes = mFilesTable->selectionModel()->selectedIndexes(); //sort selection ascending because selectedIndexes returns an unsorted list //qSort(indexes.begin(), indexes.end(), rowSmallerThan); @@ -184,18 +184,18 @@ void DataFilesList::check() if (!index.isValid()) return; - mPluginsModel->setCheckState(index, Qt::Checked); + mFilesModel->setCheckState(index, Qt::Checked); } } void DataFilesList::uncheck() { // uncheck the current selection - if (!mPluginsTable->selectionModel()->hasSelection()) { + if (!mFilesTable->selectionModel()->hasSelection()) { return; } - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + QModelIndexList indexes = mFilesTable->selectionModel()->selectedIndexes(); //sort selection ascending because selectedIndexes returns an unsorted list //qSort(indexes.begin(), indexes.end(), rowSmallerThan); @@ -204,17 +204,17 @@ void DataFilesList::uncheck() if (!index.isValid()) return; - mPluginsModel->setCheckState(index, Qt::Unchecked); + mFilesModel->setCheckState(index, Qt::Unchecked); } } void DataFilesList::refresh() { - mPluginsModel->sort(0); + mFilesModel->sort(0); // Refresh the plugins table - mPluginsTable->scrollToTop(); + mFilesTable->scrollToTop(); } @@ -230,11 +230,11 @@ void DataFilesList::setCheckState(QModelIndex index) return; if (object->objectName() == QLatin1String("PluginsTable")) { - QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(index); + QModelIndex sourceIndex = mFilesProxyModel->mapToSource(index); - (mPluginsModel->checkState(sourceIndex) == Qt::Checked) - ? mPluginsModel->setCheckState(sourceIndex, Qt::Unchecked) - : mPluginsModel->setCheckState(sourceIndex, Qt::Checked); + (mFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mFilesModel->setCheckState(sourceIndex, Qt::Unchecked) + : mFilesModel->setCheckState(sourceIndex, Qt::Checked); } return; @@ -243,25 +243,25 @@ void DataFilesList::setCheckState(QModelIndex index) void DataFilesList::uncheckAll() { - mPluginsModel->uncheckAll(); + mFilesModel->uncheckAll(); } void DataFilesList::filterChanged(const QString filter) { QRegExp regExp(filter, Qt::CaseInsensitive, QRegExp::FixedString); - mPluginsProxyModel->setFilterRegExp(regExp); + mFilesProxyModel->setFilterRegExp(regExp); } void DataFilesList::showContextMenu(const QPoint &point) { // Make sure there are plugins in the view - if (!mPluginsTable->selectionModel()->hasSelection()) { + if (!mFilesTable->selectionModel()->hasSelection()) { return; } - QPoint globalPos = mPluginsTable->mapToGlobal(point); + QPoint globalPos = mFilesTable->mapToGlobal(point); - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + QModelIndexList indexes = mFilesTable->selectionModel()->selectedIndexes(); // Show the check/uncheck actions depending on the state of the selected items mUncheckAction->setEnabled(false); @@ -271,7 +271,7 @@ void DataFilesList::showContextMenu(const QPoint &point) if (!index.isValid()) return; - (mPluginsModel->checkState(index) == Qt::Checked) + (mFilesModel->checkState(index) == Qt::Checked) ? mUncheckAction->setEnabled(true) : mCheckAction->setEnabled(true); } @@ -282,14 +282,14 @@ void DataFilesList::showContextMenu(const QPoint &point) void DataFilesList::setCheckState(const QString& element, Qt::CheckState state) { - EsmFile *file = mPluginsModel->findItem(element); + EsmFile *file = mFilesModel->findItem(element); if (file) { - mPluginsModel->setCheckState(mPluginsModel->indexFromItem(file), Qt::Checked); + mFilesModel->setCheckState(mFilesModel->indexFromItem(file), Qt::Checked); } } QStringList DataFilesList::checkedFiles() { - return mPluginsModel->checkedItems(); + return mFilesModel->checkedItems(); } \ No newline at end of file diff --git a/components/fileorderlist/datafileslist.hpp b/components/fileorderlist/datafileslist.hpp index 64584d1fbc..69a20393c2 100644 --- a/components/fileorderlist/datafileslist.hpp +++ b/components/fileorderlist/datafileslist.hpp @@ -49,11 +49,11 @@ public slots: void refresh(); private: - DataFilesModel *mPluginsModel; + DataFilesModel *mFilesModel; - QSortFilterProxyModel *mPluginsProxyModel; + QSortFilterProxyModel *mFilesProxyModel; - QTableView *mPluginsTable; + QTableView *mFilesTable; QMenu *mContextMenu; From f4d60ae7b203b90c9714fff9fa81eb06a79f278e Mon Sep 17 00:00:00 2001 From: Michal Sciubidlo Date: Sun, 10 Feb 2013 19:59:25 +0100 Subject: [PATCH 06/37] Files sorting (masters then plugins). Remove unneeded includes. --- apps/launcher/datafilespage.cpp | 7 --- components/fileorderlist/datafileslist.cpp | 1 - .../fileorderlist/model/datafilesmodel.cpp | 44 +++++-------------- .../fileorderlist/model/esm/esmfile.hpp | 18 ++++---- 4 files changed, 21 insertions(+), 49 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 52b8c9cbeb..8afece00b3 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -7,12 +7,7 @@ #include #include -////#include "model/datafilesmodel.hpp" -////#include "model/esm/esmfile.hpp" - #include "utils/profilescombobox.hpp" -////#include "utils/filedialog.hpp" -////#include "utils/naturalsort.hpp" #include "utils/textinputdialog.hpp" #include "datafilespage.hpp" @@ -527,7 +522,5 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous)); mDataFilesList->uncheckAll(); - ////mMastersModel->uncheckAll(); - ////mPluginsModel->uncheckAll(); readConfig(); } diff --git a/components/fileorderlist/datafileslist.cpp b/components/fileorderlist/datafileslist.cpp index 5ea2e051df..2f1b555c19 100644 --- a/components/fileorderlist/datafileslist.cpp +++ b/components/fileorderlist/datafileslist.cpp @@ -8,7 +8,6 @@ #include "utils/filedialog.hpp" #include "utils/lineedit.hpp" -#include "utils/naturalsort.hpp" #include "datafileslist.hpp" diff --git a/components/fileorderlist/model/datafilesmodel.cpp b/components/fileorderlist/model/datafilesmodel.cpp index 4c33a555fa..682ef01287 100644 --- a/components/fileorderlist/model/datafilesmodel.cpp +++ b/components/fileorderlist/model/datafilesmodel.cpp @@ -8,8 +8,6 @@ #include "esm/esmfile.hpp" -#include "../utils/naturalsort.hpp" - #include "datafilesmodel.hpp" DataFilesModel::DataFilesModel(QObject *parent) : @@ -219,39 +217,21 @@ bool DataFilesModel::setData(const QModelIndex &index, const QVariant &value, in return false; } +bool lessThanEsmFile(const EsmFile *e1, const EsmFile *e2) +{ + //Masters first then alphabetically + if (e1->fileName().endsWith(".esm") && !e2->fileName().endsWith(".esm")) + return true; + 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) { - // TODO: Make this more efficient emit layoutAboutToBeChanged(); - - QList sortedFiles; - - QMultiMap timestamps; - - foreach (EsmFile *file, mFiles) - timestamps.insert(file->modified().toString(Qt::ISODate), file->fileName()); - - QMapIterator ti(timestamps); - - while (ti.hasNext()) { - ti.next(); - - QModelIndex index = indexFromItem(findItem(ti.value())); - - if (!index.isValid()) - continue; - - EsmFile *file = item(index.row()); - - if (!file) - continue; - - sortedFiles.append(file); - } - - mFiles.clear(); - mFiles = sortedFiles; - + qSort(mFiles.begin(), mFiles.end(), lessThanEsmFile); emit layoutChanged(); } diff --git a/components/fileorderlist/model/esm/esmfile.hpp b/components/fileorderlist/model/esm/esmfile.hpp index ad267aa753..52b3fbd007 100644 --- a/components/fileorderlist/model/esm/esmfile.hpp +++ b/components/fileorderlist/model/esm/esmfile.hpp @@ -26,15 +26,15 @@ public: void setMasters(const QStringList &masters); void setDescription(const QString &description); - inline QString fileName() { return mFileName; } - inline QString author() { return mAuthor; } - inline int size() { return mSize; } - inline QDateTime modified() { return mModified; } - inline QDateTime accessed() { return mAccessed; } - inline float version() { return mVersion; } - inline QString path() { return mPath; } - inline QStringList masters() { return mMasters; } - inline QString description() { return mDescription; } + inline QString fileName() const { return mFileName; } + inline QString author() const { return mAuthor; } + inline int size() const { return mSize; } + inline QDateTime modified() const { return mModified; } + inline QDateTime accessed() const { return mAccessed; } + inline float version() const { return mVersion; } + inline QString path() const { return mPath; } + inline QStringList masters() const { return mMasters; } + inline QString description() const { return mDescription; } private: From aa2547151769a91b6a84704ab338b0bdee4ecac3 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 11 Feb 2013 15:01:00 +0100 Subject: [PATCH 07/37] WIP: working on improving the config file handling --- apps/launcher/CMakeLists.txt | 6 + apps/launcher/datafilespage.cpp | 295 +++++++++----------- apps/launcher/datafilespage.hpp | 14 +- apps/launcher/main.cpp | 34 ++- apps/launcher/maindialog.cpp | 79 ++++-- apps/launcher/maindialog.hpp | 16 +- apps/launcher/model/datafilesmodel.cpp | 4 +- apps/launcher/settings/gamesettings.cpp | 9 +- apps/launcher/settings/launchersettings.cpp | 45 +++ apps/launcher/settings/launchersettings.hpp | 16 ++ apps/launcher/settings/settingsbase.hpp | 23 +- apps/launcher/utils/lineedit.cpp | 13 +- apps/launcher/utils/lineedit.hpp | 2 +- apps/launcher/utils/profilescombobox.cpp | 65 ++++- apps/launcher/utils/profilescombobox.hpp | 4 +- 15 files changed, 404 insertions(+), 221 deletions(-) create mode 100644 apps/launcher/settings/launchersettings.cpp create mode 100644 apps/launcher/settings/launchersettings.hpp diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 044a0a0b73..3c721e2386 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -11,7 +11,9 @@ set(LAUNCHER settings/gamesettings.cpp settings/graphicssettings.cpp + settings/launchersettings.cpp + utils/comboboxlineedit.cpp utils/naturalsort.cpp utils/lineedit.cpp utils/profilescombobox.cpp @@ -32,8 +34,10 @@ set(LAUNCHER_HEADER settings/gamesettings.hpp settings/graphicssettings.hpp + settings/launchersettings.hpp settings/settingsbase.hpp + utils/comboboxlineedit.cpp utils/lineedit.hpp utils/naturalsort.hpp utils/profilescombobox.hpp @@ -52,6 +56,7 @@ set(LAUNCHER_HEADER_MOC model/modelitem.hpp model/esm/esmfile.hpp + utils/comboboxlineedit.hpp utils/lineedit.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp @@ -86,6 +91,7 @@ ENDIF(OGRE_STATIC) add_executable(omwlauncher ${GUI_TYPE} ${LAUNCHER} + ${LAUNCHER_HEADER} ${RCC_SRCS} ${MOC_SRCS} ) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index e253003940..12323b1f19 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -7,6 +7,7 @@ #include "model/esm/esmfile.hpp" #include "settings/gamesettings.hpp" +#include "settings/launchersettings.hpp" #include "utils/profilescombobox.hpp" #include "utils/lineedit.hpp" @@ -47,9 +48,10 @@ bool rowSmallerThan(const QModelIndex &index1, const QModelIndex &index2) return index1.row() <= index2.row(); } -DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, QWidget *parent) +DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent) : mCfgMgr(cfg) , mGameSettings(gameSettings) + , mLauncherSettings(launcherSettings) , QWidget(parent) { // Models @@ -129,15 +131,19 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mPluginsTable->setColumnHidden(8, true); // Add both tables to a splitter - QSplitter *splitter = new QSplitter(this); - splitter->setOrientation(Qt::Horizontal); - splitter->addWidget(mMastersTable); - splitter->addWidget(mPluginsTable); + mSplitter = new QSplitter(this); + mSplitter->setOrientation(Qt::Horizontal); + mSplitter->setChildrenCollapsible(false); // Don't allow the widgets to be hidden + mSplitter->addWidget(mMastersTable); + mSplitter->addWidget(mPluginsTable); // Adjust the default widget widths inside the splitter QList sizeList; - sizeList << 175 << 200; - splitter->setSizes(sizeList); + sizeList << mLauncherSettings.value(QString("General/MastersTable/width"), QString("200")).toInt(); + sizeList << mLauncherSettings.value(QString("General/PluginTable/width"), QString("340")).toInt(); + qDebug() << sizeList; + + mSplitter->setSizes(sizeList); // Bottom part with profile options QLabel *profileLabel = new QLabel(tr("Current Profile: "), this); @@ -158,7 +164,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam QVBoxLayout *pageLayout = new QVBoxLayout(this); pageLayout->addWidget(filterToolBar); - pageLayout->addWidget(splitter); + pageLayout->addWidget(mSplitter); pageLayout->addWidget(mProfileToolBar); // Create a dialog for the new profile name input @@ -178,8 +184,9 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam 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(); - setupConfig(); setupDataFiles(); } @@ -221,126 +228,50 @@ void DataFilesPage::createActions() } -void DataFilesPage::setupConfig() -{ - // Open our config file - QString config = QString::fromStdString((mCfgMgr.getUserPath() / "launcher.cfg").string()); - mLauncherConfig = new QSettings(config, QSettings::IniFormat); - - // Make sure we have no groups open - while (!mLauncherConfig->group().isEmpty()) { - mLauncherConfig->endGroup(); - } - - mLauncherConfig->beginGroup("Profiles"); - QStringList profiles = mLauncherConfig->childGroups(); - - // Add the profiles to the combobox - foreach (const QString &profile, profiles) { - - if (profile.contains(QRegExp("[^a-zA-Z0-9_]"))) - continue; // Profile name contains garbage - - - qDebug() << "adding " << profile; - mProfilesComboBox->addItem(profile); - } - - // Add a default profile - if (mProfilesComboBox->findText(QString("Default")) == -1) { - mProfilesComboBox->addItem(QString("Default")); - } - - QString currentProfile = mLauncherConfig->value("CurrentProfile").toString(); - - if (currentProfile.isEmpty()) { - // No current profile selected - currentProfile = "Default"; - } - - const int currentIndex = mProfilesComboBox->findText(currentProfile); - if (currentIndex != -1) { - // Profile is found - mProfilesComboBox->setCurrentIndex(currentIndex); - } - - mLauncherConfig->endGroup(); -} - - void DataFilesPage::readConfig() { - // Don't read the config if no masters are found - if (mMastersModel->rowCount() < 1) - return; +// // Don't read the config if no masters are found +// if (mMastersModel->rowCount() < 1) +// return; - QString profile = mProfilesComboBox->currentText(); - - // Make sure we have no groups open - while (!mLauncherConfig->group().isEmpty()) { - mLauncherConfig->endGroup(); - } - - mLauncherConfig->beginGroup("Profiles"); - mLauncherConfig->beginGroup(profile); - - QStringList childKeys = mLauncherConfig->childKeys(); - QStringList plugins; - - // Sort the child keys numerical instead of alphabetically - // i.e. Plugin1, Plugin2 instead of Plugin1, Plugin10 - qSort(childKeys.begin(), childKeys.end(), naturalSortLessThanCI); - - foreach (const QString &key, childKeys) { - const QString keyValue = mLauncherConfig->value(key).toString(); - - if (key.startsWith("Plugin")) { - //QStringList checked = mPluginsModel->checkedItems(); - EsmFile *file = mPluginsModel->findItem(keyValue); - QModelIndex index = mPluginsModel->indexFromItem(file); - - mPluginsModel->setCheckState(index, Qt::Checked); - // Move the row to the top of te view - //mPluginsModel->moveRow(index.row(), checked.count()); - plugins << keyValue; - } - - if (key.startsWith("Master")) { - EsmFile *file = mMastersModel->findItem(keyValue); - mMastersModel->setCheckState(mMastersModel->indexFromItem(file), Qt::Checked); - } - } - - qDebug() << plugins; - - -// // Set the checked item positions -// const QStringList checked = mPluginsModel->checkedItems(); -// for (int i = 0; i < plugins.size(); ++i) { -// EsmFile *file = mPluginsModel->findItem(plugins.at(i)); -// QModelIndex index = mPluginsModel->indexFromItem(file); -// mPluginsModel->moveRow(index.row(), i); -// qDebug() << "Moving: " << plugins.at(i) << " from: " << index.row() << " to: " << i << " count: " << checked.count(); +// QString profile = mProfilesComboBox->currentText(); +// // Make sure we have no groups open +// while (!mLauncherConfig->group().isEmpty()) { +// mLauncherConfig->endGroup(); // } - // Iterate over the plugins to set their checkstate and position -// for (int i = 0; i < plugins.size(); ++i) { -// const QString plugin = plugins.at(i); +// mLauncherConfig->beginGroup("Profiles"); +// mLauncherConfig->beginGroup(profile); -// const QList pluginList = mPluginsModel->findItems(plugin); +// QStringList childKeys = mLauncherConfig->childKeys(); +// QStringList plugins; -// if (!pluginList.isEmpty()) -// { -// foreach (const QStandardItem *currentPlugin, pluginList) { -// mPluginsModel->setData(currentPlugin->index(), Qt::Checked, Qt::CheckStateRole); +// // Sort the child keys numerical instead of alphabetically +// // i.e. Plugin1, Plugin2 instead of Plugin1, Plugin10 +// qSort(childKeys.begin(), childKeys.end(), naturalSortLessThanCI); -// // Move the plugin to the position specified in the config file -// mPluginsModel->insertRow(i, mPluginsModel->takeRow(currentPlugin->row())); -// } +// foreach (const QString &key, childKeys) { +// const QString keyValue = mLauncherConfig->value(key).toString(); + +// if (key.startsWith("Plugin")) { +// //QStringList checked = mPluginsModel->checkedItems(); +// EsmFile *file = mPluginsModel->findItem(keyValue); +// QModelIndex index = mPluginsModel->indexFromItem(file); + +// mPluginsModel->setCheckState(index, Qt::Checked); +// // Move the row to the top of te view +// //mPluginsModel->moveRow(index.row(), checked.count()); +// plugins << keyValue; +// } + +// if (key.startsWith("Master")) { +// EsmFile *file = mMastersModel->findItem(keyValue); +// mMastersModel->setCheckState(mMastersModel->indexFromItem(file), Qt::Checked); // } // } +// qDebug() << plugins; } void DataFilesPage::setupDataFiles() @@ -362,10 +293,43 @@ void DataFilesPage::setupDataFiles() mPluginsModel->addPlugins(dataLocal); } + loadSettings(); +} + +void DataFilesPage::loadSettings() +{ + qDebug() << "load settings"; +} + +void DataFilesPage::saveSettings() +{ + QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + qDebug() << "save settings" << profile; + + QStringList items = mMastersModel->checkedItems(); + + foreach(const QString &master, items) { + mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), master); + } + + items.clear(); + items = mPluginsModel->checkedItems(); + + qDebug() << items.size(); + + foreach(const QString &plugin, items) { + qDebug() << "setting " << plugin; + mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), plugin); + } + + + } void DataFilesPage::writeConfig(QString profile) { + + // // Don't overwrite the config if no masters are found // if (mMastersModel->rowCount() < 1) // return; @@ -518,21 +482,22 @@ void DataFilesPage::writeConfig(QString profile) void DataFilesPage::newProfile() { - if (mNewProfileDialog->exec() == QDialog::Accepted) { +// if (mNewProfileDialog->exec() == QDialog::Accepted) { - const QString text = mNewProfileDialog->lineEdit()->text(); - mProfilesComboBox->addItem(text); +// const QString text = mNewProfileDialog->lineEdit()->text(); +// mProfilesComboBox->addItem(text); +// mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(text)); +// } - // Copy the currently checked items to cfg - writeConfig(text); - mLauncherConfig->sync(); - - mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(text)); - } + mDeleteProfileAction->setEnabled(false); + mProfilesComboBox->setCurrentIndex(-1); + mProfilesComboBox->setEditEnabled(true); + mProfilesComboBox->lineEdit()->setFocus(); } void DataFilesPage::updateOkButton(const QString &text) { + // We do this here because we need the profiles combobox text if (text.isEmpty()) { mNewProfileDialog->setOkButtonEnabled(false); return; @@ -543,6 +508,16 @@ void DataFilesPage::updateOkButton(const QString &text) : mNewProfileDialog->setOkButtonEnabled(false); } +void DataFilesPage::updateSplitter() +{ + // Sigh, update the saved splitter size in settings only when moved + // Since getting mSplitter->sizes() if page is hidden returns invalid values + QList sizes = mSplitter->sizes(); + + mLauncherSettings.setValue(QString("General/MastersTable/width"), QString::number(sizes.at(0))); + mLauncherSettings.setValue(QString("General/PluginsTable/width"), QString::number(sizes.at(1))); +} + void DataFilesPage::deleteProfile() { QString profile = mProfilesComboBox->currentText(); @@ -562,18 +537,8 @@ void DataFilesPage::deleteProfile() msgBox.exec(); if (msgBox.clickedButton() == deleteButton) { - // Make sure we have no groups open - while (!mLauncherConfig->group().isEmpty()) { - mLauncherConfig->endGroup(); - } - - mLauncherConfig->beginGroup("Profiles"); - - // Open the profile-name subgroup - mLauncherConfig->beginGroup(profile); - mLauncherConfig->remove(""); // Clear the subgroup - mLauncherConfig->endGroup(); - mLauncherConfig->endGroup(); + mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); + mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); // Remove the profile from the combobox mProfilesComboBox->removeItem(mProfilesComboBox->findText(profile)); @@ -624,11 +589,8 @@ void DataFilesPage::refresh() { mPluginsModel->sort(0); - // Refresh the plugins table mPluginsTable->scrollToTop(); - writeConfig(); - readConfig(); } @@ -679,50 +641,43 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre mProfilesComboBox->setEditEnabled(true); } - if (!previous.isEmpty()) { - writeConfig(previous); - mLauncherConfig->sync(); - - if (mProfilesComboBox->currentIndex() == -1) - return; - - } else { + if (previous.isEmpty()) return; - } + + if (mProfilesComboBox->findText(previous) == -1) + return; // Profile was deleted + + // Store the previous profile + mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), previous); + saveSettings(); + mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), current); + mMastersModel->uncheckAll(); mPluginsModel->uncheckAll(); - readConfig(); + loadSettings(); } void DataFilesPage::profileRenamed(const QString &previous, const QString ¤t) { + qDebug() << "rename"; if (previous.isEmpty()) return; // Save the new profile name - writeConfig(current); + mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), current); + saveSettings(); - // Make sure we have no groups open - while (!mLauncherConfig->group().isEmpty()) { - mLauncherConfig->endGroup(); - } + // Remove the old one + mLauncherSettings.remove(QString("Profiles/") + previous + QString("/master")); + mLauncherSettings.remove(QString("Profiles/") + previous + QString("/plugin")); - mLauncherConfig->beginGroup("Profiles"); + // Remove the profile from the combobox + mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous)); - // Open the profile-name subgroup - mLauncherConfig->beginGroup(previous); - mLauncherConfig->remove(""); // Clear the subgroup - mLauncherConfig->endGroup(); - mLauncherConfig->endGroup(); - mLauncherConfig->sync(); - - // Remove the profile from the combobox - mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous)); - - mMastersModel->uncheckAll(); - mPluginsModel->uncheckAll(); - readConfig(); + mMastersModel->uncheckAll(); + mPluginsModel->uncheckAll(); + loadSettings(); } void DataFilesPage::showContextMenu(const QPoint &point) diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index e40d29d602..2dbbdb6679 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -6,16 +6,18 @@ class QTableView; class QSortFilterProxyModel; -class QSettings; class QAction; class QToolBar; +class QSplitter; class QMenu; + class ProfilesComboBox; class DataFilesModel; class TextInputDialog; class ProfilesComboBox; class GameSettings; +class LauncherSettings; namespace Files { struct ConfigurationManager; } @@ -24,11 +26,13 @@ class DataFilesPage : public QWidget Q_OBJECT public: - DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, QWidget *parent = 0); + DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent = 0); ProfilesComboBox *mProfilesComboBox; void writeConfig(QString profile = QString()); + void saveSettings(); + public slots: void setCheckState(QModelIndex index); @@ -38,6 +42,7 @@ public slots: void profileChanged(const QString &previous, const QString ¤t); void profileRenamed(const QString &previous, const QString ¤t); void updateOkButton(const QString &text); + void updateSplitter(); // Action slots void newProfile(); @@ -61,6 +66,7 @@ private: QToolBar *mProfileToolBar; QMenu *mContextMenu; + QSplitter *mSplitter; QAction *mNewProfileAction; QAction *mDeleteProfileAction; @@ -74,8 +80,8 @@ private: Files::ConfigurationManager &mCfgMgr; - QSettings *mLauncherConfig; GameSettings &mGameSettings; + LauncherSettings &mLauncherSettings; TextInputDialog *mNewProfileDialog; @@ -87,6 +93,8 @@ private: void setupConfig(); void readConfig(); + void loadSettings(); + }; #endif diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 43bf50fbc7..ba84518c1e 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -16,6 +16,7 @@ #include "maindialog.hpp" #include "settings/gamesettings.hpp" #include "settings/graphicssettings.hpp" +#include "settings/launchersettings.hpp" int main(int argc, char *argv[]) @@ -52,6 +53,7 @@ int main(int argc, char *argv[]) GameSettings gameSettings(cfgMgr); GraphicsSettings graphicsSettings; + LauncherSettings launcherSettings; QStringList paths; paths.append(userPath + QString("openmw.cfg")); @@ -118,8 +120,6 @@ int main(int argc, char *argv[]) } // On to the graphics settings - qDebug() << userPath; - QFile localDefault(QString("settings-default.cfg")); QFile globalDefault(globalPath + QString("settings-default.cfg")); @@ -163,8 +163,36 @@ int main(int argc, char *argv[]) file.close(); } + // Now the launcher settings + paths.clear(); + paths.append(QString("launcher.cfg")); + paths.append(userPath + QString("launcher.cfg")); - MainDialog mainWin(gameSettings, graphicsSettings); + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle("Error opening OpenMW configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return 0; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + launcherSettings.readFile(stream); + } + file.close(); + } + + + MainDialog mainWin(gameSettings, graphicsSettings, launcherSettings); if (mainWin.setup()) { mainWin.show(); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 4d3d24bd91..f48ea603bf 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -2,6 +2,7 @@ #include "settings/gamesettings.hpp" #include "settings/graphicssettings.hpp" +#include "settings/launchersettings.hpp" #include "utils/profilescombobox.hpp" @@ -11,9 +12,11 @@ #include "datafilespage.hpp" MainDialog::MainDialog(GameSettings &gameSettings, - GraphicsSettings &graphicsSettings) + GraphicsSettings &graphicsSettings, + LauncherSettings &launcherSettings) : mGameSettings(gameSettings) , mGraphicsSettings(graphicsSettings) + , mLauncherSettings(launcherSettings) { QWidget *centralWidget = new QWidget(this); @@ -132,7 +135,7 @@ void MainDialog::createPages() { mPlayPage = new PlayPage(this); mGraphicsPage = new GraphicsPage(mCfgMgr, mGraphicsSettings, this); - mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, this); + mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this); // Set the combobox of the play page to imitate the combobox on the datafilespage mPlayPage->mProfilesComboBox->setModel(mDataFilesPage->mProfilesComboBox->model()); @@ -161,18 +164,11 @@ void MainDialog::createPages() bool MainDialog::setup() { - // Setup the Graphics page + // Call this so we can exit on Ogre errors before mainwindow is shown if (!mGraphicsPage->setupOgre()) { return false; } - // Setup the Data Files page - /* - if (!mDataFilesPage->setupDataFiles()) { - return false; - }*/ - - return true; } @@ -184,11 +180,28 @@ void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) mPagesWidget->setCurrentIndex(mIconWidget->row(current)); } -void MainDialog::closeEvent(QCloseEvent *event) +void MainDialog::loadSettings() +{ + +} + +void 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); + + qDebug() << "size: " << width << height; +} + +void MainDialog::writeSettings() { // Now write all config files - mDataFilesPage->writeConfig(); + saveSettings(); mGraphicsPage->saveSettings(); + mDataFilesPage->saveSettings(); QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string()); QDir dir(userPath); @@ -203,7 +216,7 @@ void MainDialog::closeEvent(QCloseEvent *event) Please make sure you have the right permissions \ and try again.
").arg(userPath)); msgBox.exec(); - event->accept(); + return; } } @@ -220,7 +233,7 @@ void MainDialog::closeEvent(QCloseEvent *event) Please make sure you have the right permissions \ and try again.
").arg(file.fileName())); msgBox.exec(); - event->accept(); + return; } QTextStream stream(&file); @@ -242,26 +255,52 @@ void MainDialog::closeEvent(QCloseEvent *event) Please make sure you have the right permissions \ and try again.
").arg(file.fileName())); msgBox.exec(); - event->accept(); + return; } stream.setDevice(&file); stream.setCodec(QTextCodec::codecForName("UTF-8")); mGraphicsSettings.writeFile(stream); + file.close(); + // Launcher settings + file.setFileName(userPath + QString("launcher.cfg")); + + if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { + // File cannot be opened or created + QMessageBox msgBox; + msgBox.setWindowTitle("Error writing Launcher configuration file"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not open or create %0 for writing

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return; + } + + stream.setDevice(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + mLauncherSettings.writeFile(stream); + file.close(); +} + +void MainDialog::closeEvent(QCloseEvent *event) +{ + saveSettings(); + writeSettings(); event->accept(); } void MainDialog::play() { // First do a write of all the configs, just to be sure - mDataFilesPage->writeConfig(); + //mDataFilesPage->writeConfig(); //mGraphicsPage->writeConfig(); - - // Save user settings - const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string(); - mSettings.saveUser(settingspath); + saveSettings(); + writeSettings(); #ifdef Q_OS_WIN QString game = "./openmw.exe"; diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index c9654b874c..7167d101db 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -4,7 +4,6 @@ #include #include -#include class QListWidget; class QListWidgetItem; @@ -19,22 +18,31 @@ class DataFilesPage; class GameSettings; class GraphicsSettings; +class LauncherSettings; class MainDialog : public QMainWindow { Q_OBJECT public: - MainDialog(GameSettings &gameSettings, GraphicsSettings &GraphicsSettings); + MainDialog(GameSettings &gameSettings, + GraphicsSettings &GraphicsSettings, + LauncherSettings &launcherSettings); + + bool setup(); public slots: void changePage(QListWidgetItem *current, QListWidgetItem *previous); void play(); - bool setup(); private: void createIcons(); void createPages(); + + void loadSettings(); + void saveSettings(); + void writeSettings(); + void closeEvent(QCloseEvent *event); QListWidget *mIconWidget; @@ -45,10 +53,10 @@ private: DataFilesPage *mDataFilesPage; Files::ConfigurationManager mCfgMgr; - Settings::Manager mSettings; GameSettings &mGameSettings; GraphicsSettings &mGraphicsSettings; + LauncherSettings &mLauncherSettings; }; diff --git a/apps/launcher/model/datafilesmodel.cpp b/apps/launcher/model/datafilesmodel.cpp index e84dbe0acc..ae59cc3c3f 100644 --- a/apps/launcher/model/datafilesmodel.cpp +++ b/apps/launcher/model/datafilesmodel.cpp @@ -334,6 +334,7 @@ void DataFilesModel::addPlugins(const QString &path) QFileInfo info(dir.absoluteFilePath(path)); EsmFile *file = new EsmFile(path); + try { ESM::ESMReader fileReader; ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(mEncoding.toStdString())); @@ -361,7 +362,8 @@ void DataFilesModel::addPlugins(const QString &path) // Put the file in the table - addFile(file); + if (findItem(path) == 0) + addFile(file); } catch(std::runtime_error &e) { // An error occurred while reading the .esp qWarning() << "Error reading esp: " << e.what(); diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 2420c1e6c0..5f0fb77bc4 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -101,7 +101,14 @@ bool GameSettings::readFile(QTextStream &stream) qDebug() << "key: " << key; // There can be multiple data keys if (key == QLatin1String("data")) { - cache.insertMulti(key, value); + // 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; + cache.insertMulti(key, value); + } } else { cache.insert(key, value); } diff --git a/apps/launcher/settings/launchersettings.cpp b/apps/launcher/settings/launchersettings.cpp new file mode 100644 index 0000000000..c189c282fd --- /dev/null +++ b/apps/launcher/settings/launchersettings.cpp @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +#include "launchersettings.hpp" + +LauncherSettings::LauncherSettings() +{ +} + +LauncherSettings::~LauncherSettings() +{ +} + + +bool LauncherSettings::writeFile(QTextStream &stream) +{ + QString sectionPrefix; + QRegExp sectionRe("([^/]+)/(.+)$"); + QMap settings = SettingsBase::getSettings(); + + QMapIterator i(settings); + while (i.hasNext()) { + i.next(); + + QString prefix; + QString key; + + if (sectionRe.exactMatch(i.key())) { + prefix = sectionRe.cap(1); + key = sectionRe.cap(2); + } + + if (sectionPrefix != prefix) { + sectionPrefix = prefix; + stream << "\n[" << prefix << "]\n"; + } + + stream << key << "=" << i.value() << "\n"; + } + + return true; + +} diff --git a/apps/launcher/settings/launchersettings.hpp b/apps/launcher/settings/launchersettings.hpp new file mode 100644 index 0000000000..cf4dd4c9ff --- /dev/null +++ b/apps/launcher/settings/launchersettings.hpp @@ -0,0 +1,16 @@ +#ifndef LAUNCHERSETTINGS_HPP +#define LAUNCHERSETTINGS_HPP + +#include "settingsbase.hpp" + +class LauncherSettings : public SettingsBase> +{ +public: + LauncherSettings(); + ~LauncherSettings(); + + bool writeFile(QTextStream &stream); + +}; + +#endif // LAUNCHERSETTINGS_HPP diff --git a/apps/launcher/settings/settingsbase.hpp b/apps/launcher/settings/settingsbase.hpp index 6b8b52762d..e09ea62038 100644 --- a/apps/launcher/settings/settingsbase.hpp +++ b/apps/launcher/settings/settingsbase.hpp @@ -2,6 +2,7 @@ #define SETTINGSBASE_HPP #include +#include #include #include #include @@ -26,6 +27,17 @@ public: mSettings.insert(key, value); } + inline void setMultiValue(const QString &key, const QString &value) + { + mSettings.insertMulti(key, value); + } + + + inline void remove(const QString &key) + { + mSettings.remove(key); + } + Map getSettings() {return mSettings;} bool readFile(QTextStream &stream) @@ -56,11 +68,18 @@ public: if (!sectionPrefix.isEmpty()) key.prepend(sectionPrefix); - // QMap will replace the value if key exists, QMultiMap creates a new one - mCache.insert(key, value); + mSettings.remove(key); + + QStringList values = mCache.values(key); + if (!values.contains(value)) { + // QMap will replace the value if key exists, QMultiMap creates a new one + mCache.insert(key, value); + } } } + qDebug() << "HI THERE! " << mCache; + if (mSettings.isEmpty()) { mSettings = mCache; // This is the first time we read a file return true; diff --git a/apps/launcher/utils/lineedit.cpp b/apps/launcher/utils/lineedit.cpp index dac1964258..b0f3395897 100644 --- a/apps/launcher/utils/lineedit.cpp +++ b/apps/launcher/utils/lineedit.cpp @@ -1,7 +1,8 @@ -#include "lineedit.hpp" #include #include +#include "lineedit.hpp" + LineEdit::LineEdit(QWidget *parent) : QLineEdit(parent) { @@ -13,9 +14,11 @@ LineEdit::LineEdit(QWidget *parent) mClearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); mClearButton->hide(); connect(mClearButton, SIGNAL(clicked()), this, SLOT(clear())); - connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateCloseButton(const QString&))); + connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateClearButton(const QString&))); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1)); + + setObjectName(QString("LineEdit")); + setStyleSheet(QString("LineEdit { padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1)); QSize msz = minimumSizeHint(); setMinimumSize(qMax(msz.width(), mClearButton->sizeHint().height() + frameWidth * 2 + 2), qMax(msz.height(), mClearButton->sizeHint().height() + frameWidth * 2 + 2)); @@ -29,9 +32,7 @@ void LineEdit::resizeEvent(QResizeEvent *) (rect().bottom() + 1 - sz.height())/2); } -void LineEdit::updateCloseButton(const QString& text) +void LineEdit::updateClearButton(const QString& text) { mClearButton->setVisible(!text.isEmpty()); } - - diff --git a/apps/launcher/utils/lineedit.hpp b/apps/launcher/utils/lineedit.hpp index 2ed76d6eb7..14bd7b1b4c 100644 --- a/apps/launcher/utils/lineedit.hpp +++ b/apps/launcher/utils/lineedit.hpp @@ -25,7 +25,7 @@ protected: void resizeEvent(QResizeEvent *); private slots: - void updateCloseButton(const QString &text); + void updateClearButton(const QString &text); private: QToolButton *mClearButton; diff --git a/apps/launcher/utils/profilescombobox.cpp b/apps/launcher/utils/profilescombobox.cpp index 8354d4a780..3a75ba417a 100644 --- a/apps/launcher/utils/profilescombobox.cpp +++ b/apps/launcher/utils/profilescombobox.cpp @@ -1,45 +1,94 @@ #include #include #include +#include +#include #include "profilescombobox.hpp" +#include "comboboxlineedit.hpp" ProfilesComboBox::ProfilesComboBox(QWidget *parent) : QComboBox(parent) { mValidator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore - - setEditable(true); + setEditEnabled(true); setValidator(mValidator); setCompleter(0); connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(slotIndexChanged(int))); - connect(lineEdit(), SIGNAL(returnPressed()), this, - SLOT(slotReturnPressed())); + + } void ProfilesComboBox::setEditEnabled(bool editable) { - if (!editable) + qDebug() << "called"; + if (isEditable() == editable) + return; + + if (!editable) { + disconnect(lineEdit(), SIGNAL(editingFinished()), this, SLOT(slotEditingFinished())); + disconnect(lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(slotTextChanged(QString))); return setEditable(false); + } // Reset the completer and validator setEditable(true); setValidator(mValidator); + + ComboBoxLineEdit *edit = new ComboBoxLineEdit(this); + setLineEdit(edit); setCompleter(0); + + connect(lineEdit(), SIGNAL(editingFinished()), this, + SLOT(slotEditingFinished())); + + connect(lineEdit(), SIGNAL(textChanged(QString)), this, + SLOT(slotTextChanged(QString))); } -void ProfilesComboBox::slotReturnPressed() +void ProfilesComboBox::slotTextChanged(const QString &text) { + QString previous = itemText(currentIndex()); +// lineEdit()->setPalette(QApplication::palette()); + + if (text.isEmpty()) + return; + + if (text == previous) + return; + + qDebug() << "textChanged"; + if (findText(text) != -1) { + QPalette *palette = new QPalette(); + palette->setColor(QPalette::Text,Qt::red); + lineEdit()->setPalette(*palette); + } +} + +void ProfilesComboBox::slotEditingFinished() +{ + qDebug() << "returnpressed"; QString current = currentText(); QString previous = itemText(currentIndex()); + if (current.isEmpty()) + return; + + if (current == previous) + return; + if (findText(current) != -1) return; - setItemText(currentIndex(), current); - emit(profileRenamed(previous, current)); + + if (currentIndex() == -1) { + addItem(currentText()); + } else { + setItemText(currentIndex(), current); + emit(profileRenamed(previous, current)); + } } void ProfilesComboBox::slotIndexChanged(int index) diff --git a/apps/launcher/utils/profilescombobox.hpp b/apps/launcher/utils/profilescombobox.hpp index c7da60d2a5..08ead9a7ab 100644 --- a/apps/launcher/utils/profilescombobox.hpp +++ b/apps/launcher/utils/profilescombobox.hpp @@ -4,7 +4,6 @@ #include class QString; - class QRegExpValidator; class ProfilesComboBox : public QComboBox @@ -19,8 +18,9 @@ signals: void profileRenamed(const QString &oldName, const QString &newName); private slots: - void slotReturnPressed(); + void slotEditingFinished(); void slotIndexChanged(int index); + void slotTextChanged(const QString &text); private: QString mOldProfile; From 5d1bede9e50c13d72f548f23d3b5e8da60b79119 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Thu, 14 Feb 2013 11:20:47 +0100 Subject: [PATCH 08/37] Forgot to add two files --- apps/launcher/utils/comboboxlineedit.cpp | 35 ++++++++++++++++++++++++ apps/launcher/utils/comboboxlineedit.hpp | 35 ++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 apps/launcher/utils/comboboxlineedit.cpp create mode 100644 apps/launcher/utils/comboboxlineedit.hpp diff --git a/apps/launcher/utils/comboboxlineedit.cpp b/apps/launcher/utils/comboboxlineedit.cpp new file mode 100644 index 0000000000..4d62e1399a --- /dev/null +++ b/apps/launcher/utils/comboboxlineedit.cpp @@ -0,0 +1,35 @@ +#include +#include + +#include "comboboxlineedit.hpp" + +ComboBoxLineEdit::ComboBoxLineEdit(QWidget *parent) + : QLineEdit(parent) +{ + mClearButton = new QToolButton(this); + QPixmap pixmap(":images/clear.png"); + mClearButton->setIcon(QIcon(pixmap)); + mClearButton->setIconSize(pixmap.size()); + mClearButton->setCursor(Qt::ArrowCursor); + mClearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); + mClearButton->hide(); + connect(mClearButton, SIGNAL(clicked()), this, SLOT(clear())); + connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateClearButton(const QString&))); + int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); + + setObjectName(QString("ComboBoxLineEdit")); + setStyleSheet(QString("ComboBoxLineEdit { background-color: transparent; padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1)); +} + +void ComboBoxLineEdit::resizeEvent(QResizeEvent *) +{ + QSize sz = mClearButton->sizeHint(); + int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); + mClearButton->move(rect().right() - frameWidth - sz.width(), + (rect().bottom() + 1 - sz.height())/2); +} + +void ComboBoxLineEdit::updateClearButton(const QString& text) +{ + mClearButton->setVisible(!text.isEmpty()); +} diff --git a/apps/launcher/utils/comboboxlineedit.hpp b/apps/launcher/utils/comboboxlineedit.hpp new file mode 100644 index 0000000000..ba10731ae3 --- /dev/null +++ b/apps/launcher/utils/comboboxlineedit.hpp @@ -0,0 +1,35 @@ +/**************************************************************************** +** +** Copyright (c) 2007 Trolltech ASA +** +** Use, modification and distribution is allowed without limitation, +** warranty, liability or support of any kind. +** +****************************************************************************/ + +#ifndef LINEEDIT_H +#define LINEEDIT_H + +#include + +class QToolButton; + +class ComboBoxLineEdit : public QLineEdit +{ + Q_OBJECT + +public: + ComboBoxLineEdit(QWidget *parent = 0); + +protected: + void resizeEvent(QResizeEvent *); + +private slots: + void updateClearButton(const QString &text); + +private: + QToolButton *mClearButton; +}; + +#endif // LIENEDIT_H + From 1b9cf8c23fbcbc6591bcd45bd29fb6a34f5007c7 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Fri, 15 Feb 2013 01:20:48 +0100 Subject: [PATCH 09/37] More work on integrating the settings parser, profiles are handled correctly --- apps/launcher/datafilespage.cpp | 71 +++++++++++++++++---- apps/launcher/settings/launchersettings.cpp | 54 ++++++++++++++++ apps/launcher/settings/launchersettings.hpp | 3 + apps/launcher/settings/settingsbase.hpp | 16 +++-- apps/launcher/utils/profilescombobox.cpp | 28 ++++---- 5 files changed, 140 insertions(+), 32 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 12323b1f19..678f8cc3c2 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -293,22 +293,77 @@ void DataFilesPage::setupDataFiles() mPluginsModel->addPlugins(dataLocal); } + QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); + QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + + mProfilesComboBox->addItems(profiles); + + // Add the current profile if empty + if (mProfilesComboBox->findText(profile) == -1) + mProfilesComboBox->addItem(profile); + + if (mProfilesComboBox->findText(QString("Default")) == -1) + mProfilesComboBox->addItem(QString("Default")); + + if (profile.isEmpty()) { + mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(QString("Default"))); + } else { + mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(profile)); + } + loadSettings(); } void DataFilesPage::loadSettings() { qDebug() << "load settings"; + QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + + qDebug() << mLauncherSettings.values(QString("Profiles/Default"), Qt::MatchStartsWith); + + + + if (profile.isEmpty()) + return; + + + mMastersModel->uncheckAll(); + mPluginsModel->uncheckAll(); + + QStringList masters = mLauncherSettings.values(QString("Profiles/") + profile + QString("/master"), Qt::MatchExactly); + QStringList plugins = mLauncherSettings.values(QString("Profiles/") + profile + QString("/plugin"), Qt::MatchExactly); + qDebug() << "masters to check " << plugins; + + foreach (const QString &master, masters) { + QModelIndex index = mMastersModel->indexFromItem(mMastersModel->findItem(master)); + if (index.isValid()) + mMastersModel->setCheckState(index, Qt::Checked); + } + + foreach (const QString &plugin, plugins) { + QModelIndex index = mPluginsModel->indexFromItem(mPluginsModel->findItem(plugin)); + if (index.isValid()) + mPluginsModel->setCheckState(index, Qt::Checked); + } } void DataFilesPage::saveSettings() { QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + + if (profile.isEmpty()) { + profile = mProfilesComboBox->currentText(); + mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), profile); + } + qDebug() << "save settings" << profile; + mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); + mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); QStringList items = mMastersModel->checkedItems(); foreach(const QString &master, items) { + qDebug() << "setting " << master; mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), master); } @@ -482,17 +537,11 @@ void DataFilesPage::writeConfig(QString profile) void DataFilesPage::newProfile() { -// if (mNewProfileDialog->exec() == QDialog::Accepted) { - -// const QString text = mNewProfileDialog->lineEdit()->text(); -// mProfilesComboBox->addItem(text); -// mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(text)); -// } - - mDeleteProfileAction->setEnabled(false); - mProfilesComboBox->setCurrentIndex(-1); - mProfilesComboBox->setEditEnabled(true); - mProfilesComboBox->lineEdit()->setFocus(); + if (mNewProfileDialog->exec() == QDialog::Accepted) { + QString profile = mNewProfileDialog->lineEdit()->text(); + mProfilesComboBox->addItem(profile); + mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(profile)); + } } void DataFilesPage::updateOkButton(const QString &text) diff --git a/apps/launcher/settings/launchersettings.cpp b/apps/launcher/settings/launchersettings.cpp index c189c282fd..07502ea027 100644 --- a/apps/launcher/settings/launchersettings.cpp +++ b/apps/launcher/settings/launchersettings.cpp @@ -13,6 +13,60 @@ LauncherSettings::~LauncherSettings() { } +QStringList 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) { + qDebug() << "key is: " << currentKey << "value: " << settings.value(currentKey); + if (currentKey.startsWith(key)) + result.append(settings.value(currentKey)); + } + } + + return result; +} + +QStringList LauncherSettings::subKeys(const QString &key) +{ + QMap settings = SettingsBase::getSettings(); + QStringList keys = settings.keys(); + + 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)) { + + 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; +} bool LauncherSettings::writeFile(QTextStream &stream) { diff --git a/apps/launcher/settings/launchersettings.hpp b/apps/launcher/settings/launchersettings.hpp index cf4dd4c9ff..d78a75d458 100644 --- a/apps/launcher/settings/launchersettings.hpp +++ b/apps/launcher/settings/launchersettings.hpp @@ -9,6 +9,9 @@ public: LauncherSettings(); ~LauncherSettings(); + QStringList subKeys(const QString &key); + QStringList values(const QString &key, Qt::MatchFlags flags = Qt::MatchExactly); + bool writeFile(QTextStream &stream); }; diff --git a/apps/launcher/settings/settingsbase.hpp b/apps/launcher/settings/settingsbase.hpp index e09ea62038..361884da6f 100644 --- a/apps/launcher/settings/settingsbase.hpp +++ b/apps/launcher/settings/settingsbase.hpp @@ -24,12 +24,20 @@ public: inline void setValue(const QString &key, const QString &value) { - mSettings.insert(key, value); + QStringList values = mSettings.values(key); + if (!values.contains(value)) + mSettings.insert(key, value); } inline void setMultiValue(const QString &key, const QString &value) { - mSettings.insertMulti(key, value); + QStringList values = mSettings.values(key); + if (!values.contains(value)) { + qDebug() << "inserting " << value; + mSettings.insertMulti(key, value); + } else { + qDebug() << "not inserting " << value; + } } @@ -73,13 +81,11 @@ public: QStringList values = mCache.values(key); if (!values.contains(value)) { // QMap will replace the value if key exists, QMultiMap creates a new one - mCache.insert(key, value); + mCache.insertMulti(key, value); } } } - qDebug() << "HI THERE! " << mCache; - if (mSettings.isEmpty()) { mSettings = mCache; // This is the first time we read a file return true; diff --git a/apps/launcher/utils/profilescombobox.cpp b/apps/launcher/utils/profilescombobox.cpp index 3a75ba417a..a2c8668cb5 100644 --- a/apps/launcher/utils/profilescombobox.cpp +++ b/apps/launcher/utils/profilescombobox.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "profilescombobox.hpp" #include "comboboxlineedit.hpp" @@ -18,12 +19,11 @@ ProfilesComboBox::ProfilesComboBox(QWidget *parent) : connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(slotIndexChanged(int))); - + setInsertPolicy(QComboBox::NoInsert); } void ProfilesComboBox::setEditEnabled(bool editable) { - qDebug() << "called"; if (isEditable() == editable) return; @@ -50,29 +50,25 @@ void ProfilesComboBox::setEditEnabled(bool editable) void ProfilesComboBox::slotTextChanged(const QString &text) { - QString previous = itemText(currentIndex()); -// lineEdit()->setPalette(QApplication::palette()); + QPalette *palette = new QPalette(); + palette->setColor(QPalette::Text,Qt::red); - if (text.isEmpty()) - return; + int index = findText(text); - if (text == previous) - return; - - qDebug() << "textChanged"; - if (findText(text) != -1) { - QPalette *palette = new QPalette(); - palette->setColor(QPalette::Text,Qt::red); + if (text.isEmpty() || (index != -1 && index != currentIndex())) { lineEdit()->setPalette(*palette); + } else { + lineEdit()->setPalette(QApplication::palette()); } } void ProfilesComboBox::slotEditingFinished() { - qDebug() << "returnpressed"; QString current = currentText(); QString previous = itemText(currentIndex()); + qDebug() << current << previous; + if (current.isEmpty()) return; @@ -82,9 +78,9 @@ void ProfilesComboBox::slotEditingFinished() if (findText(current) != -1) return; - if (currentIndex() == -1) { - addItem(currentText()); + addItem(current); + setCurrentIndex(findText(current)); } else { setItemText(currentIndex(), current); emit(profileRenamed(previous, current)); From 990895fd2b9aab702c79a8e48fba2b6b6e3cf1c3 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Fri, 15 Feb 2013 14:12:25 +0100 Subject: [PATCH 10/37] Mainwindow size and position now gets saved/restored --- apps/launcher/maindialog.cpp | 14 ++++++++++++++ apps/launcher/utils/profilescombobox.cpp | 12 +++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index f48ea603bf..7b453671c7 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -169,6 +169,7 @@ bool MainDialog::setup() return false; } + loadSettings(); return true; } @@ -182,7 +183,14 @@ void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) void 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); } void MainDialog::saveSettings() @@ -193,6 +201,12 @@ void MainDialog::saveSettings() 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); + qDebug() << "size: " << width << height; } diff --git a/apps/launcher/utils/profilescombobox.cpp b/apps/launcher/utils/profilescombobox.cpp index a2c8668cb5..4c258dae60 100644 --- a/apps/launcher/utils/profilescombobox.cpp +++ b/apps/launcher/utils/profilescombobox.cpp @@ -69,6 +69,9 @@ void ProfilesComboBox::slotEditingFinished() qDebug() << current << previous; + if (currentIndex() == -1) + return; + if (current.isEmpty()) return; @@ -78,13 +81,8 @@ void ProfilesComboBox::slotEditingFinished() if (findText(current) != -1) return; - if (currentIndex() == -1) { - addItem(current); - setCurrentIndex(findText(current)); - } else { - setItemText(currentIndex(), current); - emit(profileRenamed(previous, current)); - } + setItemText(currentIndex(), current); + emit(profileRenamed(previous, current)); } void ProfilesComboBox::slotIndexChanged(int index) From 43e9ad87331d073d69c5d571acad50020263f849 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Fri, 15 Feb 2013 14:26:09 +0100 Subject: [PATCH 11/37] The text color of the profiles dialog now turns red on invalid names --- apps/launcher/utils/textinputdialog.cpp | 46 ++++++++++++++++--------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/apps/launcher/utils/textinputdialog.cpp b/apps/launcher/utils/textinputdialog.cpp index 16cadb6619..ec72e54328 100644 --- a/apps/launcher/utils/textinputdialog.cpp +++ b/apps/launcher/utils/textinputdialog.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -17,9 +18,19 @@ TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWid mButtonBox->addButton(QDialogButtonBox::Ok); mButtonBox->addButton(QDialogButtonBox::Cancel); - setMaximumHeight(height()); - setOkButtonEnabled(false); - setModal(true); + // Line edit + QValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore + mLineEdit = new LineEdit(this); + mLineEdit->setValidator(validator); + mLineEdit->setCompleter(0); + + QLabel *label = new QLabel(this); + label->setText(text); + + QVBoxLayout *dialogLayout = new QVBoxLayout(this); + dialogLayout->addWidget(label); + dialogLayout->addWidget(mLineEdit); + dialogLayout->addWidget(mButtonBox); // Messageboxes on mac have no title #ifndef Q_OS_MAC @@ -28,22 +39,13 @@ TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWid Q_UNUSED(title); #endif - QLabel *label = new QLabel(this); - label->setText(text); - - // Line edit - QValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore - mLineEdit = new LineEdit(this); - mLineEdit->setValidator(validator); - mLineEdit->setCompleter(0); - - QVBoxLayout *dialogLayout = new QVBoxLayout(this); - dialogLayout->addWidget(label); - dialogLayout->addWidget(mLineEdit); - dialogLayout->addWidget(mButtonBox); + setMaximumHeight(height()); + setOkButtonEnabled(false); + setModal(true); connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject())); + } int TextInputDialog::exec() @@ -55,7 +57,17 @@ int TextInputDialog::exec() void TextInputDialog::setOkButtonEnabled(bool enabled) { - QPushButton *okButton = mButtonBox->button(QDialogButtonBox::Ok); okButton->setEnabled(enabled); + + QPalette *palette = new QPalette(); + palette->setColor(QPalette::Text,Qt::red); + + if (enabled) { + mLineEdit->setPalette(QApplication::palette()); + } else { + // Existing profile name, make the text red + mLineEdit->setPalette(*palette); + } + } From 178cf2154e1d33d24ddd649387beab13c0696a0d Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 18 Feb 2013 17:59:08 +0100 Subject: [PATCH 12/37] Made checking/unchecking work with the new datafiles model --- apps/launcher/datafilespage.cpp | 333 +++++------------- apps/launcher/datafilespage.hpp | 6 +- apps/launcher/settings/gamesettings.cpp | 2 + .../fileorderlist/model/datafilesmodel.cpp | 9 +- 4 files changed, 95 insertions(+), 255 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index fe6c6f424f..ed24f881bd 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -56,12 +56,25 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam , QWidget(parent) { // Models - mMastersModel = new DataFilesModel(this); - mPluginsModel = new DataFilesModel(this); + mDataFilesModel = new DataFilesModel(this); + mDataFilesModel->setObjectName(QString("mDataFilesModel")); + + mMastersProxyModel = new QSortFilterProxyModel(); + mMastersProxyModel->setFilterRegExp(QString("^.*\\.esm")); + mMastersProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + mMastersProxyModel->setSourceModel(mDataFilesModel); mPluginsProxyModel = new QSortFilterProxyModel(); - mPluginsProxyModel->setDynamicSortFilter(true); - mPluginsProxyModel->setSourceModel(mPluginsModel); + mPluginsProxyModel->setObjectName(QString("mPluginsProxyModel")); + mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp")); + mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + mPluginsProxyModel->setSourceModel(mDataFilesModel); + + mFilterProxyModel = new QSortFilterProxyModel(); + mFilterProxyModel->setObjectName(QString("mFilterProxyModel")); + + mFilterProxyModel->setDynamicSortFilter(true); + mFilterProxyModel->setSourceModel(mPluginsProxyModel); // Filter toolbar QLabel *filterLabel = new QLabel(tr("&Filter:"), this); @@ -86,7 +99,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam unsigned int height = checkBox.sizeHint().height() + 4; mMastersTable = new QTableView(this); - mMastersTable->setModel(mMastersModel); + mMastersTable->setModel(mMastersProxyModel); mMastersTable->setObjectName("MastersTable"); mMastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); mMastersTable->setSelectionMode(QAbstractItemView::SingleSelection); @@ -109,7 +122,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mMastersTable->setColumnHidden(8, true); mPluginsTable = new QTableView(this); - mPluginsTable->setModel(mPluginsProxyModel); + mPluginsTable->setModel(mFilterProxyModel); mPluginsTable->setObjectName("PluginsTable"); mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); @@ -172,7 +185,14 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this); connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString))); + + connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + connect(mMastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + + connect(mPluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); + 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))); @@ -219,69 +239,20 @@ void DataFilesPage::createActions() mContextMenu->addAction(mUncheckAction); } -void DataFilesPage::readConfig() -{ -// // Don't read the config if no masters are found -// if (mMastersModel->rowCount() < 1) -// return; - -// QString profile = mProfilesComboBox->currentText(); - -// // Make sure we have no groups open -// while (!mLauncherConfig->group().isEmpty()) { -// mLauncherConfig->endGroup(); -// } - -// mLauncherConfig->beginGroup("Profiles"); -// mLauncherConfig->beginGroup(profile); - -// QStringList childKeys = mLauncherConfig->childKeys(); -// QStringList plugins; - -// // Sort the child keys numerical instead of alphabetically -// // i.e. Plugin1, Plugin2 instead of Plugin1, Plugin10 -// qSort(childKeys.begin(), childKeys.end(), naturalSortLessThanCI); - -// foreach (const QString &key, childKeys) { -// const QString keyValue = mLauncherConfig->value(key).toString(); - -// if (key.startsWith("Plugin")) { -// //QStringList checked = mPluginsModel->checkedItems(); -// EsmFile *file = mPluginsModel->findItem(keyValue); -// QModelIndex index = mPluginsModel->indexFromItem(file); - -// mPluginsModel->setCheckState(index, Qt::Checked); -// // Move the row to the top of te view -// //mPluginsModel->moveRow(index.row(), checked.count()); -// plugins << keyValue; -// } - -// if (key.startsWith("Master")) { -// EsmFile *file = mMastersModel->findItem(keyValue); -// mMastersModel->setCheckState(mMastersModel->indexFromItem(file), Qt::Checked); -// } -// } - -// qDebug() << plugins; -} - void DataFilesPage::setupDataFiles() { // Set the encoding to the one found in openmw.cfg or the default - mMastersModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252"))); - mPluginsModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252"))); + mDataFilesModel->setEncoding(mGameSettings.value(QString("encoding"), QString("win1252"))); QStringList paths = mGameSettings.getDataDirs(); foreach (const QString &path, paths) { - mMastersModel->addMasters(path); - mPluginsModel->addPlugins(path); + mDataFilesModel->addFiles(path); } QString dataLocal = mGameSettings.getDataLocal(); if (!dataLocal.isEmpty()) { - mMastersModel->addMasters(dataLocal); - mPluginsModel->addPlugins(dataLocal); + mDataFilesModel->addFiles(dataLocal); } QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); @@ -313,29 +284,26 @@ void DataFilesPage::loadSettings() qDebug() << mLauncherSettings.values(QString("Profiles/Default"), Qt::MatchStartsWith); - - if (profile.isEmpty()) return; - mMastersModel->uncheckAll(); - mPluginsModel->uncheckAll(); + mDataFilesModel->uncheckAll(); QStringList masters = mLauncherSettings.values(QString("Profiles/") + profile + QString("/master"), Qt::MatchExactly); QStringList plugins = mLauncherSettings.values(QString("Profiles/") + profile + QString("/plugin"), Qt::MatchExactly); qDebug() << "masters to check " << plugins; foreach (const QString &master, masters) { - QModelIndex index = mMastersModel->indexFromItem(mMastersModel->findItem(master)); + QModelIndex index = mDataFilesModel->indexFromItem(mDataFilesModel->findItem(master)); if (index.isValid()) - mMastersModel->setCheckState(index, Qt::Checked); + mDataFilesModel->setCheckState(index, Qt::Checked); } foreach (const QString &plugin, plugins) { - QModelIndex index = mPluginsModel->indexFromItem(mPluginsModel->findItem(plugin)); + QModelIndex index = mDataFilesModel->indexFromItem(mDataFilesModel->findItem(plugin)); if (index.isValid()) - mPluginsModel->setCheckState(index, Qt::Checked); + mDataFilesModel->setCheckState(index, Qt::Checked); } } @@ -352,178 +320,22 @@ void DataFilesPage::saveSettings() mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); - QStringList items = mMastersModel->checkedItems(); + QStringList items = mDataFilesModel->checkedItems(); - foreach(const QString &master, items) { - qDebug() << "setting " << master; - mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), master); - } + foreach(const QString &item, items) { - items.clear(); - items = mPluginsModel->checkedItems(); + if (item.endsWith(QString(".esm"), Qt::CaseInsensitive)) { + qDebug() << "setting " << item; + mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), item); - qDebug() << items.size(); - - foreach(const QString &plugin, items) { - qDebug() << "setting " << plugin; - mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), plugin); + } else if (item.endsWith(QString(".esp"), Qt::CaseInsensitive)) { + qDebug() << "setting " << item; + mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), item); + } } } -void DataFilesPage::writeConfig(QString profile) -{ - -// // Don't overwrite the config if no masters are found -// if (mMastersModel->rowCount() < 1) -// return; - -// QString pathStr = QString::fromStdString(mCfgMgr.getUserPath().string()); -// QDir userPath(pathStr); - -// if (!userPath.exists()) { -// if (!userPath.mkpath(pathStr)) { -// QMessageBox msgBox; -// msgBox.setWindowTitle("Error creating OpenMW configuration directory"); -// msgBox.setIcon(QMessageBox::Critical); -// msgBox.setStandardButtons(QMessageBox::Ok); -// msgBox.setText(tr("
Could not create %0

\ -// Please make sure you have the right permissions and try again.
").arg(pathStr)); -// msgBox.exec(); - -// qApp->quit(); -// return; -// } -// } -// // Open the OpenMW config as a QFile -// QFile file(pathStr.append("openmw.cfg")); - -// if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { -// // File cannot be opened or created -// QMessageBox msgBox; -// msgBox.setWindowTitle("Error writing OpenMW configuration file"); -// msgBox.setIcon(QMessageBox::Critical); -// msgBox.setStandardButtons(QMessageBox::Ok); -// msgBox.setText(tr("
Could not open or create %0

\ -// Please make sure you have the right permissions and try again.
").arg(file.fileName())); -// msgBox.exec(); - -// qApp->quit(); -// return; -// } - -// QTextStream in(&file); -// QByteArray buffer; - -// // Remove all previous entries from config -// while (!in.atEnd()) { -// QString line = in.readLine(); -// if (!line.startsWith("master") && -// !line.startsWith("plugin") && -// !line.startsWith("data") && -// !line.startsWith("data-local")) -// { -// buffer += line += "\n"; -// } -// } - -// file.close(); - -// // Now we write back the other config entries -// if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { -// QMessageBox msgBox; -// msgBox.setWindowTitle("Error writing OpenMW configuration file"); -// msgBox.setIcon(QMessageBox::Critical); -// msgBox.setStandardButtons(QMessageBox::Ok); -// msgBox.setText(tr("
Could not write to %0

\ -// Please make sure you have the right permissions and try again.
").arg(file.fileName())); -// msgBox.exec(); - -// qApp->quit(); -// return; -// } - -// if (!buffer.isEmpty()) { -// file.write(buffer); -// } - -// QTextStream gameConfig(&file); - - -// QString path; - -// // data= directories -// for (Files::PathContainer::iterator it = mDataDirs.begin(); it != mDataDirs.end(); ++it) { -// path = QString::fromStdString(it->string()); -// path.remove(QChar('\"')); - -// // Make sure the string is quoted when it contains spaces -// if (path.contains(" ")) { -// gameConfig << "data=\"" << path << "\"" << endl; -// } else { -// gameConfig << "data=" << path << endl; -// } -// } - -// // data-local directory -// if (!mDataLocal.empty()) { -// path = QString::fromStdString(mDataLocal.front().string()); -// path.remove(QChar('\"')); - -// if (path.contains(" ")) { -// gameConfig << "data-local=\"" << path << "\"" << endl; -// } else { -// gameConfig << "data-local=" << path << endl; -// } -// } - - -// if (profile.isEmpty()) -// profile = mProfilesComboBox->currentText(); - -// if (profile.isEmpty()) -// return; - -// // Make sure we have no groups open -// while (!mLauncherConfig->group().isEmpty()) { -// mLauncherConfig->endGroup(); -// } - -// mLauncherConfig->beginGroup("Profiles"); -// mLauncherConfig->setValue("CurrentProfile", profile); - -// // Open the profile-name subgroup -// mLauncherConfig->beginGroup(profile); -// mLauncherConfig->remove(""); // Clear the subgroup - -// // Now write the masters to the configs -// const QStringList masters = mMastersModel->checkedItems(); - -// // We don't use foreach because we need i -// for (int i = 0; i < masters.size(); ++i) { -// const QString currentMaster = masters.at(i); - -// mLauncherConfig->setValue(QString("Master%0").arg(i), currentMaster); -// gameConfig << "master=" << currentMaster << endl; - -// } - -// // And finally write all checked plugins -// const QStringList plugins = mPluginsModel->checkedItems(); - -// for (int i = 0; i < plugins.size(); ++i) { -// const QString currentPlugin = plugins.at(i); -// mLauncherConfig->setValue(QString("Plugin%1").arg(i), currentPlugin); -// gameConfig << "plugin=" << currentPlugin << endl; -// } - -// file.close(); -// mLauncherConfig->endGroup(); -// mLauncherConfig->endGroup(); -// mLauncherConfig->sync(); -} - - void DataFilesPage::newProfile() { if (mNewProfileDialog->exec() == QDialog::Accepted) { @@ -599,7 +411,13 @@ void DataFilesPage::check() if (!index.isValid()) return; - mPluginsModel->setCheckState(index, Qt::Checked); + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (!sourceIndex.isValid()) + return; + + mDataFilesModel->setCheckState(sourceIndex, Qt::Checked); } } @@ -619,13 +437,19 @@ void DataFilesPage::uncheck() if (!index.isValid()) return; - mPluginsModel->setCheckState(index, Qt::Unchecked); + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (!sourceIndex.isValid()) + return; + + mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked); } } void DataFilesPage::refresh() { - mPluginsModel->sort(0); + mDataFilesModel->sort(0); // Refresh the plugins table mPluginsTable->scrollToTop(); @@ -643,28 +467,35 @@ void DataFilesPage::setCheckState(QModelIndex index) if (!object) return; - if (object->objectName() == QLatin1String("PluginsTable")) { - QModelIndex sourceIndex = mPluginsProxyModel->mapToSource(index); - (mPluginsModel->checkState(sourceIndex) == Qt::Checked) - ? mPluginsModel->setCheckState(sourceIndex, Qt::Unchecked) - : mPluginsModel->setCheckState(sourceIndex, Qt::Checked); + if (object->objectName() == QLatin1String("PluginsTable")) { + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (sourceIndex.isValid()) { + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked) + : mDataFilesModel->setCheckState(sourceIndex, Qt::Checked); + } } if (object->objectName() == QLatin1String("MastersTable")) { - (mMastersModel->checkState(index) == Qt::Checked) - ? mMastersModel->setCheckState(index, Qt::Unchecked) - : mMastersModel->setCheckState(index, Qt::Checked); + QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index); + + if (sourceIndex.isValid()) { + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked) + : mDataFilesModel->setCheckState(sourceIndex, Qt::Checked); + } } return; - } void DataFilesPage::filterChanged(const QString filter) { QRegExp regExp(filter, Qt::CaseInsensitive, QRegExp::FixedString); - mPluginsProxyModel->setFilterRegExp(regExp); + mFilterProxyModel->setFilterRegExp(regExp); } void DataFilesPage::profileChanged(const QString &previous, const QString ¤t) @@ -690,8 +521,7 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre saveSettings(); mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), current); - mMastersModel->uncheckAll(); - mPluginsModel->uncheckAll(); + mDataFilesModel->uncheckAll(); loadSettings(); } @@ -712,8 +542,7 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre // Remove the profile from the combobox mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous)); - mMastersModel->uncheckAll(); - mPluginsModel->uncheckAll(); + mDataFilesModel->uncheckAll(); loadSettings(); } @@ -737,7 +566,13 @@ void DataFilesPage::showContextMenu(const QPoint &point) if (!index.isValid()) return; - (mPluginsModel->checkState(index) == Qt::Checked) + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (!sourceIndex.isValid()) + return; + + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) ? mUncheckAction->setEnabled(true) : mCheckAction->setEnabled(true); } diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index ef03e4ad47..e6b4194bdc 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -56,10 +56,12 @@ public slots: void refresh(); private: - DataFilesModel *mMastersModel; - DataFilesModel *mPluginsModel; + DataFilesModel *mDataFilesModel; QSortFilterProxyModel *mPluginsProxyModel; + QSortFilterProxyModel *mMastersProxyModel; + + QSortFilterProxyModel *mFilterProxyModel; QTableView *mMastersTable; QTableView *mPluginsTable; diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 5f0fb77bc4..f87937228a 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -155,4 +155,6 @@ bool GameSettings::writeFile(QTextStream &stream) } } + + return true; } diff --git a/components/fileorderlist/model/datafilesmodel.cpp b/components/fileorderlist/model/datafilesmodel.cpp index 09cffad7ac..036394800a 100644 --- a/components/fileorderlist/model/datafilesmodel.cpp +++ b/components/fileorderlist/model/datafilesmodel.cpp @@ -204,13 +204,14 @@ bool DataFilesModel::setData(const QModelIndex &index, const QVariant &value, in return false; if (role == Qt::CheckStateRole) { - - emit layoutAboutToBeChanged(); - QString name = item(index.row())->fileName(); mCheckStates[name] = static_cast(value.toInt()); - emit layoutChanged(); + // Force a redraw of the view since unchecking one item can affect another + QModelIndex firstIndex = indexFromItem(mFiles.first()); + QModelIndex lastIndex = indexFromItem(mFiles.last()); + + emit dataChanged(firstIndex, lastIndex); return true; } From bcf4f962098a5e48eb3662b045d8692b50cf0eda Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 18 Feb 2013 23:10:50 +0100 Subject: [PATCH 13/37] Added writing masters/plugins to openmw.cfg --- apps/launcher/datafilespage.cpp | 21 +++++---------------- apps/launcher/settings/gamesettings.hpp | 12 ++++++++++++ apps/launcher/settings/settingsbase.hpp | 7 +------ 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index ed24f881bd..e0ebefa589 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -57,7 +57,6 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam { // Models mDataFilesModel = new DataFilesModel(this); - mDataFilesModel->setObjectName(QString("mDataFilesModel")); mMastersProxyModel = new QSortFilterProxyModel(); mMastersProxyModel->setFilterRegExp(QString("^.*\\.esm")); @@ -65,14 +64,11 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mMastersProxyModel->setSourceModel(mDataFilesModel); mPluginsProxyModel = new QSortFilterProxyModel(); - mPluginsProxyModel->setObjectName(QString("mPluginsProxyModel")); mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp")); mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); mPluginsProxyModel->setSourceModel(mDataFilesModel); mFilterProxyModel = new QSortFilterProxyModel(); - mFilterProxyModel->setObjectName(QString("mFilterProxyModel")); - mFilterProxyModel->setDynamicSortFilter(true); mFilterProxyModel->setSourceModel(mPluginsProxyModel); @@ -155,7 +151,6 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam QList sizeList; sizeList << mLauncherSettings.value(QString("General/MastersTable/width"), QString("200")).toInt(); sizeList << mLauncherSettings.value(QString("General/PluginTable/width"), QString("340")).toInt(); - qDebug() << sizeList; mSplitter->setSizes(sizeList); @@ -279,20 +274,15 @@ void DataFilesPage::setupDataFiles() void DataFilesPage::loadSettings() { - qDebug() << "load settings"; QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); - qDebug() << mLauncherSettings.values(QString("Profiles/Default"), Qt::MatchStartsWith); - if (profile.isEmpty()) return; - mDataFilesModel->uncheckAll(); QStringList masters = mLauncherSettings.values(QString("Profiles/") + profile + QString("/master"), Qt::MatchExactly); QStringList plugins = mLauncherSettings.values(QString("Profiles/") + profile + QString("/plugin"), Qt::MatchExactly); - qDebug() << "masters to check " << plugins; foreach (const QString &master, masters) { QModelIndex index = mDataFilesModel->indexFromItem(mDataFilesModel->findItem(master)); @@ -316,21 +306,23 @@ void DataFilesPage::saveSettings() mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), profile); } - qDebug() << "save settings" << profile; mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); + mGameSettings.remove(QString("master")); + mGameSettings.remove(QString("plugin")); + QStringList items = mDataFilesModel->checkedItems(); foreach(const QString &item, items) { if (item.endsWith(QString(".esm"), Qt::CaseInsensitive)) { - qDebug() << "setting " << item; mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), item); + mGameSettings.setMultiValue(QString("master"), item); } else if (item.endsWith(QString(".esp"), Qt::CaseInsensitive)) { - qDebug() << "setting " << item; mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), item); + mGameSettings.setMultiValue(QString("plugin"), item); } } @@ -500,7 +492,6 @@ void DataFilesPage::filterChanged(const QString filter) void DataFilesPage::profileChanged(const QString &previous, const QString ¤t) { - qDebug() << "Profile is changed from: " << previous << " to " << current; // Prevent the deletion of the default profile if (current == QLatin1String("Default")) { mDeleteProfileAction->setEnabled(false); @@ -527,7 +518,6 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre void DataFilesPage::profileRenamed(const QString &previous, const QString ¤t) { - qDebug() << "rename"; if (previous.isEmpty()) return; @@ -577,7 +567,6 @@ void DataFilesPage::showContextMenu(const QPoint &point) : mCheckAction->setEnabled(true); } - // Show menu mContextMenu->exec(globalPos); diff --git a/apps/launcher/settings/gamesettings.hpp b/apps/launcher/settings/gamesettings.hpp index 717ce6e877..8aac1552da 100644 --- a/apps/launcher/settings/gamesettings.hpp +++ b/apps/launcher/settings/gamesettings.hpp @@ -29,6 +29,18 @@ public: mSettings.insert(key, value); } + inline void setMultiValue(const QString &key, const QString &value) + { + QStringList values = mSettings.values(key); + if (!values.contains(value)) + mSettings.insertMulti(key, value); + } + + inline void remove(const QString &key) + { + mSettings.remove(key); + } + inline QStringList getDataDirs() { return mDataDirs; } inline void addDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.append(dir); } inline QString getDataLocal() {return mDataLocal; } diff --git a/apps/launcher/settings/settingsbase.hpp b/apps/launcher/settings/settingsbase.hpp index 361884da6f..e70bc0d721 100644 --- a/apps/launcher/settings/settingsbase.hpp +++ b/apps/launcher/settings/settingsbase.hpp @@ -32,15 +32,10 @@ public: inline void setMultiValue(const QString &key, const QString &value) { QStringList values = mSettings.values(key); - if (!values.contains(value)) { - qDebug() << "inserting " << value; + if (!values.contains(value)) mSettings.insertMulti(key, value); - } else { - qDebug() << "not inserting " << value; - } } - inline void remove(const QString &key) { mSettings.remove(key); 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 14/37] 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(); } From 2172fb42298a4faddc7a0ae2a37a04aa3a4e15b1 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Tue, 19 Feb 2013 16:41:33 +0100 Subject: [PATCH 15/37] Added checkable message box class --- apps/launcher/CMakeLists.txt | 5 +- apps/launcher/utils/checkablemessagebox.cpp | 243 ++++++++++++++++++++ apps/launcher/utils/checkablemessagebox.hpp | 71 ++++++ 3 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 apps/launcher/utils/checkablemessagebox.cpp create mode 100644 apps/launcher/utils/checkablemessagebox.hpp diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 59cccad5fa..b2e6c70098 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -11,6 +11,7 @@ set(LAUNCHER settings/graphicssettings.cpp settings/launchersettings.cpp + utils/checkablemessagebox.cpp utils/comboboxlineedit.cpp utils/profilescombobox.cpp utils/textinputdialog.cpp @@ -31,7 +32,8 @@ set(LAUNCHER_HEADER settings/launchersettings.hpp settings/settingsbase.hpp - utils/comboboxlineedit.cpp + utils/checkablemessagebox.hpp + utils/comboboxlineedit.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp ) @@ -45,6 +47,7 @@ set(LAUNCHER_HEADER_MOC model/pluginsproxymodel.hpp + utils/checkablemessagebox.hpp utils/comboboxlineedit.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp diff --git a/apps/launcher/utils/checkablemessagebox.cpp b/apps/launcher/utils/checkablemessagebox.cpp new file mode 100644 index 0000000000..8aa01d1018 --- /dev/null +++ b/apps/launcher/utils/checkablemessagebox.cpp @@ -0,0 +1,243 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "checkablemessagebox.hpp" + + +/* + class CheckableMessageBox + Modified from the one used in Qt Creator + + A messagebox suitable for questions with a + "Do not ask me again" checkbox. + + Emulates the QMessageBox API with + static conveniences. The message label can open external URLs. +*/ + + +class CheckableMessageBoxPrivate +{ +public: + CheckableMessageBoxPrivate(QDialog *q) + : clickedButton(0) + { + QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + + pixmapLabel = new QLabel(q); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(pixmapLabel->sizePolicy().hasHeightForWidth()); + pixmapLabel->setSizePolicy(sizePolicy); + pixmapLabel->setVisible(false); + + QSpacerItem *pixmapSpacer = + new QSpacerItem(0, 5, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding); + + messageLabel = new QLabel(q); + messageLabel->setMinimumSize(QSize(300, 0)); + messageLabel->setWordWrap(true); + messageLabel->setOpenExternalLinks(true); + messageLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse); + + QSpacerItem *checkBoxRightSpacer = + new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum); + QSpacerItem *buttonSpacer = + new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::Minimum); + + checkBox = new QCheckBox(q); + checkBox->setText(CheckableMessageBox::tr("Do not ask again")); + + buttonBox = new QDialogButtonBox(q); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + QVBoxLayout *verticalLayout = new QVBoxLayout(); + verticalLayout->addWidget(pixmapLabel); + verticalLayout->addItem(pixmapSpacer); + + QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->addLayout(verticalLayout); + horizontalLayout_2->addWidget(messageLabel); + + QHBoxLayout *horizontalLayout = new QHBoxLayout(); + horizontalLayout->addWidget(checkBox); + horizontalLayout->addItem(checkBoxRightSpacer); + + QVBoxLayout *verticalLayout_2 = new QVBoxLayout(q); + verticalLayout_2->addLayout(horizontalLayout_2); + verticalLayout_2->addLayout(horizontalLayout); + verticalLayout_2->addItem(buttonSpacer); + verticalLayout_2->addWidget(buttonBox); + } + + QLabel *pixmapLabel; + QLabel *messageLabel; + QCheckBox *checkBox; + QDialogButtonBox *buttonBox; + QAbstractButton *clickedButton; +}; + +CheckableMessageBox::CheckableMessageBox(QWidget *parent) : + QDialog(parent), + d(new CheckableMessageBoxPrivate(this)) +{ + setModal(true); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + connect(d->buttonBox, SIGNAL(accepted()), SLOT(accept())); + connect(d->buttonBox, SIGNAL(rejected()), SLOT(reject())); + connect(d->buttonBox, SIGNAL(clicked(QAbstractButton*)), + SLOT(slotClicked(QAbstractButton*))); +} + +CheckableMessageBox::~CheckableMessageBox() +{ + delete d; +} + +void CheckableMessageBox::slotClicked(QAbstractButton *b) +{ + d->clickedButton = b; +} + +QAbstractButton *CheckableMessageBox::clickedButton() const +{ + return d->clickedButton; +} + +QDialogButtonBox::StandardButton CheckableMessageBox::clickedStandardButton() const +{ + if (d->clickedButton) + return d->buttonBox->standardButton(d->clickedButton); + return QDialogButtonBox::NoButton; +} + +QString CheckableMessageBox::text() const +{ + return d->messageLabel->text(); +} + +void CheckableMessageBox::setText(const QString &t) +{ + d->messageLabel->setText(t); +} + +QPixmap CheckableMessageBox::iconPixmap() const +{ + if (const QPixmap *p = d->pixmapLabel->pixmap()) + return QPixmap(*p); + return QPixmap(); +} + +void CheckableMessageBox::setIconPixmap(const QPixmap &p) +{ + d->pixmapLabel->setPixmap(p); + d->pixmapLabel->setVisible(!p.isNull()); +} + +bool CheckableMessageBox::isChecked() const +{ + return d->checkBox->isChecked(); +} + +void CheckableMessageBox::setChecked(bool s) +{ + d->checkBox->setChecked(s); +} + +QString CheckableMessageBox::checkBoxText() const +{ + return d->checkBox->text(); +} + +void CheckableMessageBox::setCheckBoxText(const QString &t) +{ + d->checkBox->setText(t); +} + +bool CheckableMessageBox::isCheckBoxVisible() const +{ + return d->checkBox->isVisible(); +} + +void CheckableMessageBox::setCheckBoxVisible(bool v) +{ + d->checkBox->setVisible(v); +} + +QDialogButtonBox::StandardButtons CheckableMessageBox::standardButtons() const +{ + return d->buttonBox->standardButtons(); +} + +void CheckableMessageBox::setStandardButtons(QDialogButtonBox::StandardButtons s) +{ + d->buttonBox->setStandardButtons(s); +} + +QPushButton *CheckableMessageBox::button(QDialogButtonBox::StandardButton b) const +{ + return d->buttonBox->button(b); +} + +QPushButton *CheckableMessageBox::addButton(const QString &text, QDialogButtonBox::ButtonRole role) +{ + return d->buttonBox->addButton(text, role); +} + +QDialogButtonBox::StandardButton CheckableMessageBox::defaultButton() const +{ + foreach (QAbstractButton *b, d->buttonBox->buttons()) + if (QPushButton *pb = qobject_cast(b)) + if (pb->isDefault()) + return d->buttonBox->standardButton(pb); + return QDialogButtonBox::NoButton; +} + +void CheckableMessageBox::setDefaultButton(QDialogButtonBox::StandardButton s) +{ + if (QPushButton *b = d->buttonBox->button(s)) { + b->setDefault(true); + b->setFocus(); + } +} + +QDialogButtonBox::StandardButton +CheckableMessageBox::question(QWidget *parent, + const QString &title, + const QString &question, + const QString &checkBoxText, + bool *checkBoxSetting, + QDialogButtonBox::StandardButtons buttons, + QDialogButtonBox::StandardButton defaultButton) +{ + CheckableMessageBox mb(parent); + mb.setWindowTitle(title); + mb.setIconPixmap(QMessageBox::standardIcon(QMessageBox::Question)); + mb.setText(question); + mb.setCheckBoxText(checkBoxText); + mb.setChecked(*checkBoxSetting); + mb.setStandardButtons(buttons); + mb.setDefaultButton(defaultButton); + mb.exec(); + *checkBoxSetting = mb.isChecked(); + return mb.clickedStandardButton(); +} + +QMessageBox::StandardButton CheckableMessageBox::dialogButtonBoxToMessageBoxButton(QDialogButtonBox::StandardButton db) +{ + return static_cast(int(db)); +} diff --git a/apps/launcher/utils/checkablemessagebox.hpp b/apps/launcher/utils/checkablemessagebox.hpp new file mode 100644 index 0000000000..ceb437d4d9 --- /dev/null +++ b/apps/launcher/utils/checkablemessagebox.hpp @@ -0,0 +1,71 @@ +#ifndef CHECKABLEMESSAGEBOX_HPP +#define CHECKABLEMESSAGEBOX_HPP + +#include +#include +#include + +class CheckableMessageBoxPrivate; + +class CheckableMessageBox : public QDialog +{ + Q_OBJECT + Q_PROPERTY(QString text READ text WRITE setText) + Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap) + Q_PROPERTY(bool isChecked READ isChecked WRITE setChecked) + Q_PROPERTY(QString checkBoxText READ checkBoxText WRITE setCheckBoxText) + Q_PROPERTY(QDialogButtonBox::StandardButtons buttons READ standardButtons WRITE setStandardButtons) + Q_PROPERTY(QDialogButtonBox::StandardButton defaultButton READ defaultButton WRITE setDefaultButton) + +public: + explicit CheckableMessageBox(QWidget *parent); + virtual ~CheckableMessageBox(); + + static QDialogButtonBox::StandardButton + question(QWidget *parent, + const QString &title, + const QString &question, + const QString &checkBoxText, + bool *checkBoxSetting, + QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Yes|QDialogButtonBox::No, + QDialogButtonBox::StandardButton defaultButton = QDialogButtonBox::No); + + QString text() const; + void setText(const QString &); + + bool isChecked() const; + void setChecked(bool s); + + QString checkBoxText() const; + void setCheckBoxText(const QString &); + + bool isCheckBoxVisible() const; + void setCheckBoxVisible(bool); + + QDialogButtonBox::StandardButtons standardButtons() const; + void setStandardButtons(QDialogButtonBox::StandardButtons s); + QPushButton *button(QDialogButtonBox::StandardButton b) const; + QPushButton *addButton(const QString &text, QDialogButtonBox::ButtonRole role); + + QDialogButtonBox::StandardButton defaultButton() const; + void setDefaultButton(QDialogButtonBox::StandardButton s); + + // See static QMessageBox::standardPixmap() + QPixmap iconPixmap() const; + void setIconPixmap (const QPixmap &p); + + // Query the result + QAbstractButton *clickedButton() const; + QDialogButtonBox::StandardButton clickedStandardButton() const; + + // Conversion convenience + static QMessageBox::StandardButton dialogButtonBoxToMessageBoxButton(QDialogButtonBox::StandardButton); + +private slots: + void slotClicked(QAbstractButton *b); + +private: + CheckableMessageBoxPrivate *d; +}; + +#endif // CHECKABLEMESSAGEBOX_HPP From 18d01cd65a585abbaf1b7f197d2af283f922c7a8 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Wed, 20 Feb 2013 19:27:04 +0100 Subject: [PATCH 16/37] Implemented a first-run dialog to import Morrowind.ini settings --- apps/launcher/main.cpp | 166 +------- apps/launcher/maindialog.cpp | 427 +++++++++++++++++--- apps/launcher/maindialog.hpp | 31 +- apps/launcher/settings/gamesettings.cpp | 34 +- apps/launcher/settings/gamesettings.hpp | 5 + apps/launcher/utils/checkablemessagebox.cpp | 43 +- apps/launcher/utils/checkablemessagebox.hpp | 43 +- 7 files changed, 493 insertions(+), 256 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index ba84518c1e..5d57dce551 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -1,23 +1,6 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include #include "maindialog.hpp" -#include "settings/gamesettings.hpp" -#include "settings/graphicssettings.hpp" -#include "settings/launchersettings.hpp" - int main(int argc, char *argv[]) { @@ -45,154 +28,7 @@ int main(int argc, char *argv[]) QDir::setCurrent(dir.absolutePath()); - // Create setting file handlers - - Files::ConfigurationManager cfgMgr; - QString userPath = QString::fromStdString(cfgMgr.getUserPath().string()); - QString globalPath = QString::fromStdString(cfgMgr.getGlobalPath().string()); - - GameSettings gameSettings(cfgMgr); - GraphicsSettings graphicsSettings; - LauncherSettings launcherSettings; - - QStringList paths; - paths.append(userPath + QString("openmw.cfg")); - paths.append(QString("openmw.cfg")); - paths.append(globalPath + QString("openmw.cfg")); - - foreach (const QString &path, paths) { - qDebug() << "Loading: " << path; - QFile file(path); - if (file.exists()) { - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error opening OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QObject::tr("
Could not open %0 for reading

\ - Please make sure you have the right permissions \ - and try again.
").arg(file.fileName())); - msgBox.exec(); - return 0; - } - QTextStream stream(&file); - stream.setCodec(QTextCodec::codecForName("UTF-8")); - - gameSettings.readFile(stream); - } - file.close(); - } - - if (gameSettings.getDataDirs().isEmpty()) - { - QMessageBox msgBox; - msgBox.setWindowTitle("Error detecting Morrowind installation"); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setStandardButtons(QMessageBox::Cancel); - msgBox.setText(QObject::tr("
Could not find the Data Files location

\ - The directory containing the data files was not found.

\ - Press \"Browse...\" to specify the location manually.
")); - - QAbstractButton *dirSelectButton = - msgBox.addButton(QObject::tr("B&rowse..."), QMessageBox::ActionRole); - - msgBox.exec(); - - QString selectedFile; - if (msgBox.clickedButton() == dirSelectButton) { - selectedFile = QFileDialog::getOpenFileName( - NULL, - QObject::tr("Select master file"), - QDir::currentPath(), - QString("Morrowind master file (*.esm)")); - } - - if (selectedFile.isEmpty()) - return 0; // Cancel was clicked; - - qDebug() << selectedFile; - QFileInfo info(selectedFile); - - // Add the new dir to the settings file and to the data dir container - gameSettings.setValue(QString("data"), info.absolutePath()); - gameSettings.addDataDir(info.absolutePath()); - - } - - // On to the graphics settings - QFile localDefault(QString("settings-default.cfg")); - QFile globalDefault(globalPath + QString("settings-default.cfg")); - - if (!localDefault.exists() && !globalDefault.exists()) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error reading OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QObject::tr("
Could not find settings-default.cfg

\ - The problem may be due to an incomplete installation of OpenMW.
\ - Reinstalling OpenMW may resolve the problem.")); - msgBox.exec(); - return 0; - } - - paths.clear(); - paths.append(globalPath + QString("settings-default.cfg")); - paths.append(QString("settings-default.cfg")); - paths.append(userPath + QString("settings.cfg")); - - foreach (const QString &path, paths) { - qDebug() << "Loading: " << path; - QFile file(path); - if (file.exists()) { - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error opening OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QObject::tr("
Could not open %0 for reading

\ - Please make sure you have the right permissions \ - and try again.
").arg(file.fileName())); - msgBox.exec(); - return 0; - } - QTextStream stream(&file); - stream.setCodec(QTextCodec::codecForName("UTF-8")); - - graphicsSettings.readFile(stream); - } - file.close(); - } - - // Now the launcher settings - paths.clear(); - paths.append(QString("launcher.cfg")); - paths.append(userPath + QString("launcher.cfg")); - - foreach (const QString &path, paths) { - qDebug() << "Loading: " << path; - QFile file(path); - if (file.exists()) { - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error opening OpenMW configuration file"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QObject::tr("
Could not open %0 for reading

\ - Please make sure you have the right permissions \ - and try again.
").arg(file.fileName())); - msgBox.exec(); - return 0; - } - QTextStream stream(&file); - stream.setCodec(QTextCodec::codecForName("UTF-8")); - - launcherSettings.readFile(stream); - } - file.close(); - } - - - MainDialog mainWin(gameSettings, graphicsSettings, launcherSettings); + MainDialog mainWin; if (mainWin.setup()) { mainWin.show(); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 15f2690dad..77526677b8 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -1,9 +1,6 @@ #include -#include "settings/gamesettings.hpp" -#include "settings/graphicssettings.hpp" -#include "settings/launchersettings.hpp" - +#include "utils/checkablemessagebox.hpp" #include "utils/profilescombobox.hpp" #include "maindialog.hpp" @@ -11,13 +8,8 @@ #include "graphicspage.hpp" #include "datafilespage.hpp" -MainDialog::MainDialog(GameSettings &gameSettings, - GraphicsSettings &graphicsSettings, - LauncherSettings &launcherSettings) - : mGameSettings(gameSettings) - , mGraphicsSettings(graphicsSettings) - , mLauncherSettings(launcherSettings) - +MainDialog::MainDialog() + : mGameSettings(mCfgMgr) { QWidget *centralWidget = new QWidget(this); setCentralWidget(centralWidget); @@ -95,7 +87,6 @@ MainDialog::MainDialog(GameSettings &gameSettings, connect(buttonBox, SIGNAL(accepted()), this, SLOT(play())); createIcons(); - createPages(); } void MainDialog::createIcons() @@ -161,14 +152,148 @@ void MainDialog::createPages() } +bool MainDialog::showFirstRunDialog() +{ + CheckableMessageBox msgBox(this); + msgBox.setWindowTitle(tr("Morrowind installation detected")); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxQuestion); + int size = QApplication::style()->pixelMetric(QStyle::PM_MessageBoxIconSize); + msgBox.setIconPixmap(icon.pixmap(size, size)); + + + QAbstractButton *importerButton = + msgBox.addButton(tr("Import"), QDialogButtonBox::AcceptRole); // ActionRole doesn't work?! + QAbstractButton *skipButton = + msgBox.addButton(tr("Skip"), QDialogButtonBox::RejectRole); + + Q_UNUSED(skipButton); // Surpress compiler unused warning + + msgBox.setStandardButtons(QDialogButtonBox::NoButton); + + msgBox.setText(tr("
An existing Morrowind installation was detected

\ + Would you like to import settings from Morrowind.ini?
")); + + msgBox.setCheckBoxText(tr("Include selected masters and plugins (creates a new profile)")); + msgBox.exec(); + + + if (msgBox.clickedButton() == importerButton) { + + QString iniPath; + + foreach (const QString &path, mGameSettings.getDataDirs()) { + QDir dir(path); + dir.setPath(dir.canonicalPath()); // Resolve symlinks + + if (!dir.cdUp()) + continue; // Cannot move from Data Files + + if (dir.exists(QString("Morrowind.ini"))) + iniPath = dir.absoluteFilePath(QString("Morrowind.ini")); + } + + if (iniPath.isEmpty()) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error reading Morrowind configuration file")); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not find Morrowind.ini

\ + The problem may be due to an incomplete installation of Morrowind.
\ + Reinstalling Morrowind may resolve the problem.")); + msgBox.exec(); + return false; + } + + // Create the file if it doesn't already exist, else the importer will fail + QString path = QString::fromStdString(mCfgMgr.getUserPath().string()) + QString("openmw.cfg"); + QFile file(path); + + if (!file.exists()) { + if (!file.open(QIODevice::ReadWrite)) { + // File cannot be created + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not open or create %0 for writing

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return false; + } + + file.close(); + } + + // Construct the arguments to run the importer + QStringList arguments; + + if (msgBox.isChecked()) + arguments.append(QString("-g")); + + arguments.append(iniPath); + arguments.append(path); + + if (!startProgram(QString("mwiniimport"), arguments, false)) + return false; + + // Re-read the game settings + mGameSettings.clear(); + + if (!setupGameSettings()) + return false; + + // Add a new profile + if (msgBox.isChecked()) { + qDebug() << "add a new profile"; + mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), QString("Imported")); + + mLauncherSettings.remove(QString("Profiles/Imported/master")); + mLauncherSettings.remove(QString("Profiles/Imported/plugin")); + + QStringList masters = mGameSettings.values(QString("master")); + QStringList plugins = mGameSettings.values(QString("plugin")); + + foreach (const QString &master, masters) { + mLauncherSettings.setMultiValue(QString("Profiles/Imported/master"), master); + } + + foreach (const QString &plugin, plugins) { + mLauncherSettings.setMultiValue(QString("Profiles/Imported/plugin"), plugin); + } + } + + } + + return true; +} bool MainDialog::setup() { - // Call this so we can exit on Ogre errors before mainwindow is shown - if (!mGraphicsPage->setupOgre()) { + if (!setupLauncherSettings()) return false; + + if (!setupGameSettings()) + return false; + + if (!setupGraphicsSettings()) + return false; + + // Check if we need to show the importer + if (mLauncherSettings.value(QString("General/firstrun"), QString("true")) == QLatin1String("true")) + { + if (!showFirstRunDialog()) + return false; } + // Now create the pages as they need the settings + createPages(); + + // Call this so we can exit on Ogre errors before mainwindow is shown + if (!mGraphicsPage->setupOgre()) + return false; + loadSettings(); return true; } @@ -181,6 +306,164 @@ void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) mPagesWidget->setCurrentIndex(mIconWidget->row(current)); } +bool MainDialog::setupLauncherSettings() +{ + QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string()); + + QStringList paths; + paths.append(QString("launcher.cfg")); + paths.append(userPath + QString("launcher.cfg")); + + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error opening OpenMW configuration file")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return false; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + mLauncherSettings.readFile(stream); + } + file.close(); + } + + return true; +} + +bool MainDialog::setupGameSettings() +{ + QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string()); + QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string()); + + QStringList paths; + paths.append(userPath + QString("openmw.cfg")); + paths.append(QString("openmw.cfg")); + paths.append(globalPath + QString("openmw.cfg")); + + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error opening OpenMW configuration file")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return false; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + mGameSettings.readFile(stream); + } + file.close(); + } + + if (mGameSettings.getDataDirs().isEmpty()) + { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error detecting Morrowind installation")); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Cancel); + msgBox.setText(QObject::tr("
Could not find the Data Files location

\ + The directory containing the data files was not found.

\ + Press \"Browse...\" to specify the location manually.
")); + + QAbstractButton *dirSelectButton = + msgBox.addButton(QObject::tr("B&rowse..."), QMessageBox::ActionRole); + + msgBox.exec(); + + QString selectedFile; + if (msgBox.clickedButton() == dirSelectButton) { + selectedFile = QFileDialog::getOpenFileName( + NULL, + QObject::tr("Select master file"), + QDir::currentPath(), + QString(tr("Morrowind master file (*.esm)"))); + } + + if (selectedFile.isEmpty()) + return false; // Cancel was clicked; + + qDebug() << selectedFile; + QFileInfo info(selectedFile); + + // Add the new dir to the settings file and to the data dir container + mGameSettings.setValue(QString("data"), info.absolutePath()); + mGameSettings.addDataDir(info.absolutePath()); + + } + + return true; +} + +bool MainDialog::setupGraphicsSettings() +{ + QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string()); + QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string()); + + QFile localDefault(QString("settings-default.cfg")); + QFile globalDefault(globalPath + QString("settings-default.cfg")); + + if (!localDefault.exists() && !globalDefault.exists()) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error reading OpenMW configuration file")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not find settings-default.cfg

\ + The problem may be due to an incomplete installation of OpenMW.
\ + Reinstalling OpenMW may resolve the problem.")); + msgBox.exec(); + return false; + } + + + QStringList paths; + paths.append(globalPath + QString("settings-default.cfg")); + paths.append(QString("settings-default.cfg")); + paths.append(userPath + QString("settings.cfg")); + + foreach (const QString &path, paths) { + qDebug() << "Loading: " << path; + QFile file(path); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error opening OpenMW configuration file")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + return false; + } + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); + + mGraphicsSettings.readFile(stream); + } + file.close(); + } + + return true; +} + void MainDialog::loadSettings() { int width = mLauncherSettings.value(QString("General/MainWindow/width")).toInt(); @@ -206,6 +489,9 @@ void MainDialog::saveSettings() mLauncherSettings.setValue(QString("General/MainWindow/posx"), posX); mLauncherSettings.setValue(QString("General/MainWindow/posy"), posY); + + mLauncherSettings.setValue(QString("General/firstrun"), QString("false")); + } void MainDialog::writeSettings() @@ -221,7 +507,7 @@ void MainDialog::writeSettings() if (!dir.exists()) { if (!dir.mkpath(userPath)) { QMessageBox msgBox; - msgBox.setWindowTitle("Error creating OpenMW configuration directory"); + msgBox.setWindowTitle(tr("Error creating OpenMW configuration directory")); msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not create %0

\ @@ -238,7 +524,7 @@ void MainDialog::writeSettings() if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { // File cannot be opened or created QMessageBox msgBox; - msgBox.setWindowTitle("Error writing OpenMW configuration file"); + msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not open or create %0 for writing

\ @@ -260,7 +546,7 @@ void MainDialog::writeSettings() if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { // File cannot be opened or created QMessageBox msgBox; - msgBox.setWindowTitle("Error writing OpenMW configuration file"); + msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not open or create %0 for writing

\ @@ -282,7 +568,7 @@ void MainDialog::writeSettings() if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { // File cannot be opened or created QMessageBox msgBox; - msgBox.setWindowTitle("Error writing Launcher configuration file"); + msgBox.setWindowTitle(tr("Error writing Launcher configuration file")); msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Could not open or create %0 for writing

\ @@ -308,69 +594,108 @@ void MainDialog::closeEvent(QCloseEvent *event) void MainDialog::play() { - // First do a write of all the configs, just to be sure - //mDataFilesPage->writeConfig(); - //mGraphicsPage->writeConfig(); saveSettings(); writeSettings(); + // Launch the game detached + startProgram(QString("openmw"), true); + qApp->quit(); +} + +bool MainDialog::startProgram(const QString &name, const QStringList &arguments, bool detached) +{ + QString path = name; #ifdef Q_OS_WIN - QString game = "./openmw.exe"; - QFile file(game); + path.append(QString(".exe")); #elif defined(Q_OS_MAC) QDir dir(QCoreApplication::applicationDirPath()); - QString game = dir.absoluteFilePath("openmw"); - QFile file(game); - game = "\"" + game + "\""; + path = dir.absoluteFilePath(name); #else - QString game = "./openmw"; - QFile file(game); + path.prepend(QString("./")); #endif + QFile file(path); + QProcess process; QFileInfo info(file); if (!file.exists()) { QMessageBox msgBox; - msgBox.setWindowTitle("Error starting OpenMW"); + msgBox.setWindowTitle(tr("Error starting executable")); msgBox.setIcon(QMessageBox::Warning); msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not find OpenMW

\ - The OpenMW application is not found.
\ - Please make sure OpenMW is installed correctly and try again.
")); + msgBox.setText(tr("
Could not find %1

\ + The application is not found.
\ + Please make sure OpenMW is installed correctly and try again.
").arg(info.fileName())); msgBox.exec(); - return; + return false; } if (!info.isExecutable()) { QMessageBox msgBox; - msgBox.setWindowTitle("Error starting OpenMW"); + msgBox.setWindowTitle(tr("Error starting executable")); msgBox.setIcon(QMessageBox::Warning); msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not start OpenMW

\ - The OpenMW application is not executable.
\ - Please make sure you have the right permissions and try again.
")); + msgBox.setText(tr("
Could not start %1

\ + The application is not executable.
\ + Please make sure you have the right permissions and try again.
").arg(info.fileName())); msgBox.exec(); - return; + return false; } - // Start the game - if (!process.startDetached(game)) { - QMessageBox msgBox; - msgBox.setWindowTitle("Error starting OpenMW"); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
Could not start OpenMW

\ - An error occurred while starting OpenMW.

\ - Press \"Show Details...\" for more information.
")); - msgBox.setDetailedText(process.errorString()); - msgBox.exec(); + // Start the executable + if (detached) { + if (!process.startDetached(path, arguments)) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error starting executable")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not start %1

\ + An error occurred while starting %1.

\ + Press \"Show Details...\" for more information.
").arg(info.fileName())); + msgBox.setDetailedText(process.errorString()); + msgBox.exec(); - return; + return false; + } } else { - qApp->quit(); + process.start(path, arguments); + if (!process.waitForFinished()) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error starting executable")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Could not start %1

\ + An error occurred while starting %1.

\ + Press \"Show Details...\" for more information.
").arg(info.fileName())); + msgBox.setDetailedText(process.errorString()); + msgBox.exec(); + + return false; + } + + if (process.exitCode() != 0) { + QString error(process.readAllStandardError()); + error.append(tr("\nArguments:\n")); + error.append(arguments.join(" ")); + + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error running executable")); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(tr("
Executable %1 returned an error

\ + An error occurred while running %1.

\ + Press \"Show Details...\" for more information.
").arg(info.fileName())); + msgBox.setDetailedText(error); + msgBox.exec(); + + return false; + } } + + return true; + } diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index 7167d101db..f221bd5e69 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -5,6 +5,10 @@ #include +#include "settings/gamesettings.hpp" +#include "settings/graphicssettings.hpp" +#include "settings/launchersettings.hpp" + class QListWidget; class QListWidgetItem; class QStackedWidget; @@ -16,20 +20,20 @@ class PlayPage; class GraphicsPage; class DataFilesPage; -class GameSettings; -class GraphicsSettings; -class LauncherSettings; - class MainDialog : public QMainWindow { Q_OBJECT public: - MainDialog(GameSettings &gameSettings, - GraphicsSettings &GraphicsSettings, - LauncherSettings &launcherSettings); + MainDialog(); + + +// GameSettings &gameSettings, +// GraphicsSettings &GraphicsSettings, +// LauncherSettings &launcherSettings); bool setup(); + bool showFirstRunDialog(); public slots: void changePage(QListWidgetItem *current, QListWidgetItem *previous); @@ -39,10 +43,17 @@ private: void createIcons(); void createPages(); + bool setupLauncherSettings(); + bool setupGameSettings(); + bool setupGraphicsSettings(); + void loadSettings(); void saveSettings(); void writeSettings(); + inline bool startProgram(const QString &name, bool detached = false) { return startProgram(name, QStringList(), detached); } + bool startProgram(const QString &name, const QStringList &arguments, bool detached = false); + void closeEvent(QCloseEvent *event); QListWidget *mIconWidget; @@ -54,9 +65,9 @@ private: Files::ConfigurationManager mCfgMgr; - GameSettings &mGameSettings; - GraphicsSettings &mGraphicsSettings; - LauncherSettings &mLauncherSettings; + GameSettings mGameSettings; + GraphicsSettings mGraphicsSettings; + LauncherSettings mLauncherSettings; }; diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index fcf6f8b8a7..20ccebc97c 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -25,6 +25,7 @@ void GameSettings::validatePaths() return; QStringList paths = mSettings.values(QString("data")); + qDebug() << "paths " << paths; Files::PathContainer dataDirs; foreach (const QString &path, paths) { @@ -63,9 +64,6 @@ void GameSettings::validatePaths() if (dir.exists()) mDataLocal = path; } - qDebug() << mSettings; - - } QStringList GameSettings::values(const QString &key, const QStringList &defaultValues) @@ -91,18 +89,24 @@ bool GameSettings::readFile(QTextStream &stream) QString key = keyRe.cap(1).simplified(); QString value = keyRe.cap(2).simplified(); - // 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 - cache.insertMulti(key, value); - } else { - cache.insert(key, value); +// // 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 +// cache.insertMulti(key, value); +// } else { +// cache.insert(key, value); +// } + mSettings.remove(key); + + QStringList values = cache.values(key); + if (!values.contains(value)) { + cache.insertMulti(key, value); } } } diff --git a/apps/launcher/settings/gamesettings.hpp b/apps/launcher/settings/gamesettings.hpp index 8aac1552da..fa62872b06 100644 --- a/apps/launcher/settings/gamesettings.hpp +++ b/apps/launcher/settings/gamesettings.hpp @@ -41,6 +41,11 @@ public: mSettings.remove(key); } + inline void clear() + { + mSettings.clear(); + } + inline QStringList getDataDirs() { return mDataDirs; } inline void addDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.append(dir); } inline QString getDataLocal() {return mDataLocal; } diff --git a/apps/launcher/utils/checkablemessagebox.cpp b/apps/launcher/utils/checkablemessagebox.cpp index 8aa01d1018..990835594b 100644 --- a/apps/launcher/utils/checkablemessagebox.cpp +++ b/apps/launcher/utils/checkablemessagebox.cpp @@ -1,3 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "checkablemessagebox.hpp" + #include #include @@ -14,21 +45,17 @@ #include #include -#include "checkablemessagebox.hpp" +/*! + \class Utils::CheckableMessageBox -/* - class CheckableMessageBox - Modified from the one used in Qt Creator - - A messagebox suitable for questions with a - "Do not ask me again" checkbox. + \brief A messagebox suitable for questions with a + "Do not ask me again" checkbox. Emulates the QMessageBox API with static conveniences. The message label can open external URLs. */ - class CheckableMessageBoxPrivate { public: diff --git a/apps/launcher/utils/checkablemessagebox.hpp b/apps/launcher/utils/checkablemessagebox.hpp index ceb437d4d9..93fd43fe1f 100644 --- a/apps/launcher/utils/checkablemessagebox.hpp +++ b/apps/launcher/utils/checkablemessagebox.hpp @@ -1,3 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + #ifndef CHECKABLEMESSAGEBOX_HPP #define CHECKABLEMESSAGEBOX_HPP @@ -22,13 +51,13 @@ public: virtual ~CheckableMessageBox(); static QDialogButtonBox::StandardButton - question(QWidget *parent, - const QString &title, - const QString &question, - const QString &checkBoxText, - bool *checkBoxSetting, - QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Yes|QDialogButtonBox::No, - QDialogButtonBox::StandardButton defaultButton = QDialogButtonBox::No); + question(QWidget *parent, + const QString &title, + const QString &question, + const QString &checkBoxText, + bool *checkBoxSetting, + QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Yes|QDialogButtonBox::No, + QDialogButtonBox::StandardButton defaultButton = QDialogButtonBox::No); QString text() const; void setText(const QString &); From 63a13cf9cac94f8b642d61b2c9c11f193c8098ad Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Wed, 20 Feb 2013 19:29:12 +0100 Subject: [PATCH 17/37] Whoops, removed an include --- apps/launcher/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 5d57dce551..a5c6e30a5e 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -1,4 +1,5 @@ #include +#include #include "maindialog.hpp" From 150d4a7a7292bd1d6cc86bcd4d3177635111e146 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sat, 23 Feb 2013 23:18:42 +0100 Subject: [PATCH 18/37] Added support for multiple ini files --- apps/launcher/maindialog.cpp | 23 +++++++++++++++++++---- apps/launcher/settings/gamesettings.cpp | 18 ++---------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 77526677b8..c03a31fd59 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -180,7 +180,7 @@ bool MainDialog::showFirstRunDialog() if (msgBox.clickedButton() == importerButton) { - QString iniPath; + QStringList iniPaths; foreach (const QString &path, mGameSettings.getDataDirs()) { QDir dir(path); @@ -190,10 +190,10 @@ bool MainDialog::showFirstRunDialog() continue; // Cannot move from Data Files if (dir.exists(QString("Morrowind.ini"))) - iniPath = dir.absoluteFilePath(QString("Morrowind.ini")); + iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini"))); } - if (iniPath.isEmpty()) { + if (iniPaths.isEmpty()) { QMessageBox msgBox; msgBox.setWindowTitle(tr("Error reading Morrowind configuration file")); msgBox.setIcon(QMessageBox::Warning); @@ -205,6 +205,21 @@ bool MainDialog::showFirstRunDialog() return false; } + if (iniPaths.count() > 1) { + // Multiple Morrowind.ini files found + bool ok; + QString path = QInputDialog::getItem(this, tr("Multiple configurations found"), + tr("
There are multiple Morrowind.ini files found.

\ + Please select the one you wish to import from:"), iniPaths, 0, false, &ok); + if (ok && !path.isEmpty()) { + iniPaths.clear(); + iniPaths.append(path); + } else { + // Cancel was clicked TODO: should we abort here? + return false; + } + } + // Create the file if it doesn't already exist, else the importer will fail QString path = QString::fromStdString(mCfgMgr.getUserPath().string()) + QString("openmw.cfg"); QFile file(path); @@ -232,7 +247,7 @@ bool MainDialog::showFirstRunDialog() if (msgBox.isChecked()) arguments.append(QString("-g")); - arguments.append(iniPath); + arguments.append(iniPaths.first()); arguments.append(path); if (!startProgram(QString("mwiniimport"), arguments, false)) diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 20ccebc97c..6b46a5160b 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -21,11 +21,10 @@ GameSettings::~GameSettings() void GameSettings::validatePaths() { - if (mSettings.isEmpty()) - return; + if (mSettings.isEmpty() || !mDataDirs.isEmpty()) + return; // Don't re-validate paths if they are already parsed QStringList paths = mSettings.values(QString("data")); - qDebug() << "paths " << paths; Files::PathContainer dataDirs; foreach (const QString &path, paths) { @@ -89,19 +88,6 @@ bool GameSettings::readFile(QTextStream &stream) QString key = keyRe.cap(1).simplified(); QString value = keyRe.cap(2).simplified(); -// // 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 -// cache.insertMulti(key, value); -// } else { -// cache.insert(key, value); -// } mSettings.remove(key); QStringList values = cache.values(key); From 9198afeefb3a50bcefe3ff4f4f56d22e63f73b90 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 24 Feb 2013 03:10:27 +0100 Subject: [PATCH 19/37] Improved context menu, added context menu for masters and added multi-selection support --- apps/launcher/datafilespage.cpp | 186 ++++++++++++++++++++------------ apps/launcher/datafilespage.hpp | 9 +- 2 files changed, 119 insertions(+), 76 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 4ecb67e4e8..60e377afb7 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -99,9 +99,10 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mMastersTable = new QTableView(this); mMastersTable->setModel(mMastersProxyModel); mMastersTable->setObjectName("MastersTable"); + mMastersTable->setContextMenuPolicy(Qt::CustomContextMenu); mMastersTable->setSortingEnabled(false); mMastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mMastersTable->setSelectionMode(QAbstractItemView::SingleSelection); + mMastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection); mMastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers); mMastersTable->setAlternatingRowColors(true); mMastersTable->horizontalHeader()->setStretchLastSection(true); @@ -118,7 +119,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); mPluginsTable->setSortingEnabled(false); mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mPluginsTable->setSelectionMode(QAbstractItemView::SingleSelection); + mPluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection); mPluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); mPluginsTable->setAlternatingRowColors(true); mPluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); @@ -173,6 +174,7 @@ 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(mMastersTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews())); @@ -208,15 +210,13 @@ void DataFilesPage::createActions() mProfileToolBar->addAction(mDeleteProfileAction); // Context menu actions - mCheckAction = new QAction(tr("Check selected"), this); + mCheckAction = new QAction(tr("Check Selection"), this); connect(mCheckAction, SIGNAL(triggered()), this, SLOT(check())); - mUncheckAction = new QAction(tr("Uncheck selected"), this); + mUncheckAction = new QAction(tr("Uncheck Selection"), this); connect(mUncheckAction, SIGNAL(triggered()), this, SLOT(uncheck())); - // Context menu for the plugins table mContextMenu = new QMenu(this); - mContextMenu->addAction(mCheckAction); mContextMenu->addAction(mUncheckAction); } @@ -296,6 +296,9 @@ void DataFilesPage::loadSettings() void DataFilesPage::saveSettings() { + if (mDataFilesModel->rowCount() < 1) + return; + QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); if (profile.isEmpty()) @@ -406,54 +409,21 @@ void DataFilesPage::deleteProfile() void DataFilesPage::check() { - // Check the current selection - if (!mPluginsTable->selectionModel()->hasSelection()) { - return; - } + if (mPluginsTable->hasFocus()) + setPluginsCheckstates(Qt::Checked); - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + if (mMastersTable->hasFocus()) + setMastersCheckstates(Qt::Checked); - //sort selection ascending because selectedIndexes returns an unsorted list - //qSort(indexes.begin(), indexes.end(), rowSmallerThan); - - foreach (const QModelIndex &index, indexes) { - if (!index.isValid()) - return; - - QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( - mFilterProxyModel->mapToSource(index)); - - if (!sourceIndex.isValid()) - return; - - mDataFilesModel->setCheckState(sourceIndex, Qt::Checked); - } } void DataFilesPage::uncheck() { - // uncheck the current selection - if (!mPluginsTable->selectionModel()->hasSelection()) { - return; - } + if (mPluginsTable->hasFocus()) + setPluginsCheckstates(Qt::Unchecked); - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); - - //sort selection ascending because selectedIndexes returns an unsorted list - //qSort(indexes.begin(), indexes.end(), rowSmallerThan); - - foreach (const QModelIndex &index, indexes) { - if (!index.isValid()) - return; - - QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( - mFilterProxyModel->mapToSource(index)); - - if (!sourceIndex.isValid()) - return; - - mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked); - } + if (mMastersTable->hasFocus()) + setMastersCheckstates(Qt::Unchecked); } void DataFilesPage::refresh() @@ -464,6 +434,50 @@ void DataFilesPage::refresh() mPluginsTable->scrollToTop(); } +void DataFilesPage::setMastersCheckstates(Qt::CheckState state) +{ + if (!mMastersTable->selectionModel()->hasSelection()) { + return; + } + + QModelIndexList indexes = mMastersTable->selectionModel()->selectedIndexes(); + + foreach (const QModelIndex &index, indexes) + { + if (!index.isValid()) + return; + + QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index); + + if (!sourceIndex.isValid()) + return; + + mDataFilesModel->setCheckState(sourceIndex, state); + } +} + +void DataFilesPage::setPluginsCheckstates(Qt::CheckState state) +{ + if (!mPluginsTable->selectionModel()->hasSelection()) { + return; + } + + QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + + foreach (const QModelIndex &index, indexes) + { + if (!index.isValid()) + return; + + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (!sourceIndex.isValid()) + return; + + mDataFilesModel->setCheckState(sourceIndex, state); + } +} void DataFilesPage::setCheckState(QModelIndex index) { @@ -554,35 +568,69 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre void DataFilesPage::showContextMenu(const QPoint &point) { - // Make sure there are plugins in the view - if (!mPluginsTable->selectionModel()->hasSelection()) { + QObject *object = QObject::sender(); + + // Not a signal-slot call + if (!object) return; - } - QPoint globalPos = mPluginsTable->mapToGlobal(point); - - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); - - // Show the check/uncheck actions depending on the state of the selected items - mUncheckAction->setEnabled(false); - mCheckAction->setEnabled(false); - - foreach (const QModelIndex &index, indexes) { - if (!index.isValid()) + if (object->objectName() == QLatin1String("PluginsTable")) { + if (!mPluginsTable->selectionModel()->hasSelection()) return; - QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( - mFilterProxyModel->mapToSource(index)); + QPoint globalPos = mPluginsTable->mapToGlobal(point); + QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); - if (!sourceIndex.isValid()) - return; + // Show the check/uncheck actions depending on the state of the selected items + mUncheckAction->setEnabled(false); + mCheckAction->setEnabled(false); - (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) - ? mUncheckAction->setEnabled(true) - : mCheckAction->setEnabled(true); + foreach (const QModelIndex &index, indexes) + { + if (!index.isValid()) + return; + + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (!sourceIndex.isValid()) + return; + + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mUncheckAction->setEnabled(true) + : mCheckAction->setEnabled(true); + } + + // Show menu + mContextMenu->exec(globalPos); } - // Show menu - mContextMenu->exec(globalPos); + if (object->objectName() == QLatin1String("MastersTable")) { + if (!mMastersTable->selectionModel()->hasSelection()) + return; + QPoint globalPos = mMastersTable->mapToGlobal(point); + QModelIndexList indexes = mMastersTable->selectionModel()->selectedIndexes(); + + // Show the check/uncheck actions depending on the state of the selected items + mUncheckAction->setEnabled(false); + mCheckAction->setEnabled(false); + + foreach (const QModelIndex &index, indexes) + { + if (!index.isValid()) + return; + + QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index); + + if (!sourceIndex.isValid()) + return; + + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mUncheckAction->setEnabled(true) + : mCheckAction->setEnabled(true); + } + + mContextMenu->exec(globalPos); + } } diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index 2561aa3d17..dd69d7489c 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -37,7 +37,6 @@ public: public slots: void setCheckState(QModelIndex index); - void filterChanged(const QString filter); void showContextMenu(const QPoint &point); void profileChanged(const QString &previous, const QString ¤t); @@ -49,10 +48,6 @@ public slots: // Action slots void newProfile(); void deleteProfile(); -// void moveUp(); -// void moveDown(); -// void moveTop(); -// void moveBottom(); void check(); void uncheck(); void refresh(); @@ -90,8 +85,8 @@ private: TextInputDialog *mNewProfileDialog; -// const QStringList checkedPlugins(); -// const QStringList selectedMasters(); + void setMastersCheckstates(Qt::CheckState state); + void setPluginsCheckstates(Qt::CheckState state); void createActions(); void setupDataFiles(); From be43fa334f88a4271d1201cd392d5f000f81aede Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 24 Feb 2013 03:14:19 +0100 Subject: [PATCH 20/37] Added support for non-latin characters, fixes Bug #515 --- apps/launcher/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index a5c6e30a5e..09da1d615f 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "maindialog.hpp" @@ -29,6 +30,9 @@ int main(int argc, char *argv[]) QDir::setCurrent(dir.absolutePath()); + // Support non-latin characters + QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); + MainDialog mainWin; if (mainWin.setup()) { From 4737b20e4cf46f0bb7165fb4a1e1d2d013aedde0 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 24 Feb 2013 04:00:22 +0100 Subject: [PATCH 21/37] Fixed a bug in the combobox popup font size, items overlapping --- apps/launcher/playpage.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/launcher/playpage.cpp b/apps/launcher/playpage.cpp index cb993a8fa0..1dbc1b9dfd 100644 --- a/apps/launcher/playpage.cpp +++ b/apps/launcher/playpage.cpp @@ -15,10 +15,15 @@ PlayPage::PlayPage(QWidget *parent) : QWidget(parent) QLabel *profileLabel = new QLabel(tr("Current Profile:"), playWidget); profileLabel->setObjectName("ProfileLabel"); + // Hacks to get the stylesheet look properly on different platforms QPlastiqueStyle *style = new QPlastiqueStyle; + QFont font = QApplication::font(); + font.setPointSize(12); // Fixes problem with overlapping items + mProfilesComboBox = new QComboBox(playWidget); mProfilesComboBox->setObjectName("ProfilesComboBox"); mProfilesComboBox->setStyle(style); + mProfilesComboBox->setFont(font); QGridLayout *playLayout = new QGridLayout(playWidget); @@ -40,4 +45,4 @@ PlayPage::PlayPage(QWidget *parent) : QWidget(parent) pageLayout->addWidget(playWidget); -} \ No newline at end of file +} From 919d1ee5728cd15527d73e38a5b875d84ffdc171 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 24 Feb 2013 04:14:18 +0100 Subject: [PATCH 22/37] Some fixes to the settings handlers --- apps/launcher/settings/gamesettings.cpp | 19 ++++--------------- apps/launcher/settings/settingsbase.hpp | 8 -------- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index 6b46a5160b..c08179acce 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -88,7 +88,9 @@ bool GameSettings::readFile(QTextStream &stream) QString key = keyRe.cap(1).simplified(); QString value = keyRe.cap(2).simplified(); - mSettings.remove(key); + // Don't remove existing data entries + if (key != QLatin1String("data")) + mSettings.remove(key); QStringList values = cache.values(key); if (!values.contains(value)) { @@ -103,19 +105,6 @@ bool GameSettings::readFile(QTextStream &stream) return true; } - // Replace values from previous settings - QMapIterator i(cache); - while (i.hasNext()) { - i.next(); - - // Don't remove existing data entries - if (i.key() == QLatin1String("data")) - continue; - - if (mSettings.contains(i.key())) - mSettings.remove(i.key()); - } - // Merge the changed keys with those which didn't mSettings.unite(cache); validatePaths(); @@ -136,7 +125,7 @@ bool GameSettings::writeFile(QTextStream &stream) continue; // Quote paths with spaces - if (i.key() == QLatin1String("data") || i.key() == QLatin1String("data")) { + if (i.key() == QLatin1String("data")) { if (i.value().contains(" ")) { stream << i.key() << "=\"" << i.value() << "\"\n"; continue; diff --git a/apps/launcher/settings/settingsbase.hpp b/apps/launcher/settings/settingsbase.hpp index 321426eed8..bbfad1fbb2 100644 --- a/apps/launcher/settings/settingsbase.hpp +++ b/apps/launcher/settings/settingsbase.hpp @@ -85,14 +85,6 @@ public: return true; } - // Replace values from previous settings - QMapIterator i(mCache); - while (i.hasNext()) { - i.next(); - if (mSettings.contains(i.key())) - mSettings.remove(i.key()); - } - // Merge the changed keys with those which didn't mSettings.unite(mCache); return true; From 17a0a201dfe0281a8600fe30742bcd3e77ce9722 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 25 Feb 2013 00:56:04 +0100 Subject: [PATCH 23/37] Various fixes and changes to the settings handling --- apps/launcher/datafilespage.cpp | 35 ++++++--------------- apps/launcher/graphicspage.cpp | 2 +- apps/launcher/settings/gamesettings.cpp | 32 +++++++++++++++++-- apps/launcher/settings/launchersettings.cpp | 8 +++++ 4 files changed, 48 insertions(+), 29 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 60e377afb7..a0df2fb828 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -19,23 +19,6 @@ #include "datafilespage.hpp" -#include -/** - * Workaround for problems with whitespaces in paths in older versions of Boost library - */ -#if (BOOST_VERSION <= 104600) -namespace boost -{ - - template<> - inline boost::filesystem::path lexical_cast(const std::string& arg) - { - return boost::filesystem::path(arg); - } - -} /* namespace boost */ -#endif /* (BOOST_VERSION <= 104600) */ - using namespace ESM; using namespace std; @@ -241,7 +224,7 @@ void DataFilesPage::setupDataFiles() mDataFilesModel->sort(3); QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); - QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); mProfilesComboBox->setCurrentIndex(-1); mProfilesComboBox->addItems(profiles); @@ -271,7 +254,7 @@ void DataFilesPage::setupDataFiles() void DataFilesPage::loadSettings() { - QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); if (profile.isEmpty()) return; @@ -299,10 +282,12 @@ void DataFilesPage::saveSettings() if (mDataFilesModel->rowCount() < 1) return; - QString profile = mLauncherSettings.value(QString("Profiles/CurrentProfile")); + QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); - if (profile.isEmpty()) - return; + if (profile.isEmpty()) { + profile = mProfilesComboBox->currentText(); + mLauncherSettings.setValue(QString("Profiles/currentprofile"), profile); + } mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master")); mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); @@ -539,9 +524,9 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre return; // Profile was deleted // Store the previous profile - mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), previous); + mLauncherSettings.setValue(QString("Profiles/currentprofile"), previous); saveSettings(); - mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), current); + mLauncherSettings.setValue(QString("Profiles/currentprofile"), current); loadSettings(); } @@ -552,7 +537,7 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre return; // Save the new profile name - mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), current); + mLauncherSettings.setValue(QString("Profiles/currentprofile"), current); saveSettings(); // Remove the old one diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 49002e87e2..b5a00b14c5 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -196,7 +196,7 @@ void GraphicsPage::loadSettings() resolution.append(QString(" x ") + mGraphicsSettings.value(QString("Video/resolution y"))); int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith); - qDebug() << "resolution from file: " << resolution; + if (resIndex != -1) mResolutionComboBox->setCurrentIndex(resIndex); } diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index c08179acce..af78757b73 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -8,6 +8,23 @@ #include +#include +/** + * Workaround for problems with whitespaces in paths in older versions of Boost library + */ +#if (BOOST_VERSION <= 104600) +namespace boost +{ + + template<> + inline boost::filesystem::path lexical_cast(const std::string& arg) + { + return boost::filesystem::path(arg); + } + +} /* namespace boost */ +#endif /* (BOOST_VERSION <= 104600) */ + #include "gamesettings.hpp" GameSettings::GameSettings(Files::ConfigurationManager &cfg) @@ -93,6 +110,8 @@ bool GameSettings::readFile(QTextStream &stream) mSettings.remove(key); QStringList values = cache.values(key); + values.append(mSettings.values(key)); + if (!values.contains(value)) { cache.insertMulti(key, value); } @@ -125,9 +144,16 @@ bool GameSettings::writeFile(QTextStream &stream) continue; // Quote paths with spaces - if (i.key() == QLatin1String("data")) { - if (i.value().contains(" ")) { - stream << i.key() << "=\"" << i.value() << "\"\n"; + if (i.key() == QLatin1String("data") + || i.key() == QLatin1String("data-local") + || i.key() == QLatin1String("resources")) + { + if (i.value().contains(QChar(' '))) + { + QString stripped = i.value(); + stripped.remove(QChar('\"')); // Remove quotes + + stream << i.key() << "=\"" << stripped << "\"\n"; continue; } } diff --git a/apps/launcher/settings/launchersettings.cpp b/apps/launcher/settings/launchersettings.cpp index e9730c2357..ee529d8912 100644 --- a/apps/launcher/settings/launchersettings.cpp +++ b/apps/launcher/settings/launchersettings.cpp @@ -66,6 +66,7 @@ bool LauncherSettings::writeFile(QTextStream &stream) QString sectionPrefix; QRegExp sectionRe("([^/]+)/(.+)$"); QMap settings = SettingsBase::getSettings(); + qDebug() << "writing " << settings; QMapIterator i(settings); i.toBack(); @@ -81,6 +82,13 @@ bool LauncherSettings::writeFile(QTextStream &stream) key = sectionRe.cap(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"; From a0007325ad7a2d4eb1af4328fe7f185586340c62 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 25 Feb 2013 01:22:14 +0100 Subject: [PATCH 24/37] Added a warning when stylesheet cannot be read and check if data paths contain masters/plugins --- apps/launcher/datafilespage.cpp | 4 +- apps/launcher/maindialog.cpp | 42 +++++++++++++++------ apps/launcher/settings/graphicssettings.cpp | 2 - apps/launcher/settings/launchersettings.cpp | 1 - apps/launcher/utils/checkablemessagebox.cpp | 1 - apps/launcher/utils/profilescombobox.cpp | 3 -- apps/launcher/utils/textinputdialog.cpp | 1 - 7 files changed, 33 insertions(+), 21 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index a0df2fb828..f8ccf3e83f 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -226,8 +226,8 @@ void DataFilesPage::setupDataFiles() QStringList profiles = mLauncherSettings.subKeys(QString("Profiles/")); QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); - mProfilesComboBox->setCurrentIndex(-1); - mProfilesComboBox->addItems(profiles); + if (!profiles.isEmpty()) + mProfilesComboBox->addItems(profiles); // Add the current profile if empty if (mProfilesComboBox->findText(profile) == -1) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index c03a31fd59..c1e70bb3fa 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -78,10 +78,20 @@ MainDialog::MainDialog() file.setFileName(QString::fromStdString((mCfgMgr.getLocalPath() / "launcher.qss").string())); } - file.open(QFile::ReadOnly); - QString styleSheet = QLatin1String(file.readAll()); - qApp->setStyleSheet(styleSheet); - file.close(); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error opening Launcher stylesheet")); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText(QObject::tr("
Could not open %0 for reading

\ + Please make sure you have the right permissions \ + and try again.
").arg(file.fileName())); + msgBox.exec(); + } else { + QString styleSheet = QLatin1String(file.readAll()); + qApp->setStyleSheet(styleSheet); + file.close(); + } connect(buttonBox, SIGNAL(rejected()), this, SLOT(close())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(play())); @@ -261,7 +271,6 @@ bool MainDialog::showFirstRunDialog() // Add a new profile if (msgBox.isChecked()) { - qDebug() << "add a new profile"; mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), QString("Imported")); mLauncherSettings.remove(QString("Profiles/Imported/master")); @@ -330,7 +339,7 @@ bool MainDialog::setupLauncherSettings() paths.append(userPath + QString("launcher.cfg")); foreach (const QString &path, paths) { - qDebug() << "Loading: " << path; + qDebug() << "Loading config file:" << qPrintable(path); QFile file(path); if (file.exists()) { if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -366,7 +375,8 @@ bool MainDialog::setupGameSettings() paths.append(globalPath + QString("openmw.cfg")); foreach (const QString &path, paths) { - qDebug() << "Loading: " << path; + qDebug() << "Loading config file:" << qPrintable(path); + QFile file(path); if (file.exists()) { if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -388,7 +398,19 @@ bool MainDialog::setupGameSettings() file.close(); } - if (mGameSettings.getDataDirs().isEmpty()) + QStringList dataDirs; + + // Check if the paths actually contain data files + foreach (const QString path, mGameSettings.getDataDirs()) { + QDir dir(path); + QStringList filters; + filters << "*.esp" << "*.esm"; + + if (!dir.entryList(filters).isEmpty()) + dataDirs.append(path); + } + + if (dataDirs.isEmpty()) { QMessageBox msgBox; msgBox.setWindowTitle(tr("Error detecting Morrowind installation")); @@ -415,13 +437,11 @@ bool MainDialog::setupGameSettings() if (selectedFile.isEmpty()) return false; // Cancel was clicked; - qDebug() << selectedFile; QFileInfo info(selectedFile); // Add the new dir to the settings file and to the data dir container mGameSettings.setValue(QString("data"), info.absolutePath()); mGameSettings.addDataDir(info.absolutePath()); - } return true; @@ -454,7 +474,7 @@ bool MainDialog::setupGraphicsSettings() paths.append(userPath + QString("settings.cfg")); foreach (const QString &path, paths) { - qDebug() << "Loading: " << path; + qDebug() << "Loading config file:" << qPrintable(path); QFile file(path); if (file.exists()) { if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { diff --git a/apps/launcher/settings/graphicssettings.cpp b/apps/launcher/settings/graphicssettings.cpp index fd70917b5d..a92477ebbc 100644 --- a/apps/launcher/settings/graphicssettings.cpp +++ b/apps/launcher/settings/graphicssettings.cpp @@ -3,8 +3,6 @@ #include #include -#include - #include "graphicssettings.hpp" GraphicsSettings::GraphicsSettings() diff --git a/apps/launcher/settings/launchersettings.cpp b/apps/launcher/settings/launchersettings.cpp index ee529d8912..1101a80b95 100644 --- a/apps/launcher/settings/launchersettings.cpp +++ b/apps/launcher/settings/launchersettings.cpp @@ -66,7 +66,6 @@ bool LauncherSettings::writeFile(QTextStream &stream) QString sectionPrefix; QRegExp sectionRe("([^/]+)/(.+)$"); QMap settings = SettingsBase::getSettings(); - qDebug() << "writing " << settings; QMapIterator i(settings); i.toBack(); diff --git a/apps/launcher/utils/checkablemessagebox.cpp b/apps/launcher/utils/checkablemessagebox.cpp index 990835594b..41207a8ded 100644 --- a/apps/launcher/utils/checkablemessagebox.cpp +++ b/apps/launcher/utils/checkablemessagebox.cpp @@ -29,7 +29,6 @@ #include "checkablemessagebox.hpp" -#include #include #include diff --git a/apps/launcher/utils/profilescombobox.cpp b/apps/launcher/utils/profilescombobox.cpp index 4c258dae60..c3ff953ae0 100644 --- a/apps/launcher/utils/profilescombobox.cpp +++ b/apps/launcher/utils/profilescombobox.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include @@ -67,8 +66,6 @@ void ProfilesComboBox::slotEditingFinished() QString current = currentText(); QString previous = itemText(currentIndex()); - qDebug() << current << previous; - if (currentIndex() == -1) return; diff --git a/apps/launcher/utils/textinputdialog.cpp b/apps/launcher/utils/textinputdialog.cpp index 09b26ae75a..011e51bf25 100644 --- a/apps/launcher/utils/textinputdialog.cpp +++ b/apps/launcher/utils/textinputdialog.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include From c4ebdc230c4ed65a6d6d6be7d212376ad4ba0ccf Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 25 Feb 2013 01:28:13 +0100 Subject: [PATCH 25/37] Cleaned up strings and indentation --- apps/launcher/maindialog.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index c1e70bb3fa..c91ffa070e 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -60,22 +60,22 @@ MainDialog::MainDialog() // Check if the font is installed if (!fonts.contains("EB Garamond")) { - QString font = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/mygui/EBGaramond-Regular.ttf").string()); - file.setFileName(font); + QString font = QString::fromStdString(mCfgMgr.getGlobalDataPath().string()) + QString("resources/mygui/EBGaramond-Regular.ttf"); + file.setFileName(font); - if (!file.exists()) { - font = QString::fromStdString((mCfgMgr.getLocalPath() / "resources/mygui/EBGaramond-Regular.ttf").string()); - } + if (!file.exists()) { + font = QString::fromStdString(mCfgMgr.getLocalPath().string()) + QString("resources/mygui/EBGaramond-Regular.ttf"); + } - fontDatabase.addApplicationFont(font); + fontDatabase.addApplicationFont(font); } // Load the stylesheet - QString config = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/launcher.qss").string()); + QString config = QString::fromStdString(mCfgMgr.getGlobalDataPath().string()) + QString("resources/launcher.qss"); file.setFileName(config); if (!file.exists()) { - file.setFileName(QString::fromStdString((mCfgMgr.getLocalPath() / "launcher.qss").string())); + file.setFileName(QString::fromStdString(mCfgMgr.getLocalPath().string()) + QString("launcher.qss")); } if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { From 9cd8dd39de31a902eafe118c9e293ee16f87218c Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 25 Feb 2013 21:22:07 +0100 Subject: [PATCH 26/37] Make the launcher code conform to the coding standards and cleanup --- apps/launcher/datafilespage.cpp | 8 +++--- apps/launcher/graphicspage.cpp | 29 +++++++++++---------- apps/launcher/maindialog.cpp | 10 +++---- apps/launcher/playpage.cpp | 4 +-- apps/launcher/settings/gamesettings.cpp | 3 ++- apps/launcher/settings/graphicssettings.cpp | 4 +-- apps/launcher/settings/launchersettings.cpp | 4 +-- 7 files changed, 30 insertions(+), 32 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index f8ccf3e83f..dd45c66024 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -1,3 +1,5 @@ +#include "datafilespage.hpp" + #include #include @@ -17,8 +19,6 @@ #include "utils/profilescombobox.hpp" #include "utils/textinputdialog.hpp" -#include "datafilespage.hpp" - using namespace ESM; using namespace std; @@ -216,9 +216,8 @@ void DataFilesPage::setupDataFiles() } QString dataLocal = mGameSettings.getDataLocal(); - if (!dataLocal.isEmpty()) { + if (!dataLocal.isEmpty()) mDataFilesModel->addFiles(dataLocal); - } // Sort by date accessed for now mDataFilesModel->sort(3); @@ -236,7 +235,6 @@ void DataFilesPage::setupDataFiles() if (mProfilesComboBox->findText(QString("Default")) == -1) mProfilesComboBox->addItem(QString("Default")); - if (profile.isEmpty() || profile == QLatin1String("Default")) { mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(QString("Default"))); } else { diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index b5a00b14c5..741aacc9df 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -1,3 +1,5 @@ +#include "graphicspage.hpp" + #include #include @@ -10,7 +12,6 @@ #include #include "settings/graphicssettings.hpp" -#include "graphicspage.hpp" QString getAspect(int x, int y) { @@ -183,22 +184,22 @@ bool GraphicsPage::setupOgre() void GraphicsPage::loadSettings() { if (mGraphicsSettings.value(QString("Video/vsync")) == QLatin1String("true")) - mVSyncCheckBox->setCheckState(Qt::Checked); + mVSyncCheckBox->setCheckState(Qt::Checked); - if (mGraphicsSettings.value(QString("Video/fullscreen")) == QLatin1String("true")) - mFullScreenCheckBox->setCheckState(Qt::Checked); + if (mGraphicsSettings.value(QString("Video/fullscreen")) == QLatin1String("true")) + mFullScreenCheckBox->setCheckState(Qt::Checked); - int aaIndex = mAntiAliasingComboBox->findText(mGraphicsSettings.value(QString("Video/antialiasing"))); - if (aaIndex != -1) - mAntiAliasingComboBox->setCurrentIndex(aaIndex); + int aaIndex = mAntiAliasingComboBox->findText(mGraphicsSettings.value(QString("Video/antialiasing"))); + if (aaIndex != -1) + mAntiAliasingComboBox->setCurrentIndex(aaIndex); - QString resolution = mGraphicsSettings.value(QString("Video/resolution x")); - resolution.append(QString(" x ") + mGraphicsSettings.value(QString("Video/resolution y"))); + QString resolution = mGraphicsSettings.value(QString("Video/resolution x")); + resolution.append(QString(" x ") + mGraphicsSettings.value(QString("Video/resolution y"))); - int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith); + int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith); - if (resIndex != -1) - mResolutionComboBox->setCurrentIndex(resIndex); + if (resIndex != -1) + mResolutionComboBox->setCurrentIndex(resIndex); } void GraphicsPage::saveSettings() @@ -215,8 +216,8 @@ void GraphicsPage::saveSettings() QRegExp resolutionRe(QString("(\\d+) x (\\d+).*")); if (resolutionRe.exactMatch(mResolutionComboBox->currentText().simplified())) { - mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1)); - mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2)); + mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1)); + mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2)); } } diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index c91ffa070e..e69f134d29 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -1,9 +1,10 @@ +#include "maindialog.hpp" + #include #include "utils/checkablemessagebox.hpp" #include "utils/profilescombobox.hpp" -#include "maindialog.hpp" #include "playpage.hpp" #include "graphicspage.hpp" #include "datafilespage.hpp" @@ -74,9 +75,8 @@ MainDialog::MainDialog() QString config = QString::fromStdString(mCfgMgr.getGlobalDataPath().string()) + QString("resources/launcher.qss"); file.setFileName(config); - if (!file.exists()) { + if (!file.exists()) file.setFileName(QString::fromStdString(mCfgMgr.getLocalPath().string()) + QString("launcher.qss")); - } if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox msgBox; @@ -101,9 +101,8 @@ MainDialog::MainDialog() void MainDialog::createIcons() { - if (!QIcon::hasThemeIcon("document-new")) { + if (!QIcon::hasThemeIcon("document-new")) QIcon::setThemeName("tango"); - } // We create a fallback icon because the default fallback doesn't work QIcon graphicsIcon = QIcon(":/icons/tango/video-display.png"); @@ -733,4 +732,3 @@ bool MainDialog::startProgram(const QString &name, const QStringList &arguments, return true; } - diff --git a/apps/launcher/playpage.cpp b/apps/launcher/playpage.cpp index 1dbc1b9dfd..b082e2e2ce 100644 --- a/apps/launcher/playpage.cpp +++ b/apps/launcher/playpage.cpp @@ -1,7 +1,7 @@ -#include - #include "playpage.hpp" +#include + PlayPage::PlayPage(QWidget *parent) : QWidget(parent) { QWidget *playWidget = new QWidget(this); diff --git a/apps/launcher/settings/gamesettings.cpp b/apps/launcher/settings/gamesettings.cpp index af78757b73..56c08582fe 100644 --- a/apps/launcher/settings/gamesettings.cpp +++ b/apps/launcher/settings/gamesettings.cpp @@ -1,3 +1,5 @@ +#include "gamesettings.hpp" + #include #include #include @@ -25,7 +27,6 @@ namespace boost } /* namespace boost */ #endif /* (BOOST_VERSION <= 104600) */ -#include "gamesettings.hpp" GameSettings::GameSettings(Files::ConfigurationManager &cfg) : mCfgMgr(cfg) diff --git a/apps/launcher/settings/graphicssettings.cpp b/apps/launcher/settings/graphicssettings.cpp index a92477ebbc..0c55800917 100644 --- a/apps/launcher/settings/graphicssettings.cpp +++ b/apps/launcher/settings/graphicssettings.cpp @@ -1,10 +1,10 @@ +#include "graphicssettings.hpp" + #include #include #include #include -#include "graphicssettings.hpp" - GraphicsSettings::GraphicsSettings() { } diff --git a/apps/launcher/settings/launchersettings.cpp b/apps/launcher/settings/launchersettings.cpp index 1101a80b95..5d298e814e 100644 --- a/apps/launcher/settings/launchersettings.cpp +++ b/apps/launcher/settings/launchersettings.cpp @@ -1,10 +1,10 @@ +#include "launchersettings.hpp" + #include #include #include #include -#include "launchersettings.hpp" - LauncherSettings::LauncherSettings() { } From b209b6a0e6cda392a3b7d78b12ecbdf7aa0838a9 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Mon, 25 Feb 2013 22:00:51 +0100 Subject: [PATCH 27/37] Added missing includes --- apps/launcher/settings/gamesettings.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/launcher/settings/gamesettings.hpp b/apps/launcher/settings/gamesettings.hpp index fa62872b06..6c296711f8 100644 --- a/apps/launcher/settings/gamesettings.hpp +++ b/apps/launcher/settings/gamesettings.hpp @@ -1,14 +1,13 @@ #ifndef GAMESETTINGS_HPP #define GAMESETTINGS_HPP +#include +#include +#include #include #include -class QTextStream; -class QStringList; -class QString; - namespace Files { typedef std::vector PathContainer; struct ConfigurationManager;} From 2b6bb9657bd46d2c2a5509a019647bcaa12dc7bb Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sat, 2 Mar 2013 23:49:31 +0100 Subject: [PATCH 28/37] Added Qt Designer .ui files --- apps/launcher/CMakeLists.txt | 10 +- apps/launcher/ui/graphicspage.ui | 134 +++++++++++++++++++++++ apps/launcher/ui/mainwindow.ui | 80 ++++++++++++++ apps/launcher/ui/playpage.ui | 180 +++++++++++++++++++++++++++++++ 4 files changed, 403 insertions(+), 1 deletion(-) create mode 100644 apps/launcher/ui/graphicspage.ui create mode 100644 apps/launcher/ui/mainwindow.ui create mode 100644 apps/launcher/ui/playpage.ui diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index b2e6c70098..bc39690972 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -53,7 +53,13 @@ set(LAUNCHER_HEADER_MOC utils/textinputdialog.hpp ) -source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC}) +set(LAUNCHER_UI + ui/graphicspage.ui + ui/mainwindow.ui + ui/playpage.ui +) + +source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) find_package(Qt4 REQUIRED) set(QT_USE_QTGUI 1) @@ -66,6 +72,7 @@ endif(WIN32) QT4_ADD_RESOURCES(RCC_SRCS resources.qrc) QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) +QT4_WRAP_UI(UI_HDRS ${LAUCHER_UI}) include(${QT_USE_FILE}) @@ -85,6 +92,7 @@ add_executable(omwlauncher ${LAUNCHER_HEADER} ${RCC_SRCS} ${MOC_SRCS} + ${UI_HDRS} ) target_link_libraries(omwlauncher diff --git a/apps/launcher/ui/graphicspage.ui b/apps/launcher/ui/graphicspage.ui new file mode 100644 index 0000000000..670b4f9c63 --- /dev/null +++ b/apps/launcher/ui/graphicspage.ui @@ -0,0 +1,134 @@ + + + graphicsPage + + + + 0 + 0 + 400 + 300 + + + + + + + Render System + + + + + + Rendering Subsystem: + + + + + + + + + + + + + GroupBox + + + + + + Vertical Sync + + + + + + + Full Screen + + + + + + + Anti-aliasing: + + + + + + + Resolution: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + + + + + + + + + x + + + + + + + + + + + + Custom: + + + + + + + Standard: + + + true + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 61 + + + + + + + + + diff --git a/apps/launcher/ui/mainwindow.ui b/apps/launcher/ui/mainwindow.ui new file mode 100644 index 0000000000..4e1a7854d6 --- /dev/null +++ b/apps/launcher/ui/mainwindow.ui @@ -0,0 +1,80 @@ + + + MainWindow + + + + 0 + 0 + 575 + 575 + + + + + 575 + 575 + + + + OpenMW Launcher + + + + :/images/openmw.png:/images/openmw.png + + + + + + + + 400 + 80 + + + + + 16777215 + 80 + + + + #iconWidget { + background-image: url(":/images/openmw-header.png"); + background-color: white; + background-repeat: no-repeat; + background-attachment: scroll; + background-position: right; +} + + + + + + + + + + + + + + + + + + + + QDialogButtonBox::Close + + + + + + + + + + + diff --git a/apps/launcher/ui/playpage.ui b/apps/launcher/ui/playpage.ui new file mode 100644 index 0000000000..86a763f648 --- /dev/null +++ b/apps/launcher/ui/playpage.ui @@ -0,0 +1,180 @@ + + + playPage + + + #playPage { + background-image: url(":/images/playpage-background.png"); + background-repeat: no-repeat; + background-position: top; +} + + + + + 30 + + + 100 + + + 30 + + + + + + 200 + 85 + + + + + 200 + 85 + + + + #playButton { + height: 50px; + margin-bottom: 30px; + + background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, + stop:0 rgba(255, 255, 255, 200), + stop:0.1 rgba(255, 255, 255, 15), + stop:0.49 rgba(255, 255, 255, 75), + stop:0.5 rgba(0, 0, 0, 0), + stop:0.9 rgba(0, 0, 0, 55), + stop:1 rgba(0, 0, 0, 100)); + + font-size: 26pt; + font-family: "EB Garamond", "EB Garamond 08"; + color: black; + + border-right: 1px solid rgba(0, 0, 0, 155); + border-left: 1px solid rgba(0, 0, 0, 55); + border-top: 1px solid rgba(0, 0, 0, 55); + border-bottom: 1px solid rgba(0, 0, 0, 155); + + border-radius: 5px; +} + +#playButton:hover { + border-bottom: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-top: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-right: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-left: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-width: 2px; + border-style: solid; +} + +#playButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 rgba(0, 0, 0, 75), + stop:0.1 rgba(0, 0, 0, 15), + stop:0.2 rgba(255, 255, 255, 55) + stop:0.95 rgba(255, 255, 255, 55), + stop:1 rgba(255, 255, 255, 155)); + + border: 1px solid rgba(0, 0, 0, 55); +} + + + Play + + + + + + + #profileLabel { + font-size: 18pt; + font-family: "EB Garamond", "EB Garamond 08"; +} + + + + Current Profile: + + + + + + + #profilesComboBox { + padding: 1px 18px 1px 3px; + + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 white, stop:0.2 rgba(0, 0, 0, 25), stop:1 white); + border-width: 1px; + border-color: rgba(0, 0, 0, 125); + border-style: solid; + border-radius: 2px; +} + +/*QComboBox gets the "on" state when the popup is open */ +#profilesComboBox:!editable:on, #ProfilesComboBox::drop-down:editable:on { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 rgba(0, 0, 0, 75), + stop:0.1 rgba(0, 0, 0, 15), + stop:0.2 rgba(255, 255, 255, 55)); + + border: 1px solid rgba(0, 0, 0, 55); +} + +#profilesComboBox { /* shift the text when the popup opens */ + padding-top: 3px; + padding-left: 4px; + + font-size: 12pt; + font-family: "EB Garamond", "EB Garamond 08"; +} + +#profilesComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + + border-width: 1px; + border-left-width: 1px; + border-left-color: darkgray; + border-left-style: solid; /* just a single line */ + border-top-right-radius: 3px; /* same radius as the QComboBox */ + border-bottom-right-radius: 3px; +} + +#profilesComboBox::down-arrow { + image: url(":/images/down.png"); +} + +#profilesComboBox::down-arrow:on { /* shift the arrow when popup is open */ + top: 1px; + left: 1px; +} + +#profilesComboBox QAbstractItemView { + border: 2px solid lightgray; + border-radius: 5px; +} + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + From f2193bb1bacde7fe5c37475cab839c3f2e08374f Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 3 Mar 2013 00:48:09 +0100 Subject: [PATCH 29/37] Made the mainwindow use a .ui file and removed the stylesheet --- CMakeLists.txt | 6 -- apps/launcher/CMakeLists.txt | 22 ++----- apps/launcher/maindialog.cpp | 92 +++++++------------------- apps/launcher/maindialog.hpp | 8 ++- files/launcher.qss | 123 ----------------------------------- 5 files changed, 35 insertions(+), 216 deletions(-) delete mode 100644 files/launcher.qss diff --git a/CMakeLists.txt b/CMakeLists.txt index e583f23d44..6498e723c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -379,7 +379,6 @@ if(WIN32) "${OpenMW_SOURCE_DIR}/OFL.txt" "${OpenMW_SOURCE_DIR}/DejaVu Font License.txt" "${OpenMW_SOURCE_DIR}/Daedric Font License.txt" - "${OpenMW_BINARY_DIR}/launcher.qss" "${OpenMW_BINARY_DIR}/settings-default.cfg" "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" "${OpenMW_BINARY_DIR}/Release/omwlauncher.exe" @@ -566,8 +565,6 @@ if (APPLE) install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) @@ -681,7 +678,4 @@ if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE) # Install resources INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" ) - IF(BUILD_LAUNCHER) - INSTALL(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${DATADIR}/resources" ) - ENDIF(BUILD_LAUNCHER) endif(NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index bc39690972..206e94794e 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -36,6 +36,7 @@ set(LAUNCHER_HEADER utils/comboboxlineedit.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp + ) # Headers that must be pre-processed @@ -54,9 +55,9 @@ set(LAUNCHER_HEADER_MOC ) set(LAUNCHER_UI - ui/graphicspage.ui - ui/mainwindow.ui - ui/playpage.ui + ./ui/graphicspage.ui + ./ui/mainwindow.ui + ./ui/playpage.ui ) source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) @@ -72,9 +73,10 @@ endif(WIN32) QT4_ADD_RESOURCES(RCC_SRCS resources.qrc) QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) -QT4_WRAP_UI(UI_HDRS ${LAUCHER_UI}) +QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI}) include(${QT_USE_FILE}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) # Main executable IF(OGRE_STATIC) @@ -107,18 +109,6 @@ if(DPKG_PROGRAM) INSTALL(TARGETS omwlauncher RUNTIME DESTINATION games COMPONENT omwlauncher) endif() -if (APPLE) - configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss - "${APP_BUNDLE_DIR}/../launcher.qss") -else() - configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss - "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/resources/launcher.qss") - - # Fallback in case getGlobalDataPath does not point to resources - configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss - "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.qss") -endif() - if (BUILD_WITH_CODE_COVERAGE) add_definitions (--coverage) target_link_libraries(omwlauncher gcov) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index e69f134d29..f438e64c9a 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -12,46 +12,6 @@ MainDialog::MainDialog() : mGameSettings(mCfgMgr) { - QWidget *centralWidget = new QWidget(this); - setCentralWidget(centralWidget); - - mIconWidget = new QListWidget(centralWidget); - mIconWidget->setObjectName("IconWidget"); - mIconWidget->setViewMode(QListView::IconMode); - mIconWidget->setWrapping(false); - mIconWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Just to be sure - mIconWidget->setIconSize(QSize(48, 48)); - mIconWidget->setMovement(QListView::Static); - - mIconWidget->setMinimumWidth(400); - mIconWidget->setFixedHeight(80); - mIconWidget->setSpacing(4); - mIconWidget->setCurrentRow(0); - mIconWidget->setFlow(QListView::LeftToRight); - - QGroupBox *groupBox = new QGroupBox(centralWidget); - QVBoxLayout *groupLayout = new QVBoxLayout(groupBox); - - mPagesWidget = new QStackedWidget(groupBox); - groupLayout->addWidget(mPagesWidget); - - QPushButton *playButton = new QPushButton(tr("Play")); - - QDialogButtonBox *buttonBox = new QDialogButtonBox(centralWidget); - buttonBox->setStandardButtons(QDialogButtonBox::Close); - buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole); - - QVBoxLayout *dialogLayout = new QVBoxLayout(centralWidget); - dialogLayout->addWidget(mIconWidget); - dialogLayout->addWidget(groupBox); - dialogLayout->addWidget(buttonBox); - - setWindowTitle(tr("OpenMW Launcher")); - setWindowIcon(QIcon(":/images/openmw.png")); - // Remove what's this? button - setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); - setMinimumSize(QSize(575, 575)); - // Install the stylesheet font QFile file; QFontDatabase fontDatabase; @@ -71,31 +31,27 @@ MainDialog::MainDialog() fontDatabase.addApplicationFont(font); } - // Load the stylesheet - QString config = QString::fromStdString(mCfgMgr.getGlobalDataPath().string()) + QString("resources/launcher.qss"); - file.setFileName(config); + setupUi(this); - if (!file.exists()) - file.setFileName(QString::fromStdString(mCfgMgr.getLocalPath().string()) + QString("launcher.qss")); + iconWidget->setViewMode(QListView::IconMode); + iconWidget->setWrapping(false); + iconWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Just to be sure + iconWidget->setIconSize(QSize(48, 48)); + iconWidget->setMovement(QListView::Static); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QMessageBox msgBox; - msgBox.setWindowTitle(tr("Error opening Launcher stylesheet")); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QObject::tr("
Could not open %0 for reading

\ - Please make sure you have the right permissions \ - and try again.
").arg(file.fileName())); - msgBox.exec(); - } else { - QString styleSheet = QLatin1String(file.readAll()); - qApp->setStyleSheet(styleSheet); - file.close(); - } + iconWidget->setSpacing(4); + iconWidget->setCurrentRow(0); + iconWidget->setFlow(QListView::LeftToRight); + + QPushButton *playButton = new QPushButton(tr("Play")); + buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole); connect(buttonBox, SIGNAL(rejected()), this, SLOT(close())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(play())); + // Remove what's this? button + setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); + createIcons(); } @@ -107,25 +63,25 @@ void MainDialog::createIcons() // We create a fallback icon because the default fallback doesn't work QIcon graphicsIcon = QIcon(":/icons/tango/video-display.png"); - QListWidgetItem *playButton = new QListWidgetItem(mIconWidget); + QListWidgetItem *playButton = new QListWidgetItem(iconWidget); playButton->setIcon(QIcon(":/images/openmw.png")); playButton->setText(tr("Play")); playButton->setTextAlignment(Qt::AlignCenter); playButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - QListWidgetItem *graphicsButton = new QListWidgetItem(mIconWidget); + QListWidgetItem *graphicsButton = new QListWidgetItem(iconWidget); graphicsButton->setIcon(QIcon::fromTheme("video-display", graphicsIcon)); graphicsButton->setText(tr("Graphics")); graphicsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom | Qt::AlignAbsolute); graphicsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - QListWidgetItem *dataFilesButton = new QListWidgetItem(mIconWidget); + QListWidgetItem *dataFilesButton = new QListWidgetItem(iconWidget); dataFilesButton->setIcon(QIcon(":/images/openmw-plugin.png")); dataFilesButton->setText(tr("Data Files")); dataFilesButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom); dataFilesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - connect(mIconWidget, + connect(iconWidget, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this, SLOT(changePage(QListWidgetItem*,QListWidgetItem*))); @@ -142,12 +98,12 @@ void MainDialog::createPages() mPlayPage->mProfilesComboBox->setCurrentIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); // Add the pages to the stacked widget - mPagesWidget->addWidget(mPlayPage); - mPagesWidget->addWidget(mGraphicsPage); - mPagesWidget->addWidget(mDataFilesPage); + pagesWidget->addWidget(mPlayPage); + pagesWidget->addWidget(mGraphicsPage); + pagesWidget->addWidget(mDataFilesPage); // Select the first page - mIconWidget->setCurrentItem(mIconWidget->item(0), QItemSelectionModel::Select); + iconWidget->setCurrentItem(iconWidget->item(0), QItemSelectionModel::Select); connect(mPlayPage->mPlayButton, SIGNAL(clicked()), this, SLOT(play())); @@ -326,7 +282,7 @@ void MainDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) if (!current) current = previous; - mPagesWidget->setCurrentIndex(mIconWidget->row(current)); + pagesWidget->setCurrentIndex(iconWidget->row(current)); } bool MainDialog::setupLauncherSettings() diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index f221bd5e69..780cd8beb3 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -9,6 +9,8 @@ #include "settings/graphicssettings.hpp" #include "settings/launchersettings.hpp" +#include "ui_mainwindow.h" + class QListWidget; class QListWidgetItem; class QStackedWidget; @@ -20,7 +22,7 @@ class PlayPage; class GraphicsPage; class DataFilesPage; -class MainDialog : public QMainWindow +class MainDialog : public QMainWindow, private Ui::MainWindow { Q_OBJECT @@ -56,8 +58,8 @@ private: void closeEvent(QCloseEvent *event); - QListWidget *mIconWidget; - QStackedWidget *mPagesWidget; +// QListWidget *mIconWidget; +// QStackedWidget *mPagesWidget; PlayPage *mPlayPage; GraphicsPage *mGraphicsPage; diff --git a/files/launcher.qss b/files/launcher.qss deleted file mode 100644 index 1eb056d4d3..0000000000 --- a/files/launcher.qss +++ /dev/null @@ -1,123 +0,0 @@ -#PlayGroup { - background-image: url(":/images/playpage-background.png"); - background-repeat: no-repeat; - background-position: top; - padding-left: 30px; - padding-right: 30px; -} - -#MastersWidget { - selection-background-color: palette(highlight); -} - -#PlayButton { - height: 50px; - margin-bottom: 30px; - - background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, - stop:0 rgba(255, 255, 255, 200), - stop:0.1 rgba(255, 255, 255, 15), - stop:0.49 rgba(255, 255, 255, 75), - stop:0.5 rgba(0, 0, 0, 0), - stop:0.9 rgba(0, 0, 0, 55), - stop:1 rgba(0, 0, 0, 100)); - - font-size: 26pt; - font-family: "EB Garamond", "EB Garamond 08"; - color: black; - - border-right: 1px solid rgba(0, 0, 0, 155); - border-left: 1px solid rgba(0, 0, 0, 55); - border-top: 1px solid rgba(0, 0, 0, 55); - border-bottom: 1px solid rgba(0, 0, 0, 155); - - border-radius: 5px; -} - -#PlayButton:hover { - border-bottom: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-top: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-right: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-left: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-width: 2px; - border-style: solid; -} - -#PlayButton:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 rgba(0, 0, 0, 75), - stop:0.1 rgba(0, 0, 0, 15), - stop:0.2 rgba(255, 255, 255, 55) - stop:0.95 rgba(255, 255, 255, 55), - stop:1 rgba(255, 255, 255, 155)); - - border: 1px solid rgba(0, 0, 0, 55); -} - -#ProfileLabel { - font-size: 18pt; - font-family: "EB Garamond", "EB Garamond 08"; -} - -#ProfilesComboBox { - padding: 1px 18px 1px 3px; - - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 white, stop:0.2 rgba(0, 0, 0, 25), stop:1 white); - border-width: 1px; - border-color: rgba(0, 0, 0, 125); - border-style: solid; - border-radius: 2px; -} - -/*QComboBox gets the "on" state when the popup is open */ -#ProfilesComboBox:!editable:on, #ProfilesComboBox::drop-down:editable:on { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 rgba(0, 0, 0, 75), - stop:0.1 rgba(0, 0, 0, 15), - stop:0.2 rgba(255, 255, 255, 55)); - - border: 1px solid rgba(0, 0, 0, 55); -} - - -#ProfilesComboBox { /* shift the text when the popup opens */ - padding-top: 3px; - padding-left: 4px; - - font-size: 12pt; - font-family: "EB Garamond", "EB Garamond 08"; -} - -#ProfilesComboBox::drop-down { - subcontrol-origin: padding; - subcontrol-position: top right; - - border-width: 1px; - border-left-width: 1px; - border-left-color: darkgray; - border-left-style: solid; /* just a single line */ - border-top-right-radius: 3px; /* same radius as the QComboBox */ - border-bottom-right-radius: 3px; -} - -#ProfilesComboBox::down-arrow { - image: url(":/images/down.png"); -} - -#ProfilesComboBox::down-arrow:on { /* shift the arrow when popup is open */ - top: 1px; - left: 1px; -} - -#ProfilesComboBox QAbstractItemView { - border: 2px solid lightgray; - border-radius: 5px; -} - -#IconWidget { - background-image: url(":/images/openmw-header.png"); - background-color: white; - background-repeat: no-repeat; - background-attachment: scroll; - background-position: right; -} From 0a6e3701abf08bb5804f151ab8bd4f87e31a7e90 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sun, 3 Mar 2013 01:49:41 +0100 Subject: [PATCH 30/37] Made the Play page use a .ui file too --- apps/launcher/maindialog.cpp | 15 +- apps/launcher/maindialog.hpp | 9 -- apps/launcher/playpage.cpp | 58 ++++---- apps/launcher/playpage.hpp | 22 ++- apps/launcher/ui/graphicspage.ui | 4 +- apps/launcher/ui/playpage.ui | 228 ++++++++++++++++--------------- 6 files changed, 170 insertions(+), 166 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index f438e64c9a..5621b75c02 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -94,8 +94,8 @@ void MainDialog::createPages() mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this); // Set the combobox of the play page to imitate the combobox on the datafilespage - mPlayPage->mProfilesComboBox->setModel(mDataFilesPage->mProfilesComboBox->model()); - mPlayPage->mProfilesComboBox->setCurrentIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); + mPlayPage->setProfilesComboBoxModel(mDataFilesPage->mProfilesComboBox->model()); + mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); // Add the pages to the stacked widget pagesWidget->addWidget(mPlayPage); @@ -105,15 +105,10 @@ void MainDialog::createPages() // Select the first page iconWidget->setCurrentItem(iconWidget->item(0), QItemSelectionModel::Select); - connect(mPlayPage->mPlayButton, SIGNAL(clicked()), this, SLOT(play())); + connect(mPlayPage, SIGNAL(playButtonClicked()), this, SLOT(play())); - connect(mPlayPage->mProfilesComboBox, - SIGNAL(currentIndexChanged(int)), - mDataFilesPage->mProfilesComboBox, SLOT(setCurrentIndex(int))); - - connect(mDataFilesPage->mProfilesComboBox, - SIGNAL(currentIndexChanged(int)), - mPlayPage->mProfilesComboBox, SLOT(setCurrentIndex(int))); + connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage->mProfilesComboBox, SLOT(setCurrentIndex(int))); + connect(mDataFilesPage->mProfilesComboBox, SIGNAL(currentIndexChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int))); } diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index 780cd8beb3..643206ab6c 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -28,12 +28,6 @@ class MainDialog : public QMainWindow, private Ui::MainWindow public: MainDialog(); - - -// GameSettings &gameSettings, -// GraphicsSettings &GraphicsSettings, -// LauncherSettings &launcherSettings); - bool setup(); bool showFirstRunDialog(); @@ -58,9 +52,6 @@ private: void closeEvent(QCloseEvent *event); -// QListWidget *mIconWidget; -// QStackedWidget *mPagesWidget; - PlayPage *mPlayPage; GraphicsPage *mGraphicsPage; DataFilesPage *mDataFilesPage; diff --git a/apps/launcher/playpage.cpp b/apps/launcher/playpage.cpp index b082e2e2ce..27b7846ddd 100644 --- a/apps/launcher/playpage.cpp +++ b/apps/launcher/playpage.cpp @@ -4,45 +4,37 @@ PlayPage::PlayPage(QWidget *parent) : QWidget(parent) { - QWidget *playWidget = new QWidget(this); - playWidget->setObjectName("PlayGroup"); - playWidget->setFixedSize(QSize(425, 375)); - - mPlayButton = new QPushButton(tr("Play"), playWidget); - mPlayButton->setObjectName("PlayButton"); - mPlayButton->setMinimumSize(QSize(200, 50)); - - QLabel *profileLabel = new QLabel(tr("Current Profile:"), playWidget); - profileLabel->setObjectName("ProfileLabel"); + setupUi(this); // Hacks to get the stylesheet look properly on different platforms QPlastiqueStyle *style = new QPlastiqueStyle; QFont font = QApplication::font(); font.setPointSize(12); // Fixes problem with overlapping items - mProfilesComboBox = new QComboBox(playWidget); - mProfilesComboBox->setObjectName("ProfilesComboBox"); - mProfilesComboBox->setStyle(style); - mProfilesComboBox->setFont(font); + profilesComboBox->setStyle(style); + profilesComboBox->setFont(font); - QGridLayout *playLayout = new QGridLayout(playWidget); - - QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - QSpacerItem *hSpacer2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - QSpacerItem *vSpacer1 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); - QSpacerItem *vSpacer2 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); - - playLayout->addWidget(mPlayButton, 1, 1, 1, 1); - playLayout->addWidget(profileLabel, 2, 1, 1, 1); - playLayout->addWidget(mProfilesComboBox, 3, 1, 1, 1); - playLayout->addItem(hSpacer1, 2, 0, 1, 1); - playLayout->addItem(hSpacer2, 2, 2, 1, 1); - playLayout->addItem(vSpacer1, 0, 1, 1, 1); - playLayout->addItem(vSpacer2, 4, 1, 1, 1); - - QHBoxLayout *pageLayout = new QHBoxLayout(this); - - pageLayout->addWidget(playWidget); + connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int))); + connect(playButton, SIGNAL(clicked()), this, SLOT(slotPlayClicked())); } + +void PlayPage::setProfilesComboBoxModel(QAbstractItemModel *model) +{ + profilesComboBox->setModel(model); +} + +void PlayPage::setProfilesComboBoxIndex(int index) +{ + profilesComboBox->setCurrentIndex(index); +} + +void PlayPage::slotCurrentIndexChanged(int index) +{ + emit profileChanged(index); +} + +void PlayPage::slotPlayClicked() +{ + emit playButtonClicked(); +} diff --git a/apps/launcher/playpage.hpp b/apps/launcher/playpage.hpp index efec6f2b38..4306396bd2 100644 --- a/apps/launcher/playpage.hpp +++ b/apps/launcher/playpage.hpp @@ -3,19 +3,33 @@ #include +#include "ui_playpage.h" + class QComboBox; class QPushButton; +class QAbstractItemModel; -class PlayPage : public QWidget +class PlayPage : public QWidget, private Ui::PlayPage { Q_OBJECT public: PlayPage(QWidget *parent = 0); + void setProfilesComboBoxModel(QAbstractItemModel *model); + +signals: + void profileChanged(int index); + void playButtonClicked(); + +public slots: + void setProfilesComboBoxIndex(int index); + +private slots: + void slotCurrentIndexChanged(int index); + void slotPlayClicked(); + - QComboBox *mProfilesComboBox; - QPushButton *mPlayButton; }; -#endif \ No newline at end of file +#endif diff --git a/apps/launcher/ui/graphicspage.ui b/apps/launcher/ui/graphicspage.ui index 670b4f9c63..e04cd58559 100644 --- a/apps/launcher/ui/graphicspage.ui +++ b/apps/launcher/ui/graphicspage.ui @@ -1,7 +1,7 @@ - graphicsPage - + GraphicsPage + 0 diff --git a/apps/launcher/ui/playpage.ui b/apps/launcher/ui/playpage.ui index 86a763f648..ccd17f519c 100644 --- a/apps/launcher/ui/playpage.ui +++ b/apps/launcher/ui/playpage.ui @@ -1,107 +1,38 @@ - playPage - - - #playPage { + PlayPage + + + + + + #Scroll { background-image: url(":/images/playpage-background.png"); background-repeat: no-repeat; background-position: top; } - - - - 30 - - - 100 - - - 30 - - - - - - 200 - 85 - - - - 200 - 85 - + + QFrame::StyledPanel - - #playButton { - height: 50px; - margin-bottom: 30px; - - background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, - stop:0 rgba(255, 255, 255, 200), - stop:0.1 rgba(255, 255, 255, 15), - stop:0.49 rgba(255, 255, 255, 75), - stop:0.5 rgba(0, 0, 0, 0), - stop:0.9 rgba(0, 0, 0, 55), - stop:1 rgba(0, 0, 0, 100)); - - font-size: 26pt; - font-family: "EB Garamond", "EB Garamond 08"; - color: black; - - border-right: 1px solid rgba(0, 0, 0, 155); - border-left: 1px solid rgba(0, 0, 0, 55); - border-top: 1px solid rgba(0, 0, 0, 55); - border-bottom: 1px solid rgba(0, 0, 0, 155); - - border-radius: 5px; -} - -#playButton:hover { - border-bottom: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-top: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-right: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-left: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); - border-width: 2px; - border-style: solid; -} - -#playButton:pressed { - background: qlineargradient(x1:0, y1:0, x2:0, y2:1, - stop:0 rgba(0, 0, 0, 75), - stop:0.1 rgba(0, 0, 0, 15), - stop:0.2 rgba(255, 255, 255, 55) - stop:0.95 rgba(255, 255, 255, 55), - stop:1 rgba(255, 255, 255, 155)); - - border: 1px solid rgba(0, 0, 0, 55); -} + + QFrame::Plain - - Play - - - - - - - #profileLabel { - font-size: 18pt; - font-family: "EB Garamond", "EB Garamond 08"; -} - - - - Current Profile: - - - - - - - #profilesComboBox { + + + 30 + + + 100 + + + 30 + + + + + #profilesComboBox { padding: 1px 18px 1px 3px; background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 white, stop:0.2 rgba(0, 0, 0, 25), stop:1 white); @@ -155,22 +86,103 @@ border-radius: 5px; } - + + + + + + + #profileLabel { + font-size: 18pt; + font-family: "EB Garamond", "EB Garamond 08"; +} + + + + Current Profile: + + + + + + + + 200 + 85 + + + + + 200 + 85 + + + + #playButton { + height: 50px; + margin-bottom: 30px; + + background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, + stop:0 rgba(255, 255, 255, 200), + stop:0.1 rgba(255, 255, 255, 15), + stop:0.49 rgba(255, 255, 255, 75), + stop:0.5 rgba(0, 0, 0, 0), + stop:0.9 rgba(0, 0, 0, 55), + stop:1 rgba(0, 0, 0, 100)); + + font-size: 26pt; + font-family: "EB Garamond", "EB Garamond 08"; + color: black; + + border-right: 1px solid rgba(0, 0, 0, 155); + border-left: 1px solid rgba(0, 0, 0, 55); + border-top: 1px solid rgba(0, 0, 0, 55); + border-bottom: 1px solid rgba(0, 0, 0, 155); + + border-radius: 5px; +} + +#playButton:hover { + border-bottom: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-top: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-right: qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-left: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(164, 192, 228, 255), stop:1 rgba(255, 255, 255, 0)); + border-width: 2px; + border-style: solid; +} + +#playButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 rgba(0, 0, 0, 75), + stop:0.1 rgba(0, 0, 0, 15), + stop:0.2 rgba(255, 255, 255, 55) + stop:0.95 rgba(255, 255, 255, 55), + stop:1 rgba(255, 255, 255, 155)); + + border: 1px solid rgba(0, 0, 0, 55); +} + + + Play + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + - - - - Qt::Vertical - - - - 20 - 40 - - - - From fb5213a754cab17c457c649bdb089f96ed519424 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Tue, 5 Mar 2013 02:17:28 +0100 Subject: [PATCH 31/37] Made the GraphicsPage use a .ui file and added support for custom res --- apps/launcher/graphicspage.cpp | 137 ++++++++++++++++--------------- apps/launcher/graphicspage.hpp | 21 ++--- apps/launcher/ui/graphicspage.ui | 22 +++-- 3 files changed, 92 insertions(+), 88 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 741aacc9df..5905043548 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -30,48 +30,17 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &g , mGraphicsSettings(graphicsSetting) , QWidget(parent) { - QGroupBox *rendererGroup = new QGroupBox(tr("Renderer"), this); + setupUi(this); - QLabel *rendererLabel = new QLabel(tr("Rendering Subsystem:"), rendererGroup); - mRendererComboBox = new QComboBox(rendererGroup); + // Set the maximum res we can set in windowed mode + QRect res = QApplication::desktop()->screenGeometry(); + customWidthSpinBox->setMaximum(res.width()); + customHeightSpinBox->setMaximum(res.height()); - // Layout for the combobox and label - QGridLayout *renderSystemLayout = new QGridLayout(); - renderSystemLayout->addWidget(rendererLabel, 0, 0, 1, 1); - renderSystemLayout->addWidget(mRendererComboBox, 0, 1, 1, 1); + connect(rendererComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(rendererChanged(const QString&))); + connect(fullScreenCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotFullScreenChanged(int))); + connect(standardRadioButton, SIGNAL(toggled(bool)), this, SLOT(slotStandardToggled(bool))); - // Display - QGroupBox *displayGroup = new QGroupBox(tr("Display"), this); - - mVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), displayGroup); - mFullScreenCheckBox = new QCheckBox(tr("Full Screen"), displayGroup); - - QLabel *antiAliasingLabel = new QLabel(tr("Antialiasing:"), displayGroup); - QLabel *resolutionLabel = new QLabel(tr("Resolution:"), displayGroup); - - mResolutionComboBox = new QComboBox(displayGroup); - mAntiAliasingComboBox = new QComboBox(displayGroup); - - QVBoxLayout *rendererGroupLayout = new QVBoxLayout(rendererGroup); - rendererGroupLayout->addLayout(renderSystemLayout); - - QGridLayout *displayGroupLayout = new QGridLayout(displayGroup); - displayGroupLayout->addWidget(mVSyncCheckBox, 0, 0, 1, 1); - displayGroupLayout->addWidget(mFullScreenCheckBox, 1, 0, 1, 1); - displayGroupLayout->addWidget(antiAliasingLabel, 2, 0, 1, 1); - displayGroupLayout->addWidget(mAntiAliasingComboBox, 2, 1, 1, 1); - displayGroupLayout->addWidget(resolutionLabel, 3, 0, 1, 1); - displayGroupLayout->addWidget(mResolutionComboBox, 3, 1, 1, 1); - - // Layout for the whole page - QVBoxLayout *pageLayout = new QVBoxLayout(this); - QSpacerItem *vSpacer1 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding); - - pageLayout->addWidget(rendererGroup); - pageLayout->addWidget(displayGroup); - pageLayout->addItem(vSpacer1); - - connect(mRendererComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(rendererChanged(const QString&))); } bool GraphicsPage::setupOgre() @@ -138,7 +107,7 @@ bool GraphicsPage::setupOgre() for (Ogre::RenderSystemList::const_iterator r = renderers.begin(); r != renderers.end(); ++r) { mSelectedRenderSystem = *r; - mRendererComboBox->addItem((*r)->getName().c_str()); + rendererComboBox->addItem((*r)->getName().c_str()); } QString openGLName = QString("OpenGL Rendering Subsystem"); @@ -160,21 +129,21 @@ bool GraphicsPage::setupOgre() } // Now fill the GUI elements - int index = mRendererComboBox->findText(mGraphicsSettings.value(QString("Video/render system"))); + int index = rendererComboBox->findText(mGraphicsSettings.value(QString("Video/render system"))); if ( index != -1) { - mRendererComboBox->setCurrentIndex(index); + rendererComboBox->setCurrentIndex(index); } else { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - mRendererComboBox->setCurrentIndex(mRendererComboBox->findText(direct3DName)); + rendererComboBox->setCurrentIndex(rendererComboBox->findText(direct3DName)); #else - mRendererComboBox->setCurrentIndex(mRendererComboBox->findText(openGLName)); + rendererComboBox->setCurrentIndex(rendererComboBox->findText(openGLName)); #endif } - mAntiAliasingComboBox->clear(); - mResolutionComboBox->clear(); - mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); - mResolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem)); + antiAliasingComboBox->clear(); + resolutionComboBox->clear(); + antiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); + resolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem)); // Load the rest of the values loadSettings(); @@ -184,38 +153,46 @@ bool GraphicsPage::setupOgre() void GraphicsPage::loadSettings() { if (mGraphicsSettings.value(QString("Video/vsync")) == QLatin1String("true")) - mVSyncCheckBox->setCheckState(Qt::Checked); + vSyncCheckBox->setCheckState(Qt::Checked); if (mGraphicsSettings.value(QString("Video/fullscreen")) == QLatin1String("true")) - mFullScreenCheckBox->setCheckState(Qt::Checked); + fullScreenCheckBox->setCheckState(Qt::Checked); - int aaIndex = mAntiAliasingComboBox->findText(mGraphicsSettings.value(QString("Video/antialiasing"))); + int aaIndex = antiAliasingComboBox->findText(mGraphicsSettings.value(QString("Video/antialiasing"))); if (aaIndex != -1) - mAntiAliasingComboBox->setCurrentIndex(aaIndex); + antiAliasingComboBox->setCurrentIndex(aaIndex); - QString resolution = mGraphicsSettings.value(QString("Video/resolution x")); - resolution.append(QString(" x ") + mGraphicsSettings.value(QString("Video/resolution y"))); + QString width = mGraphicsSettings.value(QString("Video/resolution x")); + QString height = mGraphicsSettings.value(QString("Video/resolution y")); + QString resolution = width + QString(" x ") + height; - int resIndex = mResolutionComboBox->findText(resolution, Qt::MatchStartsWith); + int resIndex = resolutionComboBox->findText(resolution, Qt::MatchStartsWith); - if (resIndex != -1) - mResolutionComboBox->setCurrentIndex(resIndex); + if (resIndex != -1) { + standardRadioButton->toggle(); + resolutionComboBox->setCurrentIndex(resIndex); + } else { + customRadioButton->toggle(); + customWidthSpinBox->setValue(width.toInt()); + customHeightSpinBox->setValue(height.toInt()); + + } } void GraphicsPage::saveSettings() { - mVSyncCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/vsync"), QString("true")) + vSyncCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/vsync"), QString("true")) : mGraphicsSettings.setValue(QString("Video/vsync"), QString("false")); - mFullScreenCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("true")) + fullScreenCheckBox->checkState() ? mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("true")) : mGraphicsSettings.setValue(QString("Video/fullscreen"), QString("false")); - mGraphicsSettings.setValue(QString("Video/antialiasing"), mAntiAliasingComboBox->currentText()); - mGraphicsSettings.setValue(QString("Video/render system"), mRendererComboBox->currentText()); + mGraphicsSettings.setValue(QString("Video/antialiasing"), antiAliasingComboBox->currentText()); + mGraphicsSettings.setValue(QString("Video/render system"), rendererComboBox->currentText()); QRegExp resolutionRe(QString("(\\d+) x (\\d+).*")); - if (resolutionRe.exactMatch(mResolutionComboBox->currentText().simplified())) { + if (resolutionRe.exactMatch(resolutionComboBox->currentText().simplified())) { mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1)); mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2)); } @@ -277,6 +254,7 @@ QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer) // remove extra tokens after the resolution (for example bpp, can be there or not depending on rendersystem) QStringList tokens = qval.split(" ", QString::SkipEmptyParts); assert (tokens.size() >= 3); + QString resolutionStr = tokens.at(0) + QString(" x ") + tokens.at(2); QString aspect = getAspect(tokens.at(0).toInt(),tokens.at(2).toInt()); @@ -304,9 +282,36 @@ void GraphicsPage::rendererChanged(const QString &renderer) { mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString()); - mAntiAliasingComboBox->clear(); - mResolutionComboBox->clear(); + antiAliasingComboBox->clear(); + resolutionComboBox->clear(); - mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); - mResolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem)); + antiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem)); + resolutionComboBox->addItems(getAvailableResolutions(mSelectedRenderSystem)); +} + +void GraphicsPage::slotFullScreenChanged(int state) +{ + if (state == Qt::Checked) { + standardRadioButton->toggle(); + customRadioButton->setEnabled(false); + customWidthSpinBox->setEnabled(false); + customHeightSpinBox->setEnabled(false); + } else { + customRadioButton->setEnabled(true); + customWidthSpinBox->setEnabled(true); + customHeightSpinBox->setEnabled(true); + } +} + +void GraphicsPage::slotStandardToggled(bool checked) +{ + if (checked) { + resolutionComboBox->setEnabled(true); + customWidthSpinBox->setEnabled(false); + customHeightSpinBox->setEnabled(false); + } else { + resolutionComboBox->setEnabled(false); + customWidthSpinBox->setEnabled(true); + customHeightSpinBox->setEnabled(true); + } } diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp index 48b9ff7854..21039af430 100644 --- a/apps/launcher/graphicspage.hpp +++ b/apps/launcher/graphicspage.hpp @@ -16,16 +16,13 @@ # include "OgreD3D9Plugin.h" #endif -class QComboBox; -class QCheckBox; -class QStackedWidget; -class QSettings; +#include "ui_graphicspage.h" class GraphicsSettings; namespace Files { struct ConfigurationManager; } -class GraphicsPage : public QWidget +class GraphicsPage : public QWidget, private Ui::GraphicsPage { Q_OBJECT @@ -38,6 +35,10 @@ public: public slots: void rendererChanged(const QString &renderer); +private slots: + void slotFullScreenChanged(int state); + void slotStandardToggled(bool checked); + private: Ogre::Root *mOgre; Ogre::RenderSystem *mSelectedRenderSystem; @@ -50,22 +51,12 @@ private: Ogre::D3D9Plugin* mD3D9Plugin; #endif - QComboBox *mRendererComboBox; - - QStackedWidget *mDisplayStackedWidget; - - QComboBox *mAntiAliasingComboBox; - QComboBox *mResolutionComboBox; - QCheckBox *mVSyncCheckBox; - QCheckBox *mFullScreenCheckBox; - Files::ConfigurationManager &mCfgMgr; GraphicsSettings &mGraphicsSettings; QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer); QStringList getAvailableResolutions(Ogre::RenderSystem *renderer); - void createPages(); void loadSettings(); }; diff --git a/apps/launcher/ui/graphicspage.ui b/apps/launcher/ui/graphicspage.ui index e04cd58559..5c330cebd5 100644 --- a/apps/launcher/ui/graphicspage.ui +++ b/apps/launcher/ui/graphicspage.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 300 + 332 + 297 @@ -33,7 +33,7 @@ - GroupBox + Display @@ -73,9 +73,13 @@ - + - + + + 800 + + @@ -85,7 +89,11 @@ - + + + 600 + + @@ -101,7 +109,7 @@ Standard: - + true From 4c9d0563fe4d96f3ca50489b3ea2d4abbf48a44d Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Tue, 5 Mar 2013 03:13:39 +0100 Subject: [PATCH 32/37] WIP: Implementing the .ui for the DataFilesPage --- apps/launcher/CMakeLists.txt | 13 +- apps/launcher/datafilespage.cpp | 272 +++++++++--------- apps/launcher/datafilespage.hpp | 19 +- apps/launcher/maindialog.cpp | 9 +- components/CMakeLists.txt | 2 +- .../fileorderlist}/utils/comboboxlineedit.cpp | 0 .../fileorderlist}/utils/comboboxlineedit.hpp | 0 .../fileorderlist}/utils/profilescombobox.cpp | 0 .../fileorderlist}/utils/profilescombobox.hpp | 0 9 files changed, 155 insertions(+), 160 deletions(-) rename {apps/launcher => components/fileorderlist}/utils/comboboxlineedit.cpp (100%) rename {apps/launcher => components/fileorderlist}/utils/comboboxlineedit.hpp (100%) rename {apps/launcher => components/fileorderlist}/utils/profilescombobox.cpp (100%) rename {apps/launcher => components/fileorderlist}/utils/profilescombobox.hpp (100%) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 206e94794e..a1c2289456 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -12,8 +12,6 @@ set(LAUNCHER settings/launchersettings.cpp utils/checkablemessagebox.cpp - utils/comboboxlineedit.cpp - utils/profilescombobox.cpp utils/textinputdialog.cpp launcher.rc @@ -33,8 +31,6 @@ set(LAUNCHER_HEADER settings/settingsbase.hpp utils/checkablemessagebox.hpp - utils/comboboxlineedit.hpp - utils/profilescombobox.hpp utils/textinputdialog.hpp ) @@ -49,15 +45,14 @@ set(LAUNCHER_HEADER_MOC model/pluginsproxymodel.hpp utils/checkablemessagebox.hpp - utils/comboboxlineedit.hpp - utils/profilescombobox.hpp utils/textinputdialog.hpp ) set(LAUNCHER_UI - ./ui/graphicspage.ui - ./ui/mainwindow.ui - ./ui/playpage.ui + ui/datafilespage.ui + ui/graphicspage.ui + ui/mainwindow.ui + ui/playpage.ui ) source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index dd45c66024..d7dccbab6d 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -10,13 +10,13 @@ #include #include +#include #include "model/pluginsproxymodel.hpp" #include "settings/gamesettings.hpp" #include "settings/launchersettings.hpp" -#include "utils/profilescombobox.hpp" #include "utils/textinputdialog.hpp" using namespace ESM; @@ -40,6 +40,8 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam , mLauncherSettings(launcherSettings) , QWidget(parent) { + setupUi(this); + // Models mDataFilesModel = new DataFilesModel(this); @@ -57,113 +59,117 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam mFilterProxyModel->setDynamicSortFilter(true); mFilterProxyModel->setSourceModel(mPluginsProxyModel); - // Filter toolbar - QLabel *filterLabel = new QLabel(tr("&Filter:"), this); - LineEdit *filterLineEdit = new LineEdit(this); - filterLabel->setBuddy(filterLineEdit); - - QToolBar *filterToolBar = new QToolBar(this); - filterToolBar->setMovable(false); - - // Create a container widget and a layout to get the spacer to work - QWidget *filterWidget = new QWidget(this); - QHBoxLayout *filterLayout = new QHBoxLayout(filterWidget); - QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - filterLayout->addItem(hSpacer1); - filterLayout->addWidget(filterLabel); - filterLayout->addWidget(filterLineEdit); - - filterToolBar->addWidget(filterWidget); - QCheckBox checkBox; unsigned int height = checkBox.sizeHint().height() + 4; - mMastersTable = new QTableView(this); - mMastersTable->setModel(mMastersProxyModel); - mMastersTable->setObjectName("MastersTable"); - mMastersTable->setContextMenuPolicy(Qt::CustomContextMenu); - mMastersTable->setSortingEnabled(false); - mMastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mMastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection); - mMastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - mMastersTable->setAlternatingRowColors(true); - mMastersTable->horizontalHeader()->setStretchLastSection(true); - mMastersTable->horizontalHeader()->hide(); + mastersTable->setModel(mMastersProxyModel); + mastersTable->setObjectName("MastersTable"); + mastersTable->setContextMenuPolicy(Qt::CustomContextMenu); + mastersTable->setSortingEnabled(false); + mastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); + mastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + mastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + mastersTable->setAlternatingRowColors(true); + mastersTable->horizontalHeader()->setStretchLastSection(true); + mastersTable->horizontalHeader()->hide(); // Set the row height to the size of the checkboxes - mMastersTable->verticalHeader()->setDefaultSectionSize(height); - mMastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); - mMastersTable->verticalHeader()->hide(); + mastersTable->verticalHeader()->setDefaultSectionSize(height); + mastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); + mastersTable->verticalHeader()->hide(); - mPluginsTable = new QTableView(this); - mPluginsTable->setModel(mFilterProxyModel); - mPluginsTable->setObjectName("PluginsTable"); - mPluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); - mPluginsTable->setSortingEnabled(false); - mPluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mPluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection); - mPluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - mPluginsTable->setAlternatingRowColors(true); - mPluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); - mPluginsTable->horizontalHeader()->setStretchLastSection(true); - mPluginsTable->horizontalHeader()->hide(); + pluginsTable->setModel(mFilterProxyModel); + pluginsTable->setObjectName("PluginsTable"); + pluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); + pluginsTable->setSortingEnabled(false); + pluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); + pluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + pluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + pluginsTable->setAlternatingRowColors(true); + pluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); + pluginsTable->horizontalHeader()->setStretchLastSection(true); + pluginsTable->horizontalHeader()->hide(); - mPluginsTable->verticalHeader()->setDefaultSectionSize(height); - mPluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); + pluginsTable->verticalHeader()->setDefaultSectionSize(height); + pluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); - // Add both tables to a splitter - mSplitter = new QSplitter(this); - mSplitter->setOrientation(Qt::Horizontal); - mSplitter->setChildrenCollapsible(false); // Don't allow the widgets to be hidden - mSplitter->addWidget(mMastersTable); - mSplitter->addWidget(mPluginsTable); - - // Adjust the default widget widths inside the splitter + // Adjust the tableview widths inside the splitter QList sizeList; sizeList << mLauncherSettings.value(QString("General/MastersTable/width"), QString("200")).toInt(); sizeList << mLauncherSettings.value(QString("General/PluginTable/width"), QString("340")).toInt(); - mSplitter->setSizes(sizeList); + splitter->setSizes(sizeList); - // Bottom part with profile options - QLabel *profileLabel = new QLabel(tr("Current Profile: "), this); +// // Filter toolbar +// QLabel *filterLabel = new QLabel(tr("&Filter:"), this); +// LineEdit *filterLineEdit = new LineEdit(this); +// filterLabel->setBuddy(filterLineEdit); - mProfilesComboBox = new ProfilesComboBox(this); - mProfilesComboBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); - mProfilesComboBox->setInsertPolicy(QComboBox::NoInsert); - mProfilesComboBox->setDuplicatesEnabled(false); - mProfilesComboBox->setEditEnabled(false); +// QToolBar *filterToolBar = new QToolBar(this); +// filterToolBar->setMovable(false); - mProfileToolBar = new QToolBar(this); - mProfileToolBar->setMovable(false); - mProfileToolBar->setIconSize(QSize(16, 16)); +// // Create a container widget and a layout to get the spacer to work +// QWidget *filterWidget = new QWidget(this); +// QHBoxLayout *filterLayout = new QHBoxLayout(filterWidget); +// QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - mProfileToolBar->addWidget(profileLabel); - mProfileToolBar->addWidget(mProfilesComboBox); +// filterLayout->addItem(hSpacer1); +// filterLayout->addWidget(filterLabel); +// filterLayout->addWidget(filterLineEdit); - QVBoxLayout *pageLayout = new QVBoxLayout(this); +// filterToolBar->addWidget(filterWidget); - pageLayout->addWidget(filterToolBar); - pageLayout->addWidget(mSplitter); - pageLayout->addWidget(mProfileToolBar); + + +// // Add both tables to a splitter +// mSplitter = new QSplitter(this); +// mSplitter->setOrientation(Qt::Horizontal); +// mSplitter->setChildrenCollapsible(false); // Don't allow the widgets to be hidden +// mSplitter->addWidget(mastersTable); +// mSplitter->addWidget(pluginsTable); + + + +// + +// // Bottom part with profile options +// QLabel *profileLabel = new QLabel(tr("Current Profile: "), this); + +// profilesComboBox = new ProfilesComboBox(this); +// profilesComboBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); +// profilesComboBox->setInsertPolicy(QComboBox::NoInsert); +// profilesComboBox->setDuplicatesEnabled(false); +// profilesComboBox->setEditEnabled(false); + +// mProfileToolBar = new QToolBar(this); +// mProfileToolBar->setMovable(false); +// mProfileToolBar->setIconSize(QSize(16, 16)); + +// mProfileToolBar->addWidget(profileLabel); +// mProfileToolBar->addWidget(profilesComboBox); + +// QVBoxLayout *pageLayout = new QVBoxLayout(this); + +// pageLayout->addWidget(filterToolBar); +// pageLayout->addWidget(mSplitter); +// pageLayout->addWidget(mProfileToolBar); // Create a dialog for the new profile name input mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this); connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString))); - connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); - connect(mMastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + connect(pluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + connect(mastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); - connect(mPluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); - connect(mMastersTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); + connect(pluginsTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); + connect(mastersTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews())); connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); - connect(mSplitter, SIGNAL(splitterMoved(int,int)), this, SLOT(updateSplitter())); + connect(splitter, SIGNAL(splitterMoved(int,int)), this, SLOT(updateSplitter())); createActions(); setupDataFiles(); @@ -188,9 +194,9 @@ void DataFilesPage::createActions() connect(mDeleteProfileAction, SIGNAL(triggered()), this, SLOT(deleteProfile())); // Add the newly created actions to the toolbar - mProfileToolBar->addSeparator(); - mProfileToolBar->addAction(mNewProfileAction); - mProfileToolBar->addAction(mDeleteProfileAction); +// mProfileToolBar->addSeparator(); +// mProfileToolBar->addAction(mNewProfileAction); +// mProfileToolBar->addAction(mDeleteProfileAction); // Context menu actions mCheckAction = new QAction(tr("Check Selection"), this); @@ -226,25 +232,25 @@ void DataFilesPage::setupDataFiles() QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); if (!profiles.isEmpty()) - mProfilesComboBox->addItems(profiles); + profilesComboBox->addItems(profiles); // Add the current profile if empty - if (mProfilesComboBox->findText(profile) == -1) - mProfilesComboBox->addItem(profile); + if (profilesComboBox->findText(profile) == -1) + profilesComboBox->addItem(profile); - if (mProfilesComboBox->findText(QString("Default")) == -1) - mProfilesComboBox->addItem(QString("Default")); + if (profilesComboBox->findText(QString("Default")) == -1) + profilesComboBox->addItem(QString("Default")); if (profile.isEmpty() || profile == QLatin1String("Default")) { - mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(QString("Default"))); + profilesComboBox->setCurrentIndex(profilesComboBox->findText(QString("Default"))); } else { - mProfilesComboBox->setEditEnabled(true); - mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(profile)); + profilesComboBox->setEditEnabled(true); + profilesComboBox->setCurrentIndex(profilesComboBox->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))); + connect(profilesComboBox, SIGNAL(profileRenamed(QString,QString)), this, SLOT(profileRenamed(QString,QString))); + connect(profilesComboBox, SIGNAL(profileChanged(QString,QString)), this, SLOT(profileChanged(QString,QString))); loadSettings(); @@ -283,7 +289,7 @@ void DataFilesPage::saveSettings() QString profile = mLauncherSettings.value(QString("Profiles/currentprofile")); if (profile.isEmpty()) { - profile = mProfilesComboBox->currentText(); + profile = profilesComboBox->currentText(); mLauncherSettings.setValue(QString("Profiles/currentprofile"), profile); } @@ -313,8 +319,8 @@ void DataFilesPage::newProfile() { if (mNewProfileDialog->exec() == QDialog::Accepted) { QString profile = mNewProfileDialog->lineEdit()->text(); - mProfilesComboBox->addItem(profile); - mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(profile)); + profilesComboBox->addItem(profile); + profilesComboBox->setCurrentIndex(profilesComboBox->findText(profile)); } } @@ -326,7 +332,7 @@ void DataFilesPage::updateOkButton(const QString &text) return; } - (mProfilesComboBox->findText(text) == -1) + (profilesComboBox->findText(text) == -1) ? mNewProfileDialog->setOkButtonEnabled(true) : mNewProfileDialog->setOkButtonEnabled(false); } @@ -335,7 +341,7 @@ void DataFilesPage::updateSplitter() { // Sigh, update the saved splitter size in settings only when moved // Since getting mSplitter->sizes() if page is hidden returns invalid values - QList sizes = mSplitter->sizes(); + QList sizes = splitter->sizes(); mLauncherSettings.setValue(QString("General/MastersTable/width"), QString::number(sizes.at(0))); mLauncherSettings.setValue(QString("General/PluginsTable/width"), QString::number(sizes.at(1))); @@ -344,28 +350,28 @@ void DataFilesPage::updateSplitter() 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); + mastersTable->setColumnHidden(1, true); + mastersTable->setColumnHidden(2, true); + mastersTable->setColumnHidden(3, true); + mastersTable->setColumnHidden(4, true); + mastersTable->setColumnHidden(5, true); + mastersTable->setColumnHidden(6, true); + mastersTable->setColumnHidden(7, true); + mastersTable->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); + pluginsTable->setColumnHidden(1, true); + pluginsTable->setColumnHidden(2, true); + pluginsTable->setColumnHidden(3, true); + pluginsTable->setColumnHidden(4, true); + pluginsTable->setColumnHidden(5, true); + pluginsTable->setColumnHidden(6, true); + pluginsTable->setColumnHidden(7, true); + pluginsTable->setColumnHidden(8, true); } void DataFilesPage::deleteProfile() { - QString profile = mProfilesComboBox->currentText(); + QString profile = profilesComboBox->currentText(); if (profile.isEmpty()) return; @@ -386,26 +392,26 @@ void DataFilesPage::deleteProfile() mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin")); // Remove the profile from the combobox - mProfilesComboBox->removeItem(mProfilesComboBox->findText(profile)); + profilesComboBox->removeItem(profilesComboBox->findText(profile)); } } void DataFilesPage::check() { - if (mPluginsTable->hasFocus()) + if (pluginsTable->hasFocus()) setPluginsCheckstates(Qt::Checked); - if (mMastersTable->hasFocus()) + if (mastersTable->hasFocus()) setMastersCheckstates(Qt::Checked); } void DataFilesPage::uncheck() { - if (mPluginsTable->hasFocus()) + if (pluginsTable->hasFocus()) setPluginsCheckstates(Qt::Unchecked); - if (mMastersTable->hasFocus()) + if (mastersTable->hasFocus()) setMastersCheckstates(Qt::Unchecked); } @@ -414,16 +420,16 @@ void DataFilesPage::refresh() // mDataFilesModel->sort(0); // Refresh the plugins table - mPluginsTable->scrollToTop(); + pluginsTable->scrollToTop(); } void DataFilesPage::setMastersCheckstates(Qt::CheckState state) { - if (!mMastersTable->selectionModel()->hasSelection()) { + if (!mastersTable->selectionModel()->hasSelection()) { return; } - QModelIndexList indexes = mMastersTable->selectionModel()->selectedIndexes(); + QModelIndexList indexes = mastersTable->selectionModel()->selectedIndexes(); foreach (const QModelIndex &index, indexes) { @@ -441,11 +447,11 @@ void DataFilesPage::setMastersCheckstates(Qt::CheckState state) void DataFilesPage::setPluginsCheckstates(Qt::CheckState state) { - if (!mPluginsTable->selectionModel()->hasSelection()) { + if (!pluginsTable->selectionModel()->hasSelection()) { return; } - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + QModelIndexList indexes = pluginsTable->selectionModel()->selectedIndexes(); foreach (const QModelIndex &index, indexes) { @@ -509,16 +515,16 @@ void DataFilesPage::profileChanged(const QString &previous, const QString &curre // Prevent the deletion of the default profile if (current == QLatin1String("Default")) { mDeleteProfileAction->setEnabled(false); - mProfilesComboBox->setEditEnabled(false); + profilesComboBox->setEditEnabled(false); } else { mDeleteProfileAction->setEnabled(true); - mProfilesComboBox->setEditEnabled(true); + profilesComboBox->setEditEnabled(true); } if (previous.isEmpty()) return; - if (mProfilesComboBox->findText(previous) == -1) + if (profilesComboBox->findText(previous) == -1) return; // Profile was deleted // Store the previous profile @@ -543,7 +549,7 @@ void DataFilesPage::profileRenamed(const QString &previous, const QString &curre mLauncherSettings.remove(QString("Profiles/") + previous + QString("/plugin")); // Remove the profile from the combobox - mProfilesComboBox->removeItem(mProfilesComboBox->findText(previous)); + profilesComboBox->removeItem(profilesComboBox->findText(previous)); loadSettings(); @@ -558,11 +564,11 @@ void DataFilesPage::showContextMenu(const QPoint &point) return; if (object->objectName() == QLatin1String("PluginsTable")) { - if (!mPluginsTable->selectionModel()->hasSelection()) + if (!pluginsTable->selectionModel()->hasSelection()) return; - QPoint globalPos = mPluginsTable->mapToGlobal(point); - QModelIndexList indexes = mPluginsTable->selectionModel()->selectedIndexes(); + QPoint globalPos = pluginsTable->mapToGlobal(point); + QModelIndexList indexes = pluginsTable->selectionModel()->selectedIndexes(); // Show the check/uncheck actions depending on the state of the selected items mUncheckAction->setEnabled(false); @@ -589,11 +595,11 @@ void DataFilesPage::showContextMenu(const QPoint &point) } if (object->objectName() == QLatin1String("MastersTable")) { - if (!mMastersTable->selectionModel()->hasSelection()) + if (!mastersTable->selectionModel()->hasSelection()) return; - QPoint globalPos = mMastersTable->mapToGlobal(point); - QModelIndexList indexes = mMastersTable->selectionModel()->selectedIndexes(); + QPoint globalPos = mastersTable->mapToGlobal(point); + QModelIndexList indexes = mastersTable->selectionModel()->selectedIndexes(); // Show the check/uncheck actions depending on the state of the selected items mUncheckAction->setEnabled(false); diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index dd69d7489c..e98b09aef7 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -4,33 +4,28 @@ #include #include -class QTableView; +#include "ui_datafilespage.h" + class QSortFilterProxyModel; class QAction; -class QToolBar; -class QSplitter; class QMenu; -class ProfilesComboBox; class DataFilesModel; class TextInputDialog; -class ProfilesComboBox; class GameSettings; class LauncherSettings; class PluginsProxyModel; namespace Files { struct ConfigurationManager; } -class DataFilesPage : public QWidget +class DataFilesPage : public QWidget, private Ui::DataFilesPage { Q_OBJECT public: DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent = 0); - ProfilesComboBox *mProfilesComboBox; - void writeConfig(QString profile = QString()); void saveSettings(); @@ -60,13 +55,13 @@ private: QSortFilterProxyModel *mFilterProxyModel; - QTableView *mMastersTable; - QTableView *mPluginsTable; +// QTableView *mMastersTable; +// QTableView *mPluginsTable; - QToolBar *mProfileToolBar; +// QToolBar *mProfileToolBar; QMenu *mContextMenu; - QSplitter *mSplitter; +// QSplitter *mSplitter; QAction *mNewProfileAction; QAction *mDeleteProfileAction; diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 5621b75c02..cab763b105 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -3,7 +3,6 @@ #include #include "utils/checkablemessagebox.hpp" -#include "utils/profilescombobox.hpp" #include "playpage.hpp" #include "graphicspage.hpp" @@ -94,8 +93,8 @@ void MainDialog::createPages() mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this); // Set the combobox of the play page to imitate the combobox on the datafilespage - mPlayPage->setProfilesComboBoxModel(mDataFilesPage->mProfilesComboBox->model()); - mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); +// mPlayPage->setProfilesComboBoxModel(mDataFilesPage->mProfilesComboBox->model()); +// mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); // Add the pages to the stacked widget pagesWidget->addWidget(mPlayPage); @@ -107,8 +106,8 @@ void MainDialog::createPages() connect(mPlayPage, SIGNAL(playButtonClicked()), this, SLOT(play())); - connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage->mProfilesComboBox, SLOT(setCurrentIndex(int))); - connect(mDataFilesPage->mProfilesComboBox, SIGNAL(currentIndexChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int))); +// connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage->mProfilesComboBox, SLOT(setCurrentIndex(int))); +// connect(mDataFilesPage->mProfilesComboBox, SIGNAL(currentIndexChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int))); } diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 00342e2ac8..7c52ab12cc 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -71,7 +71,7 @@ find_package(Qt4 COMPONENTS QtCore QtGui) if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) add_component_qt_dir (fileorderlist datafileslist model/modelitem model/datafilesmodel model/esm/esmfile - utils/filedialog utils/lineedit utils/naturalsort + utils/profilescombobox utils/comboboxlineedit utils/lineedit utils/naturalsort ) include(${QT_USE_FILE}) diff --git a/apps/launcher/utils/comboboxlineedit.cpp b/components/fileorderlist/utils/comboboxlineedit.cpp similarity index 100% rename from apps/launcher/utils/comboboxlineedit.cpp rename to components/fileorderlist/utils/comboboxlineedit.cpp diff --git a/apps/launcher/utils/comboboxlineedit.hpp b/components/fileorderlist/utils/comboboxlineedit.hpp similarity index 100% rename from apps/launcher/utils/comboboxlineedit.hpp rename to components/fileorderlist/utils/comboboxlineedit.hpp diff --git a/apps/launcher/utils/profilescombobox.cpp b/components/fileorderlist/utils/profilescombobox.cpp similarity index 100% rename from apps/launcher/utils/profilescombobox.cpp rename to components/fileorderlist/utils/profilescombobox.cpp diff --git a/apps/launcher/utils/profilescombobox.hpp b/components/fileorderlist/utils/profilescombobox.hpp similarity index 100% rename from apps/launcher/utils/profilescombobox.hpp rename to components/fileorderlist/utils/profilescombobox.hpp From 75cf009101828d8f83c98eb0915bede65c1c54dd Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Tue, 5 Mar 2013 03:47:57 +0100 Subject: [PATCH 33/37] Finished implementing the .ui file for the DataFilesPage --- apps/launcher/datafilespage.cpp | 32 ++++++++++++++++++++++++++------ apps/launcher/datafilespage.hpp | 12 +++++++++++- apps/launcher/maindialog.cpp | 8 ++++---- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index d7dccbab6d..069cdd9ac9 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -157,6 +157,8 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam // Create a dialog for the new profile name input mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this); + connect(profilesComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int))); + connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString))); connect(pluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); @@ -182,7 +184,7 @@ void DataFilesPage::createActions() refreshAction->setShortcut(QKeySequence(tr("F5"))); connect(refreshAction, SIGNAL(triggered()), this, SLOT(refresh())); - // Profile actions + // We can't create actions inside the .ui file mNewProfileAction = new QAction(QIcon::fromTheme("document-new"), tr("&New Profile"), this); mNewProfileAction->setToolTip(tr("New Profile")); mNewProfileAction->setShortcut(QKeySequence(tr("Ctrl+N"))); @@ -190,13 +192,11 @@ void DataFilesPage::createActions() mDeleteProfileAction = new QAction(QIcon::fromTheme("edit-delete"), tr("Delete Profile"), this); mDeleteProfileAction->setToolTip(tr("Delete Profile")); - mDeleteProfileAction->setShortcut(QKeySequence(tr("Delete"))); connect(mDeleteProfileAction, SIGNAL(triggered()), this, SLOT(deleteProfile())); - // Add the newly created actions to the toolbar -// mProfileToolBar->addSeparator(); -// mProfileToolBar->addAction(mNewProfileAction); -// mProfileToolBar->addAction(mDeleteProfileAction); + // Add the newly created actions to the toolbuttons + newProfileButton->setDefaultAction(mNewProfileAction); + deleteProfileButton->setDefaultAction(mDeleteProfileAction); // Context menu actions mCheckAction = new QAction(tr("Check Selection"), this); @@ -369,6 +369,26 @@ void DataFilesPage::updateViews() pluginsTable->setColumnHidden(8, true); } +void DataFilesPage::setProfilesComboBoxIndex(int index) +{ + profilesComboBox->setCurrentIndex(index); +} + +void DataFilesPage::slotCurrentIndexChanged(int index) +{ + emit profileChanged(index); +} + +QAbstractItemModel* DataFilesPage::profilesComboBoxModel() +{ + return profilesComboBox->model(); +} + +int DataFilesPage::profilesComboBoxIndex() +{ + return profilesComboBox->currentIndex(); +} + void DataFilesPage::deleteProfile() { QString profile = profilesComboBox->currentText(); diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index e98b09aef7..301abf59bf 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -7,11 +7,11 @@ #include "ui_datafilespage.h" class QSortFilterProxyModel; +class QAbstractItemModel; class QAction; class QMenu; class DataFilesModel; - class TextInputDialog; class GameSettings; class LauncherSettings; @@ -26,12 +26,19 @@ class DataFilesPage : public QWidget, private Ui::DataFilesPage public: DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gameSettings, LauncherSettings &launcherSettings, QWidget *parent = 0); + QAbstractItemModel* profilesComboBoxModel(); + int profilesComboBoxIndex(); + void writeConfig(QString profile = QString()); void saveSettings(); +signals: + void profileChanged(int index); public slots: void setCheckState(QModelIndex index); + void setProfilesComboBoxIndex(int index); + void filterChanged(const QString filter); void showContextMenu(const QPoint &point); void profileChanged(const QString &previous, const QString ¤t); @@ -47,6 +54,9 @@ public slots: void uncheck(); void refresh(); +private slots: + void slotCurrentIndexChanged(int index); + private: DataFilesModel *mDataFilesModel; diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index cab763b105..6a3965cc91 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -93,8 +93,8 @@ void MainDialog::createPages() mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this); // Set the combobox of the play page to imitate the combobox on the datafilespage -// mPlayPage->setProfilesComboBoxModel(mDataFilesPage->mProfilesComboBox->model()); -// mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->mProfilesComboBox->currentIndex()); + mPlayPage->setProfilesComboBoxModel(mDataFilesPage->profilesComboBoxModel()); + mPlayPage->setProfilesComboBoxIndex(mDataFilesPage->profilesComboBoxIndex()); // Add the pages to the stacked widget pagesWidget->addWidget(mPlayPage); @@ -106,8 +106,8 @@ void MainDialog::createPages() connect(mPlayPage, SIGNAL(playButtonClicked()), this, SLOT(play())); -// connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage->mProfilesComboBox, SLOT(setCurrentIndex(int))); -// connect(mDataFilesPage->mProfilesComboBox, SIGNAL(currentIndexChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int))); + connect(mPlayPage, SIGNAL(profileChanged(int)), mDataFilesPage, SLOT(setProfilesComboBoxIndex(int))); + connect(mDataFilesPage, SIGNAL(profileChanged(int)), mPlayPage, SLOT(setProfilesComboBoxIndex(int))); } From 770d8af931ea7ad75c3a978761eb36fcd4e1e37c Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Tue, 5 Mar 2013 03:57:27 +0100 Subject: [PATCH 34/37] Forgot to add the DataFilesPage .ui --- apps/launcher/ui/datafilespage.ui | 125 ++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 apps/launcher/ui/datafilespage.ui diff --git a/apps/launcher/ui/datafilespage.ui b/apps/launcher/ui/datafilespage.ui new file mode 100644 index 0000000000..91b5475e67 --- /dev/null +++ b/apps/launcher/ui/datafilespage.ui @@ -0,0 +1,125 @@ + + + DataFilesPage + + + + 0 + 0 + 520 + 256 + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Filter: + + + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + false + + + + + + + + + + + Current Profile: + + + + + + + + 0 + 0 + + + + + + + + New Profile + + + &New Profile + + + true + + + + + + + Delete Profile + + + Delete Profile + + + Ctrl+D + + + true + + + + + + + + + + LineEdit + QLineEdit +
components/fileorderlist/utils/lineedit.hpp
+
+ + ProfilesComboBox + QComboBox +
components/fileorderlist/utils/profilescombobox.hpp
+
+
+ + +
From c9859382bf70ef009a9a3f932e0a1ad6b2bf261d Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Wed, 6 Mar 2013 01:35:32 +0100 Subject: [PATCH 35/37] Made the launcher write the custom resolution to file, cleaned resolution parsing --- apps/launcher/graphicspage.cpp | 43 ++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 5905043548..6d5b3ab09e 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -190,11 +190,17 @@ void GraphicsPage::saveSettings() mGraphicsSettings.setValue(QString("Video/antialiasing"), antiAliasingComboBox->currentText()); mGraphicsSettings.setValue(QString("Video/render system"), rendererComboBox->currentText()); - QRegExp resolutionRe(QString("(\\d+) x (\\d+).*")); - if (resolutionRe.exactMatch(resolutionComboBox->currentText().simplified())) { - mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1)); - mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2)); + if (standardRadioButton->isChecked()) { + QRegExp resolutionRe(QString("(\\d+) x (\\d+).*")); + + if (resolutionRe.exactMatch(resolutionComboBox->currentText().simplified())) { + mGraphicsSettings.setValue(QString("Video/resolution x"), resolutionRe.cap(1)); + mGraphicsSettings.setValue(QString("Video/resolution y"), resolutionRe.cap(2)); + } + } else { + mGraphicsSettings.setValue(QString("Video/resolution x"), QString::number(customWidthSpinBox->value())); + mGraphicsSettings.setValue(QString("Video/resolution y"), QString::number(customHeightSpinBox->value())); } } @@ -250,25 +256,26 @@ QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer) for (opt_it = i->second.possibleValues.begin (); opt_it != i->second.possibleValues.end (); opt_it++, idx++) { - QString qval = QString::fromStdString(*opt_it).simplified(); - // remove extra tokens after the resolution (for example bpp, can be there or not depending on rendersystem) - QStringList tokens = qval.split(" ", QString::SkipEmptyParts); - assert (tokens.size() >= 3); + QRegExp resolutionRe(QString("(\\d+) x (\\d+)")); + QString resolution = QString::fromStdString(*opt_it).simplified(); - QString resolutionStr = tokens.at(0) + QString(" x ") + tokens.at(2); + if (resolutionRe.exactMatch(resolution)) { - QString aspect = getAspect(tokens.at(0).toInt(),tokens.at(2).toInt()); + int width = resolutionRe.cap(1).toInt(); + int height = resolutionRe.cap(2).toInt(); - if (aspect == QLatin1String("16:9") || aspect == QLatin1String("16:10")) { - resolutionStr.append(tr("\t(Widescreen ") + aspect + ")"); + QString aspect = getAspect(width, height); - } else if (aspect == QLatin1String("4:3")) { - resolutionStr.append(tr("\t(Standard 4:3)")); + if (aspect == QLatin1String("16:9") || aspect == QLatin1String("16:10")) { + resolution.append(tr("\t(Wide ") + aspect + ")"); + + } else if (aspect == QLatin1String("4:3")) { + resolution.append(tr("\t(Standard 4:3)")); + } + // do not add duplicate resolutions + if (!result.contains(resolution)) + result.append(resolution); } - - // do not add duplicate resolutions - if (!result.contains(resolutionStr)) - result << resolutionStr; } } From 7504ae675b44c4ebea2509d8ef3e8381200111d3 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Thu, 7 Mar 2013 03:00:59 +0100 Subject: [PATCH 36/37] Implemented a file dialog for the editor using launcher .ui --- apps/launcher/CMakeLists.txt | 16 +- apps/launcher/datafilespage.cpp | 60 +--- apps/launcher/resources.qrc | 21 -- apps/opencs/CMakeLists.txt | 6 +- apps/opencs/editor.cpp | 101 ++++-- apps/opencs/editor.hpp | 15 +- apps/opencs/view/doc/filedialog.cpp | 272 ++++++++++++++++ apps/opencs/view/doc/filedialog.hpp | 66 ++++ components/CMakeLists.txt | 2 +- components/fileorderlist/datafileslist.cpp | 293 ------------------ components/fileorderlist/datafileslist.hpp | 75 ----- .../fileorderlist/model/datafilesmodel.cpp | 1 + .../fileorderlist/model/datafilesmodel.hpp | 3 + .../model/pluginsproxymodel.cpp | 0 .../model/pluginsproxymodel.hpp | 0 .../launcher}/icons/tango/document-new.png | Bin .../launcher}/icons/tango/edit-copy.png | Bin .../launcher}/icons/tango/edit-delete.png | Bin .../launcher}/icons/tango/go-bottom.png | Bin .../launcher}/icons/tango/go-down.png | Bin .../launcher}/icons/tango/go-top.png | Bin .../launcher}/icons/tango/go-up.png | Bin .../launcher}/icons/tango/index.theme | 0 .../launcher}/icons/tango/video-display.png | Bin .../launcher}/images/clear.png | Bin .../launcher}/images/down.png | Bin .../launcher}/images/openmw-header.png | Bin .../launcher}/images/openmw-plugin.png | Bin .../launcher}/images/openmw.ico | Bin .../launcher}/images/openmw.png | Bin .../launcher}/images/playpage-background.png | Bin files/launcher/launcher.qrc | 21 ++ {apps/launcher => files}/ui/datafilespage.ui | 2 +- {apps/launcher => files}/ui/graphicspage.ui | 0 {apps/launcher => files}/ui/mainwindow.ui | 0 {apps/launcher => files}/ui/playpage.ui | 0 36 files changed, 464 insertions(+), 490 deletions(-) delete mode 100644 apps/launcher/resources.qrc create mode 100644 apps/opencs/view/doc/filedialog.cpp create mode 100644 apps/opencs/view/doc/filedialog.hpp delete mode 100644 components/fileorderlist/datafileslist.cpp delete mode 100644 components/fileorderlist/datafileslist.hpp rename {apps/launcher => components/fileorderlist}/model/pluginsproxymodel.cpp (100%) rename {apps/launcher => components/fileorderlist}/model/pluginsproxymodel.hpp (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/document-new.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/edit-copy.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/edit-delete.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/go-bottom.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/go-down.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/go-top.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/go-up.png (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/index.theme (100%) rename {apps/launcher/resources => files/launcher}/icons/tango/video-display.png (100%) rename {apps/launcher/resources => files/launcher}/images/clear.png (100%) rename {apps/launcher/resources => files/launcher}/images/down.png (100%) rename {apps/launcher/resources => files/launcher}/images/openmw-header.png (100%) rename {apps/launcher/resources => files/launcher}/images/openmw-plugin.png (100%) rename {apps/launcher/resources => files/launcher}/images/openmw.ico (100%) rename {apps/launcher/resources => files/launcher}/images/openmw.png (100%) rename {apps/launcher/resources => files/launcher}/images/playpage-background.png (100%) create mode 100644 files/launcher/launcher.qrc rename {apps/launcher => files}/ui/datafilespage.ui (98%) rename {apps/launcher => files}/ui/graphicspage.ui (100%) rename {apps/launcher => files}/ui/mainwindow.ui (100%) rename {apps/launcher => files}/ui/playpage.ui (100%) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index a1c2289456..a63898c0ec 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -5,8 +5,6 @@ set(LAUNCHER maindialog.cpp playpage.cpp - model/pluginsproxymodel.cpp - settings/gamesettings.cpp settings/graphicssettings.cpp settings/launchersettings.cpp @@ -23,8 +21,6 @@ set(LAUNCHER_HEADER maindialog.hpp playpage.hpp - model/pluginsproxymodel.hpp - settings/gamesettings.hpp settings/graphicssettings.hpp settings/launchersettings.hpp @@ -42,17 +38,15 @@ set(LAUNCHER_HEADER_MOC maindialog.hpp playpage.hpp - model/pluginsproxymodel.hpp - utils/checkablemessagebox.hpp utils/textinputdialog.hpp ) set(LAUNCHER_UI - ui/datafilespage.ui - ui/graphicspage.ui - ui/mainwindow.ui - ui/playpage.ui + ../../files/ui/datafilespage.ui + ../../files/ui/graphicspage.ui + ../../files/ui/mainwindow.ui + ../../files/ui/playpage.ui ) source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) @@ -66,7 +60,7 @@ if(WIN32) set(QT_USE_QTMAIN TRUE) endif(WIN32) -QT4_ADD_RESOURCES(RCC_SRCS resources.qrc) +QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc) QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI}) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 069cdd9ac9..90cdd29425 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -2,25 +2,21 @@ #include -#include #include #include +#include #include #include #include #include -#include "model/pluginsproxymodel.hpp" - #include "settings/gamesettings.hpp" #include "settings/launchersettings.hpp" #include "utils/textinputdialog.hpp" -using namespace ESM; -using namespace std; //sort QModelIndexList ascending bool rowGreaterThan(const QModelIndex &index1, const QModelIndex &index2) @@ -100,60 +96,6 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam splitter->setSizes(sizeList); -// // Filter toolbar -// QLabel *filterLabel = new QLabel(tr("&Filter:"), this); -// LineEdit *filterLineEdit = new LineEdit(this); -// filterLabel->setBuddy(filterLineEdit); - -// QToolBar *filterToolBar = new QToolBar(this); -// filterToolBar->setMovable(false); - -// // Create a container widget and a layout to get the spacer to work -// QWidget *filterWidget = new QWidget(this); -// QHBoxLayout *filterLayout = new QHBoxLayout(filterWidget); -// QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - -// filterLayout->addItem(hSpacer1); -// filterLayout->addWidget(filterLabel); -// filterLayout->addWidget(filterLineEdit); - -// filterToolBar->addWidget(filterWidget); - - - -// // Add both tables to a splitter -// mSplitter = new QSplitter(this); -// mSplitter->setOrientation(Qt::Horizontal); -// mSplitter->setChildrenCollapsible(false); // Don't allow the widgets to be hidden -// mSplitter->addWidget(mastersTable); -// mSplitter->addWidget(pluginsTable); - - - -// - -// // Bottom part with profile options -// QLabel *profileLabel = new QLabel(tr("Current Profile: "), this); - -// profilesComboBox = new ProfilesComboBox(this); -// profilesComboBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); -// profilesComboBox->setInsertPolicy(QComboBox::NoInsert); -// profilesComboBox->setDuplicatesEnabled(false); -// profilesComboBox->setEditEnabled(false); - -// mProfileToolBar = new QToolBar(this); -// mProfileToolBar->setMovable(false); -// mProfileToolBar->setIconSize(QSize(16, 16)); - -// mProfileToolBar->addWidget(profileLabel); -// mProfileToolBar->addWidget(profilesComboBox); - -// QVBoxLayout *pageLayout = new QVBoxLayout(this); - -// pageLayout->addWidget(filterToolBar); -// pageLayout->addWidget(mSplitter); -// pageLayout->addWidget(mProfileToolBar); - // Create a dialog for the new profile name input mNewProfileDialog = new TextInputDialog(tr("New Profile"), tr("Profile name:"), this); diff --git a/apps/launcher/resources.qrc b/apps/launcher/resources.qrc deleted file mode 100644 index 2b56f80fd6..0000000000 --- a/apps/launcher/resources.qrc +++ /dev/null @@ -1,21 +0,0 @@ - - - resources/images/clear.png - resources/images/down.png - resources/images/openmw.png - resources/images/openmw-plugin.png - resources/images/openmw-header.png - resources/images/playpage-background.png - - - resources/icons/tango/index.theme - resources/icons/tango/video-display.png - resources/icons/tango/document-new.png - resources/icons/tango/edit-copy.png - resources/icons/tango/edit-delete.png - resources/icons/tango/go-bottom.png - resources/icons/tango/go-down.png - resources/icons/tango/go-top.png - resources/icons/tango/go-up.png - - diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d5d389a141..0071dd1fc7 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -41,7 +41,7 @@ opencs_units_noqt (model/tools opencs_units (view/doc - viewmanager view operations operation subview startup opendialog + viewmanager view operations operation subview startup filedialog ) @@ -76,6 +76,10 @@ set (OPENCS_US ) set (OPENCS_RES ../../files/opencs/resources.qrc + ../../files/launcher/launcher.qrc + ) + +set (OPENCS_UI ../../files/ui/datafilespage.ui ) source_group (opencs FILES ${OPENCS_SRC} ${OPENCS_HDR}) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index e2df365a29..5966d089e3 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -1,14 +1,12 @@ #include "editor.hpp" -#include - #include #include "model/doc/document.hpp" #include "model/world/data.hpp" -CS::Editor::Editor() : mViewManager (mDocumentManager), mNewDocumentIndex (0) +CS::Editor::Editor() : mViewManager (mDocumentManager) { connect (&mViewManager, SIGNAL (newDocumentRequest ()), this, SLOT (createDocument ())); connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ())); @@ -16,42 +14,99 @@ CS::Editor::Editor() : mViewManager (mDocumentManager), mNewDocumentIndex (0) connect (&mStartup, SIGNAL (createDocument()), this, SLOT (createDocument ())); connect (&mStartup, SIGNAL (loadDocument()), this, SLOT (loadDocument ())); - connect (&mOpenDialog, SIGNAL(accepted()), this, SLOT(openFiles())); + connect (&mFileDialog, SIGNAL(openFiles()), this, SLOT(openFiles())); + connect (&mFileDialog, SIGNAL(createNewFile()), this, SLOT(createNewFile())); + + setupDataFiles(); +} + +void CS::Editor::setupDataFiles() +{ + boost::program_options::variables_map variables; + boost::program_options::options_description desc; + + desc.add_options() + ("data", boost::program_options::value()->default_value(Files::PathContainer(), "data")->multitoken()) + ("data-local", boost::program_options::value()->default_value("")) + ("fs-strict", boost::program_options::value()->implicit_value(true)->default_value(false)) + ("encoding", boost::program_options::value()->default_value("win1252")); + + boost::program_options::notify(variables); + + mCfgMgr.readConfiguration(variables, desc); + + Files::PathContainer mDataDirs, mDataLocal; + if (!variables["data"].empty()) { + mDataDirs = Files::PathContainer(variables["data"].as()); + } + + std::string local = variables["data-local"].as(); + if (!local.empty()) { + mDataLocal.push_back(Files::PathContainer::value_type(local)); + } + + mCfgMgr.processPaths(mDataDirs); + mCfgMgr.processPaths(mDataLocal); + + // Set the charset for reading the esm/esp files + QString encoding = QString::fromStdString(variables["encoding"].as()); + mFileDialog.setEncoding(encoding); + + Files::PathContainer dataDirs; + dataDirs.insert(dataDirs.end(), mDataDirs.begin(), mDataDirs.end()); + dataDirs.insert(dataDirs.end(), mDataLocal.begin(), mDataLocal.end()); + + for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter) + { + QString path = QString::fromStdString(iter->string()); + mFileDialog.addFiles(path); + } } void CS::Editor::createDocument() { mStartup.hide(); - /// \todo open the ESX picker instead - - std::ostringstream stream; - - stream << "NewDocument" << (++mNewDocumentIndex); - - std::vector files; - files.push_back (stream.str()); - - CSMDoc::Document *document = mDocumentManager.addDocument (files, true); - - mViewManager.addView (document); + mFileDialog.newFile(); } void CS::Editor::loadDocument() { mStartup.hide(); - mOpenDialog.show(); - mOpenDialog.raise(); - mOpenDialog.activateWindow(); + + mFileDialog.openFile(); } void CS::Editor::openFiles() { - std::vector paths; - mOpenDialog.getFileList(paths); - CSMDoc::Document *document = mDocumentManager.addDocument(paths, false); + std::vector files; + QStringList paths = mFileDialog.checkedItemsPaths(); + + foreach (const QString &path, paths) { + files.push_back(path.toStdString()); + } + + CSMDoc::Document *document = mDocumentManager.addDocument(files, false); mViewManager.addView (document); + mFileDialog.hide(); +} + +void CS::Editor::createNewFile() +{ + std::vector files; + QStringList paths = mFileDialog.checkedItemsPaths(); + + foreach (const QString &path, paths) { + files.push_back(path.toStdString()); + } + + files.push_back(mFileDialog.fileName().toStdString()); + + CSMDoc::Document *document = mDocumentManager.addDocument (files, true); + + mViewManager.addView (document); + mFileDialog.hide(); } int CS::Editor::run() @@ -59,4 +114,4 @@ int CS::Editor::run() mStartup.show(); return QApplication::exec(); -} \ No newline at end of file +} diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 024475bf01..c242a17ea8 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -3,11 +3,13 @@ #include +#include + #include "model/doc/documentmanager.hpp" #include "view/doc/viewmanager.hpp" #include "view/doc/startup.hpp" -#include "view/doc/opendialog.hpp" +#include "view/doc/filedialog.hpp" namespace CS { @@ -15,12 +17,14 @@ namespace CS { Q_OBJECT - int mNewDocumentIndex; ///< \todo remove when the proper new document dialogue is implemented. - CSMDoc::DocumentManager mDocumentManager; CSVDoc::ViewManager mViewManager; CSVDoc::StartupDialogue mStartup; - OpenDialog mOpenDialog; + FileDialog mFileDialog; + + Files::ConfigurationManager mCfgMgr; + + void setupDataFiles(); // not implemented Editor (const Editor&); @@ -39,7 +43,8 @@ namespace CS void loadDocument(); void openFiles(); + void createNewFile(); }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/view/doc/filedialog.cpp b/apps/opencs/view/doc/filedialog.cpp new file mode 100644 index 0000000000..f956317a71 --- /dev/null +++ b/apps/opencs/view/doc/filedialog.cpp @@ -0,0 +1,272 @@ +#include "filedialog.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +FileDialog::FileDialog(QWidget *parent) : + QDialog(parent) +{ + setupUi(this); + + // Models + mDataFilesModel = new DataFilesModel(this); + + mMastersProxyModel = new QSortFilterProxyModel(); + mMastersProxyModel->setFilterRegExp(QString("^.*\\.esm")); + mMastersProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + mMastersProxyModel->setSourceModel(mDataFilesModel); + + mPluginsProxyModel = new PluginsProxyModel(); + mPluginsProxyModel->setFilterRegExp(QString("^.*\\.esp")); + mPluginsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + mPluginsProxyModel->setSourceModel(mDataFilesModel); + + mFilterProxyModel = new QSortFilterProxyModel(); + mFilterProxyModel->setDynamicSortFilter(true); + mFilterProxyModel->setSourceModel(mPluginsProxyModel); + + QCheckBox checkBox; + unsigned int height = checkBox.sizeHint().height() + 4; + + mastersTable->setModel(mMastersProxyModel); + mastersTable->setObjectName("MastersTable"); + mastersTable->setContextMenuPolicy(Qt::CustomContextMenu); + mastersTable->setSortingEnabled(false); + mastersTable->setSelectionBehavior(QAbstractItemView::SelectRows); + mastersTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + mastersTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + mastersTable->setAlternatingRowColors(true); + mastersTable->horizontalHeader()->setStretchLastSection(true); + + // Set the row height to the size of the checkboxes + mastersTable->verticalHeader()->setDefaultSectionSize(height); + mastersTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); + mastersTable->verticalHeader()->hide(); + + pluginsTable->setModel(mFilterProxyModel); + pluginsTable->setObjectName("PluginsTable"); + pluginsTable->setContextMenuPolicy(Qt::CustomContextMenu); + pluginsTable->setSortingEnabled(false); + pluginsTable->setSelectionBehavior(QAbstractItemView::SelectRows); + pluginsTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + pluginsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + pluginsTable->setAlternatingRowColors(true); + pluginsTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); + pluginsTable->horizontalHeader()->setStretchLastSection(true); + + pluginsTable->verticalHeader()->setDefaultSectionSize(height); + pluginsTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); + + // Hide the profile elements + profileLabel->hide(); + profilesComboBox->hide(); + newProfileButton->hide(); + deleteProfileButton->hide(); + + // Add some extra widgets + QHBoxLayout *nameLayout = new QHBoxLayout(); + QSpacerItem *spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + mNameLabel = new QLabel(tr("File Name:"), this); + + QRegExpValidator *validator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9\\s]*$")); + mNameLineEdit = new LineEdit(this); + mNameLineEdit->setValidator(validator); + + nameLayout->addSpacerItem(spacer); + nameLayout->addWidget(mNameLabel); + nameLayout->addWidget(mNameLineEdit); + + mButtonBox = new QDialogButtonBox(this); + + mCreateButton = new QPushButton(tr("Create"), this); + mCreateButton->setEnabled(false); + + verticalLayout->addLayout(nameLayout); + verticalLayout->addWidget(mButtonBox); + + // Set sizes + QList sizeList; + sizeList << 175; + sizeList << 200; + + splitter->setSizes(sizeList); + + resize(600, 400); + + connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews())); + connect(mDataFilesModel, SIGNAL(checkedItemsChanged(QStringList)), this, SLOT(updateOpenButton(QStringList))); + connect(mNameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(updateCreateButton(QString))); + + connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); + + connect(pluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + connect(mastersTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); + + connect(mCreateButton, SIGNAL(clicked()), this, SLOT(createButtonClicked())); + + connect(mButtonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(mButtonBox, SIGNAL(rejected()), this, SLOT(reject())); +} + +void FileDialog::updateViews() +{ + // Ensure the columns are hidden because sort() re-enables them + mastersTable->setColumnHidden(1, true); + mastersTable->setColumnHidden(3, true); + mastersTable->setColumnHidden(4, true); + mastersTable->setColumnHidden(5, true); + mastersTable->setColumnHidden(6, true); + mastersTable->setColumnHidden(7, true); + mastersTable->setColumnHidden(8, true); + mastersTable->resizeColumnsToContents(); + + pluginsTable->setColumnHidden(1, true); + pluginsTable->setColumnHidden(3, true); + pluginsTable->setColumnHidden(4, true); + pluginsTable->setColumnHidden(5, true); + pluginsTable->setColumnHidden(6, true); + pluginsTable->setColumnHidden(7, true); + pluginsTable->setColumnHidden(8, true); + pluginsTable->resizeColumnsToContents(); + +} + +void FileDialog::updateOpenButton(const QStringList &items) +{ + QPushButton *openButton = mButtonBox->button(QDialogButtonBox::Open); + + if (!openButton) + return; + + openButton->setEnabled(!items.isEmpty()); +} + +void FileDialog::updateCreateButton(const QString &name) +{ + if (!mCreateButton->isVisible()) + return; + + mCreateButton->setEnabled(!name.isEmpty()); +} + +void FileDialog::filterChanged(const QString &filter) +{ + QRegExp filterRe(filter, Qt::CaseInsensitive, QRegExp::FixedString); + mFilterProxyModel->setFilterRegExp(filterRe); +} + +void FileDialog::addFiles(const QString &path) +{ + mDataFilesModel->addFiles(path); + mDataFilesModel->sort(3); // Sort by date accessed +} + +void FileDialog::setEncoding(const QString &encoding) +{ + mDataFilesModel->setEncoding(encoding); +} + +void FileDialog::setCheckState(QModelIndex index) +{ + if (!index.isValid()) + return; + + QObject *object = QObject::sender(); + + // Not a signal-slot call + if (!object) + return; + + + if (object->objectName() == QLatin1String("PluginsTable")) { + QModelIndex sourceIndex = mPluginsProxyModel->mapToSource( + mFilterProxyModel->mapToSource(index)); + + if (sourceIndex.isValid()) { + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked) + : mDataFilesModel->setCheckState(sourceIndex, Qt::Checked); + } + } + + if (object->objectName() == QLatin1String("MastersTable")) { + QModelIndex sourceIndex = mMastersProxyModel->mapToSource(index); + + if (sourceIndex.isValid()) { + (mDataFilesModel->checkState(sourceIndex) == Qt::Checked) + ? mDataFilesModel->setCheckState(sourceIndex, Qt::Unchecked) + : mDataFilesModel->setCheckState(sourceIndex, Qt::Checked); + } + } + + return; +} + +QStringList FileDialog::checkedItemsPaths() +{ + return mDataFilesModel->checkedItemsPaths(); +} + +QString FileDialog::fileName() +{ + return mNameLineEdit->text(); +} + +void FileDialog::openFile() +{ + setWindowTitle(tr("Open")); + + mNameLabel->hide(); + mNameLineEdit->hide(); + mCreateButton->hide(); + + mButtonBox->removeButton(mCreateButton); + mButtonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Open); + QPushButton *openButton = mButtonBox->button(QDialogButtonBox::Open); + openButton->setEnabled(false); + + show(); + raise(); + activateWindow(); +} + +void FileDialog::newFile() +{ + setWindowTitle(tr("New")); + + mNameLabel->show(); + mNameLineEdit->clear(); + mNameLineEdit->show(); + mCreateButton->show(); + + mButtonBox->setStandardButtons(QDialogButtonBox::Cancel); + mButtonBox->addButton(mCreateButton, QDialogButtonBox::ActionRole); + + show(); + raise(); + activateWindow(); +} + +void FileDialog::accept() +{ + emit openFiles(); +} + +void FileDialog::createButtonClicked() +{ + emit createNewFile(); +} diff --git a/apps/opencs/view/doc/filedialog.hpp b/apps/opencs/view/doc/filedialog.hpp new file mode 100644 index 0000000000..b21618d5de --- /dev/null +++ b/apps/opencs/view/doc/filedialog.hpp @@ -0,0 +1,66 @@ +#ifndef FILEDIALOG_HPP +#define FILEDIALOG_HPP + +#include +#include + +#include "ui_datafilespage.h" + +class QDialogButtonBox; +class QSortFilterProxyModel; +class QAbstractItemModel; +class QPushButton; +class QStringList; +class QString; +class QMenu; + +class DataFilesModel; +class PluginsProxyModel; + +class FileDialog : public QDialog, private Ui::DataFilesPage +{ + Q_OBJECT +public: + explicit FileDialog(QWidget *parent = 0); + void addFiles(const QString &path); + void setEncoding(const QString &encoding); + + void openFile(); + void newFile(); + void accepted(); + + QStringList checkedItemsPaths(); + QString fileName(); + +signals: + void openFiles(); + void createNewFile(); + +public slots: + void accept(); + +private slots: + void updateViews(); + void updateOpenButton(const QStringList &items); + void updateCreateButton(const QString &name); + void setCheckState(QModelIndex index); + + void filterChanged(const QString &filter); + + void createButtonClicked(); + +private: + QLabel *mNameLabel; + LineEdit *mNameLineEdit; + + QPushButton *mCreateButton; + QDialogButtonBox *mButtonBox; + + DataFilesModel *mDataFilesModel; + + PluginsProxyModel *mPluginsProxyModel; + QSortFilterProxyModel *mMastersProxyModel; + QSortFilterProxyModel *mFilterProxyModel; +}; + +#endif // FILEDIALOG_HPP diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 7c52ab12cc..a4b194fab3 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -70,7 +70,7 @@ find_package(Qt4 COMPONENTS QtCore QtGui) if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) add_component_qt_dir (fileorderlist - datafileslist model/modelitem model/datafilesmodel model/esm/esmfile + model/modelitem model/datafilesmodel model/pluginsproxymodel model/esm/esmfile utils/profilescombobox utils/comboboxlineedit utils/lineedit utils/naturalsort ) diff --git a/components/fileorderlist/datafileslist.cpp b/components/fileorderlist/datafileslist.cpp deleted file mode 100644 index 9fe8d0fea2..0000000000 --- a/components/fileorderlist/datafileslist.cpp +++ /dev/null @@ -1,293 +0,0 @@ -#include - -#include -#include - -#include "model/datafilesmodel.hpp" -#include "model/esm/esmfile.hpp" - -#include "utils/lineedit.hpp" - -#include "datafileslist.hpp" - -#include -/** - * Workaround for problems with whitespaces in paths in older versions of Boost library - */ -#if (BOOST_VERSION <= 104600) -namespace boost -{ - - template<> - inline boost::filesystem::path lexical_cast(const std::string& arg) - { - return boost::filesystem::path(arg); - } - -} /* namespace boost */ -#endif /* (BOOST_VERSION <= 104600) */ - -using namespace ESM; -using namespace std; - -//sort QModelIndexList ascending -bool rowGreaterThan(const QModelIndex &index1, const QModelIndex &index2) -{ - return index1.row() >= index2.row(); -} - -//sort QModelIndexList descending -bool rowSmallerThan(const QModelIndex &index1, const QModelIndex &index2) -{ - return index1.row() <= index2.row(); -} - -DataFilesList::DataFilesList(Files::ConfigurationManager &cfg, QWidget *parent) - : QWidget(parent) - , mCfgMgr(cfg) -{ - // Model - mFilesModel = new DataFilesModel(this); - - mFilesProxyModel = new QSortFilterProxyModel(); - mFilesProxyModel->setDynamicSortFilter(true); - mFilesProxyModel->setSourceModel(mFilesModel); - - // Filter toolbar - QLabel *filterLabel = new QLabel(tr("&Filter:"), this); - LineEdit *filterLineEdit = new LineEdit(this); - filterLabel->setBuddy(filterLineEdit); - - QToolBar *filterToolBar = new QToolBar(this); - filterToolBar->setMovable(false); - - // Create a container widget and a layout to get the spacer to work - QWidget *filterWidget = new QWidget(this); - QHBoxLayout *filterLayout = new QHBoxLayout(filterWidget); - QSpacerItem *hSpacer1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - filterLayout->addItem(hSpacer1); - filterLayout->addWidget(filterLabel); - filterLayout->addWidget(filterLineEdit); - - filterToolBar->addWidget(filterWidget); - - QCheckBox checkBox; - unsigned int height = checkBox.sizeHint().height() + 4; - - mFilesTable = new QTableView(this); - mFilesTable->setModel(mFilesProxyModel); - mFilesTable->setObjectName("PluginsTable"); - mFilesTable->setContextMenuPolicy(Qt::CustomContextMenu); - mFilesTable->setSelectionBehavior(QAbstractItemView::SelectRows); - mFilesTable->setSelectionMode(QAbstractItemView::SingleSelection); - mFilesTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - mFilesTable->setAlternatingRowColors(true); - mFilesTable->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); - mFilesTable->horizontalHeader()->setStretchLastSection(true); - mFilesTable->horizontalHeader()->hide(); - - mFilesTable->verticalHeader()->setDefaultSectionSize(height); - mFilesTable->verticalHeader()->setResizeMode(QHeaderView::Fixed); - mFilesTable->setColumnHidden(1, true); - mFilesTable->setColumnHidden(2, true); - mFilesTable->setColumnHidden(3, true); - mFilesTable->setColumnHidden(4, true); - mFilesTable->setColumnHidden(5, true); - mFilesTable->setColumnHidden(6, true); - mFilesTable->setColumnHidden(7, true); - mFilesTable->setColumnHidden(8, true); - - QVBoxLayout *pageLayout = new QVBoxLayout(this); - - pageLayout->addWidget(filterToolBar); - pageLayout->addWidget(mFilesTable); - - connect(mFilesTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); - - connect(mFilesModel, SIGNAL(checkedItemsChanged(QStringList,QStringList)), mFilesModel, SLOT(slotcheckedItemsChanged(QStringList,QStringList))); - - connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); - - connect(mFilesTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); - - createActions(); -} - -void DataFilesList::createActions() -{ - // Refresh the plugins - QAction *refreshAction = new QAction(tr("Refresh"), this); - refreshAction->setShortcut(QKeySequence(tr("F5"))); - connect(refreshAction, SIGNAL(triggered()), this, SLOT(refresh())); - - // Context menu actions - mCheckAction = new QAction(tr("Check selected"), this); - connect(mCheckAction, SIGNAL(triggered()), this, SLOT(check())); - - mUncheckAction = new QAction(tr("Uncheck selected"), this); - connect(mUncheckAction, SIGNAL(triggered()), this, SLOT(uncheck())); - - // Context menu for the plugins table - mContextMenu = new QMenu(this); - - mContextMenu->addAction(mCheckAction); - mContextMenu->addAction(mUncheckAction); - -} - -bool DataFilesList::setupDataFiles(Files::PathContainer dataDirs, const QString encoding) -{ - // Set the charset for reading the esm/esp files - if (!encoding.isEmpty() && encoding != QLatin1String("win1252")) { - mFilesModel->setEncoding(encoding); - } - - // Add the paths to the respective models - for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { - QString path = QString::fromStdString(it->string()); - path.remove(QChar('\"')); - mFilesModel->addFiles(path); - } - - mFilesModel->sort(0); -// mMastersTable->sortByColumn(3, Qt::AscendingOrder); -// mPluginsTable->sortByColumn(3, Qt::AscendingOrder); - - return true; -} - -void DataFilesList::selectedFiles(std::vector& paths) -{ - QStringList pluginPaths = mFilesModel->checkedItemsPaths(); - foreach (const QString &path, pluginPaths) - { - paths.push_back(path.toStdString()); - } -} - -void DataFilesList::check() -{ - // Check the current selection - if (!mFilesTable->selectionModel()->hasSelection()) { - return; - } - - QModelIndexList indexes = mFilesTable->selectionModel()->selectedIndexes(); - - //sort selection ascending because selectedIndexes returns an unsorted list - //qSort(indexes.begin(), indexes.end(), rowSmallerThan); - - foreach (const QModelIndex &index, indexes) { - if (!index.isValid()) - return; - - mFilesModel->setCheckState(index, Qt::Checked); - } -} - -void DataFilesList::uncheck() -{ - // uncheck the current selection - if (!mFilesTable->selectionModel()->hasSelection()) { - return; - } - - QModelIndexList indexes = mFilesTable->selectionModel()->selectedIndexes(); - - //sort selection ascending because selectedIndexes returns an unsorted list - //qSort(indexes.begin(), indexes.end(), rowSmallerThan); - - foreach (const QModelIndex &index, indexes) { - if (!index.isValid()) - return; - - mFilesModel->setCheckState(index, Qt::Unchecked); - } -} - -void DataFilesList::refresh() -{ - mFilesModel->sort(0); - - - // Refresh the plugins table - mFilesTable->scrollToTop(); -} - - -void DataFilesList::setCheckState(QModelIndex index) -{ - if (!index.isValid()) - return; - - QObject *object = QObject::sender(); - - // Not a signal-slot call - if (!object) - return; - - if (object->objectName() == QLatin1String("PluginsTable")) { - QModelIndex sourceIndex = mFilesProxyModel->mapToSource(index); - - (mFilesModel->checkState(sourceIndex) == Qt::Checked) - ? mFilesModel->setCheckState(sourceIndex, Qt::Unchecked) - : mFilesModel->setCheckState(sourceIndex, Qt::Checked); - } - - return; - -} - -void DataFilesList::uncheckAll() -{ - mFilesModel->uncheckAll(); -} - -void DataFilesList::filterChanged(const QString filter) -{ - QRegExp regExp(filter, Qt::CaseInsensitive, QRegExp::FixedString); - mFilesProxyModel->setFilterRegExp(regExp); -} - -void DataFilesList::showContextMenu(const QPoint &point) -{ - // Make sure there are plugins in the view - if (!mFilesTable->selectionModel()->hasSelection()) { - return; - } - - QPoint globalPos = mFilesTable->mapToGlobal(point); - - QModelIndexList indexes = mFilesTable->selectionModel()->selectedIndexes(); - - // Show the check/uncheck actions depending on the state of the selected items - mUncheckAction->setEnabled(false); - mCheckAction->setEnabled(false); - - foreach (const QModelIndex &index, indexes) { - if (!index.isValid()) - return; - - (mFilesModel->checkState(index) == Qt::Checked) - ? mUncheckAction->setEnabled(true) - : mCheckAction->setEnabled(true); - } - - // Show menu - mContextMenu->exec(globalPos); -} - -void DataFilesList::setCheckState(const QString& element, Qt::CheckState state) -{ - EsmFile *file = mFilesModel->findItem(element); - if (file) - { - mFilesModel->setCheckState(mFilesModel->indexFromItem(file), Qt::Checked); - } -} - -QStringList DataFilesList::checkedFiles() -{ - return mFilesModel->checkedItems(); -} diff --git a/components/fileorderlist/datafileslist.hpp b/components/fileorderlist/datafileslist.hpp deleted file mode 100644 index 69a20393c2..0000000000 --- a/components/fileorderlist/datafileslist.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef DATAFILESLIST_H -#define DATAFILESLIST_H - -#include -#include -#include - - -class QTableView; -class QSortFilterProxyModel; -class QSettings; -class QAction; -class QToolBar; -class QMenu; -class ProfilesComboBox; -class DataFilesModel; - -class TextInputDialog; - -namespace Files { struct ConfigurationManager; } - -class DataFilesList : public QWidget -{ - Q_OBJECT - -public: - DataFilesList(Files::ConfigurationManager& cfg, QWidget *parent = 0); - - bool setupDataFiles(Files::PathContainer dataDirs, const QString encoding); - void selectedFiles(std::vector& paths); - void uncheckAll(); - QStringList checkedFiles(); - void setCheckState(const QString& element, Qt::CheckState); - - -public slots: - void setCheckState(QModelIndex index); - - void filterChanged(const QString filter); - void showContextMenu(const QPoint &point); - - // Action slots -// void moveUp(); -// void moveDown(); -// void moveTop(); -// void moveBottom(); - void check(); - void uncheck(); - void refresh(); - -private: - DataFilesModel *mFilesModel; - - QSortFilterProxyModel *mFilesProxyModel; - - QTableView *mFilesTable; - - QMenu *mContextMenu; - -// QAction *mMoveUpAction; -// QAction *mMoveDownAction; -// QAction *mMoveTopAction; -// QAction *mMoveBottomAction; - QAction *mCheckAction; - QAction *mUncheckAction; - - Files::ConfigurationManager &mCfgMgr; - -// const QStringList checkedPlugins(); -// const QStringList selectedMasters(); - - void createActions(); -}; - -#endif diff --git a/components/fileorderlist/model/datafilesmodel.cpp b/components/fileorderlist/model/datafilesmodel.cpp index 4e9b69dc27..b33e2e12ab 100644 --- a/components/fileorderlist/model/datafilesmodel.cpp +++ b/components/fileorderlist/model/datafilesmodel.cpp @@ -212,6 +212,7 @@ bool DataFilesModel::setData(const QModelIndex &index, const QVariant &value, in QModelIndex lastIndex = indexFromItem(mFiles.last()); emit dataChanged(firstIndex, lastIndex); + emit checkedItemsChanged(checkedItems()); return true; } diff --git a/components/fileorderlist/model/datafilesmodel.hpp b/components/fileorderlist/model/datafilesmodel.hpp index 0e5008abe1..0a07a536f8 100644 --- a/components/fileorderlist/model/datafilesmodel.hpp +++ b/components/fileorderlist/model/datafilesmodel.hpp @@ -48,6 +48,9 @@ public: QModelIndex indexFromItem(EsmFile *item) const; EsmFile* findItem(const QString &name); EsmFile* item(int row) const; + +signals: + void checkedItemsChanged(const QStringList &items); private: bool canBeChecked(EsmFile *file) const; diff --git a/apps/launcher/model/pluginsproxymodel.cpp b/components/fileorderlist/model/pluginsproxymodel.cpp similarity index 100% rename from apps/launcher/model/pluginsproxymodel.cpp rename to components/fileorderlist/model/pluginsproxymodel.cpp diff --git a/apps/launcher/model/pluginsproxymodel.hpp b/components/fileorderlist/model/pluginsproxymodel.hpp similarity index 100% rename from apps/launcher/model/pluginsproxymodel.hpp rename to components/fileorderlist/model/pluginsproxymodel.hpp diff --git a/apps/launcher/resources/icons/tango/document-new.png b/files/launcher/icons/tango/document-new.png similarity index 100% rename from apps/launcher/resources/icons/tango/document-new.png rename to files/launcher/icons/tango/document-new.png diff --git a/apps/launcher/resources/icons/tango/edit-copy.png b/files/launcher/icons/tango/edit-copy.png similarity index 100% rename from apps/launcher/resources/icons/tango/edit-copy.png rename to files/launcher/icons/tango/edit-copy.png diff --git a/apps/launcher/resources/icons/tango/edit-delete.png b/files/launcher/icons/tango/edit-delete.png similarity index 100% rename from apps/launcher/resources/icons/tango/edit-delete.png rename to files/launcher/icons/tango/edit-delete.png diff --git a/apps/launcher/resources/icons/tango/go-bottom.png b/files/launcher/icons/tango/go-bottom.png similarity index 100% rename from apps/launcher/resources/icons/tango/go-bottom.png rename to files/launcher/icons/tango/go-bottom.png diff --git a/apps/launcher/resources/icons/tango/go-down.png b/files/launcher/icons/tango/go-down.png similarity index 100% rename from apps/launcher/resources/icons/tango/go-down.png rename to files/launcher/icons/tango/go-down.png diff --git a/apps/launcher/resources/icons/tango/go-top.png b/files/launcher/icons/tango/go-top.png similarity index 100% rename from apps/launcher/resources/icons/tango/go-top.png rename to files/launcher/icons/tango/go-top.png diff --git a/apps/launcher/resources/icons/tango/go-up.png b/files/launcher/icons/tango/go-up.png similarity index 100% rename from apps/launcher/resources/icons/tango/go-up.png rename to files/launcher/icons/tango/go-up.png diff --git a/apps/launcher/resources/icons/tango/index.theme b/files/launcher/icons/tango/index.theme similarity index 100% rename from apps/launcher/resources/icons/tango/index.theme rename to files/launcher/icons/tango/index.theme diff --git a/apps/launcher/resources/icons/tango/video-display.png b/files/launcher/icons/tango/video-display.png similarity index 100% rename from apps/launcher/resources/icons/tango/video-display.png rename to files/launcher/icons/tango/video-display.png diff --git a/apps/launcher/resources/images/clear.png b/files/launcher/images/clear.png similarity index 100% rename from apps/launcher/resources/images/clear.png rename to files/launcher/images/clear.png diff --git a/apps/launcher/resources/images/down.png b/files/launcher/images/down.png similarity index 100% rename from apps/launcher/resources/images/down.png rename to files/launcher/images/down.png diff --git a/apps/launcher/resources/images/openmw-header.png b/files/launcher/images/openmw-header.png similarity index 100% rename from apps/launcher/resources/images/openmw-header.png rename to files/launcher/images/openmw-header.png diff --git a/apps/launcher/resources/images/openmw-plugin.png b/files/launcher/images/openmw-plugin.png similarity index 100% rename from apps/launcher/resources/images/openmw-plugin.png rename to files/launcher/images/openmw-plugin.png diff --git a/apps/launcher/resources/images/openmw.ico b/files/launcher/images/openmw.ico similarity index 100% rename from apps/launcher/resources/images/openmw.ico rename to files/launcher/images/openmw.ico diff --git a/apps/launcher/resources/images/openmw.png b/files/launcher/images/openmw.png similarity index 100% rename from apps/launcher/resources/images/openmw.png rename to files/launcher/images/openmw.png diff --git a/apps/launcher/resources/images/playpage-background.png b/files/launcher/images/playpage-background.png similarity index 100% rename from apps/launcher/resources/images/playpage-background.png rename to files/launcher/images/playpage-background.png diff --git a/files/launcher/launcher.qrc b/files/launcher/launcher.qrc new file mode 100644 index 0000000000..19b1c5a6f4 --- /dev/null +++ b/files/launcher/launcher.qrc @@ -0,0 +1,21 @@ + + + images/clear.png + images/down.png + images/openmw.png + images/openmw-plugin.png + images/openmw-header.png + images/playpage-background.png + + + icons/tango/index.theme + icons/tango/video-display.png + icons/tango/document-new.png + icons/tango/edit-copy.png + icons/tango/edit-delete.png + icons/tango/go-bottom.png + icons/tango/go-down.png + icons/tango/go-top.png + icons/tango/go-up.png + + diff --git a/apps/launcher/ui/datafilespage.ui b/files/ui/datafilespage.ui similarity index 98% rename from apps/launcher/ui/datafilespage.ui rename to files/ui/datafilespage.ui index 91b5475e67..044817fb40 100644 --- a/apps/launcher/ui/datafilespage.ui +++ b/files/ui/datafilespage.ui @@ -59,7 +59,7 @@ - + Current Profile: diff --git a/apps/launcher/ui/graphicspage.ui b/files/ui/graphicspage.ui similarity index 100% rename from apps/launcher/ui/graphicspage.ui rename to files/ui/graphicspage.ui diff --git a/apps/launcher/ui/mainwindow.ui b/files/ui/mainwindow.ui similarity index 100% rename from apps/launcher/ui/mainwindow.ui rename to files/ui/mainwindow.ui diff --git a/apps/launcher/ui/playpage.ui b/files/ui/playpage.ui similarity index 100% rename from apps/launcher/ui/playpage.ui rename to files/ui/playpage.ui From a994a23f4ec1a1fe956216651caea2ff7bd0a127 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 7 Mar 2013 07:56:29 +0100 Subject: [PATCH 37/37] file loading fixes --- apps/opencs/model/doc/document.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index e709cc5bfd..11d877d0b1 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -18,9 +18,6 @@ void CSMDoc::Document::load (const std::vector::const_i if (lastAsModified) getData().loadFile (*end2, false); - - addOptionalGmsts(); - addOptionalGlobals(); } void CSMDoc::Document::addOptionalGmsts() @@ -199,6 +196,8 @@ void CSMDoc::Document::createBase() getData().getGlobals().add (record); } + + /// \todo add GMSTs } CSMDoc::Document::Document (const std::vector& files, bool new_) @@ -213,7 +212,9 @@ CSMDoc::Document::Document (const std::vector& files, b mName = files.back().filename().string(); - if (files.size()>1 || !new_) + if (new_ && files.size()==1) + createBase(); + else if (files.size()>1) { std::vector::const_iterator end = files.end(); @@ -223,8 +224,8 @@ CSMDoc::Document::Document (const std::vector& files, b load (files.begin(), end, !new_); } - if (new_ && files.size()==1) - createBase(); + addOptionalGmsts(); + addOptionalGlobals(); connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool)));