From da74ca5ce0242cfd107a98d7934835aba178024f Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Mon, 5 Mar 2018 21:26:59 -0600 Subject: [PATCH 01/17] Add testing options to the Settings page --- apps/launcher/settingspage.cpp | 42 ++++ apps/launcher/settingspage.hpp | 1 + files/ui/settingspage.ui | 367 ++++++++++++++++++++------------- 3 files changed, 265 insertions(+), 145 deletions(-) diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp index 843b51391..906459c23 100644 --- a/apps/launcher/settingspage.cpp +++ b/apps/launcher/settingspage.cpp @@ -177,6 +177,28 @@ void Launcher::SettingsPage::on_browseButton_clicked() } } +void Launcher::SettingsPage::on_runScriptAfterStartupBrowseButton_clicked() +{ + QString scriptFile = QFileDialog::getOpenFileName( + this, + QObject::tr("Select script file"), + QDir::currentPath(), + QString(tr("Text file (*.txt)"))); + + + if (scriptFile.isEmpty()) + return; + + QFileInfo info(scriptFile); + + if (!info.exists() || !info.isReadable()) + return; + + const QString path(QDir::toNativeSeparators(info.absoluteFilePath())); + + runScriptAfterStartupField->setText(path); +} + void Launcher::SettingsPage::wizardStarted() { mMain->hide(); // Hide the launcher @@ -260,6 +282,19 @@ void Launcher::SettingsPage::saveSettings() } else { mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1252")); } + + // Testing + int skipMenu = skipMenuCheckBox->checkState() == Qt::Checked; + if (skipMenu != mGameSettings.value("skip-menu").toInt()) + mGameSettings.setValue("skip-menu", QString::number(skipMenu)); + + QString startCell = startDefaultCharacterAtField->text(); + if (startCell != mGameSettings.value("start")) { + mGameSettings.setValue("start", startCell); + } + QString scriptRun = runScriptAfterStartupField->text(); + if (scriptRun != mGameSettings.value("script-run")) + mGameSettings.setValue("script-run", scriptRun); } bool Launcher::SettingsPage::loadSettings() @@ -271,5 +306,12 @@ bool Launcher::SettingsPage::loadSettings() if (index != -1) languageComboBox->setCurrentIndex(index); + // Testing + if (mGameSettings.value("skip-menu").toInt() == 1) + skipMenuCheckBox->setCheckState(Qt::Checked); + + startDefaultCharacterAtField->setText(mGameSettings.value("start")); + runScriptAfterStartupField->setText(mGameSettings.value("script-run")); + return true; } diff --git a/apps/launcher/settingspage.hpp b/apps/launcher/settingspage.hpp index ccc2061dd..12539a0fc 100644 --- a/apps/launcher/settingspage.hpp +++ b/apps/launcher/settingspage.hpp @@ -38,6 +38,7 @@ namespace Launcher void on_wizardButton_clicked(); void on_importerButton_clicked(); void on_browseButton_clicked(); + void on_runScriptAfterStartupBrowseButton_clicked(); void wizardStarted(); void wizardFinished(int exitCode, QProcess::ExitStatus exitStatus); diff --git a/files/ui/settingspage.ui b/files/ui/settingspage.ui index f4f41f839..eed723adb 100644 --- a/files/ui/settingspage.ui +++ b/files/ui/settingspage.ui @@ -7,7 +7,7 @@ 0 0 514 - 397 + 532 @@ -15,153 +15,230 @@ - - - Morrowind Content Language + + + true - - - - - - 250 - 0 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + + 0 + 0 + 473 + 510 + + + + + + + Morrowind Content Language + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 250 + 0 + + + + + + + + + + + Morrowind Installation Wizard + + + + + + Run &Installation Wizard + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Morrowind Settings Importer + + + + + + + + File to import settings from: + + + + + + + + + + Browse... + + + + + + + + + Import add-on and plugin selection (creates a new Content List) + + + true + + + + + + + + + Run &Settings Importer + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 4 + + + false + + + + + + + + + + Testing + + + + + + Skip menu and generate default character + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Start default character at + + + + + + + default cell + + + + + + + + + Run script after startup: + + + + + + + + + + + + Browse… + + + + + + + + + + - - - - Morrowind Installation Wizard - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Run &Installation Wizard - - - - - - - - - - Morrowind Settings Importer - - - - - - - - File to import settings from: - - - - - - - - - - Browse... - - - - - - - - - Import add-on and plugin selection (creates a new Content List) - - - true - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Run &Settings Importer - - - - - - - - - 4 - - - false - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - From 082e166faefd2daa149d3af49657c98bbb67db5f Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Mon, 5 Mar 2018 21:41:29 -0600 Subject: [PATCH 02/17] Making "start default character at" field enabled or disabled by the previous checkbox --- apps/launcher/settingspage.cpp | 55 ++++++++++++++++++++-------------- apps/launcher/settingspage.hpp | 4 ++- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp index 906459c23..ec784c9d3 100644 --- a/apps/launcher/settingspage.cpp +++ b/apps/launcher/settingspage.cpp @@ -177,28 +177,6 @@ void Launcher::SettingsPage::on_browseButton_clicked() } } -void Launcher::SettingsPage::on_runScriptAfterStartupBrowseButton_clicked() -{ - QString scriptFile = QFileDialog::getOpenFileName( - this, - QObject::tr("Select script file"), - QDir::currentPath(), - QString(tr("Text file (*.txt)"))); - - - if (scriptFile.isEmpty()) - return; - - QFileInfo info(scriptFile); - - if (!info.exists() || !info.isReadable()) - return; - - const QString path(QDir::toNativeSeparators(info.absoluteFilePath())); - - runScriptAfterStartupField->setText(path); -} - void Launcher::SettingsPage::wizardStarted() { mMain->hide(); // Hide the launcher @@ -269,6 +247,33 @@ void Launcher::SettingsPage::updateOkButton(const QString &text) : mProfileDialog->setOkButtonEnabled(true); } +void Launcher::SettingsPage::on_skipMenuCheckBox_stateChanged(int state) { + startDefaultCharacterAtLabel->setEnabled(state == Qt::Checked); + startDefaultCharacterAtField->setEnabled(state == Qt::Checked); +} + +void Launcher::SettingsPage::on_runScriptAfterStartupBrowseButton_clicked() +{ + QString scriptFile = QFileDialog::getOpenFileName( + this, + QObject::tr("Select script file"), + QDir::currentPath(), + QString(tr("Text file (*.txt)"))); + + + if (scriptFile.isEmpty()) + return; + + QFileInfo info(scriptFile); + + if (!info.exists() || !info.isReadable()) + return; + + const QString path(QDir::toNativeSeparators(info.absoluteFilePath())); + + runScriptAfterStartupField->setText(path); +} + void Launcher::SettingsPage::saveSettings() { QString language(languageComboBox->currentText()); @@ -307,8 +312,12 @@ bool Launcher::SettingsPage::loadSettings() languageComboBox->setCurrentIndex(index); // Testing - if (mGameSettings.value("skip-menu").toInt() == 1) + bool skipMenu = mGameSettings.value("skip-menu").toInt() == Qt::Checked; + if (skipMenu) { skipMenuCheckBox->setCheckState(Qt::Checked); + } + startDefaultCharacterAtLabel->setEnabled(skipMenu); + startDefaultCharacterAtField->setEnabled(skipMenu); startDefaultCharacterAtField->setText(mGameSettings.value("start")); runScriptAfterStartupField->setText(mGameSettings.value("script-run")); diff --git a/apps/launcher/settingspage.hpp b/apps/launcher/settingspage.hpp index 12539a0fc..a9de974ff 100644 --- a/apps/launcher/settingspage.hpp +++ b/apps/launcher/settingspage.hpp @@ -38,7 +38,6 @@ namespace Launcher void on_wizardButton_clicked(); void on_importerButton_clicked(); void on_browseButton_clicked(); - void on_runScriptAfterStartupBrowseButton_clicked(); void wizardStarted(); void wizardFinished(int exitCode, QProcess::ExitStatus exitStatus); @@ -48,6 +47,9 @@ namespace Launcher void updateOkButton(const QString &text); + void on_skipMenuCheckBox_stateChanged(int state); + void on_runScriptAfterStartupBrowseButton_clicked(); + private: Process::ProcessInvoker *mWizardInvoker; From dcc262ed911fa4c0ba3db4e7f47e0d3cb22d80dd Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Mon, 5 Mar 2018 23:10:08 -0600 Subject: [PATCH 03/17] Fixing Skip Menu checkbox not working correctly --- apps/launcher/settingspage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp index ec784c9d3..986aee048 100644 --- a/apps/launcher/settingspage.cpp +++ b/apps/launcher/settingspage.cpp @@ -312,7 +312,7 @@ bool Launcher::SettingsPage::loadSettings() languageComboBox->setCurrentIndex(index); // Testing - bool skipMenu = mGameSettings.value("skip-menu").toInt() == Qt::Checked; + bool skipMenu = mGameSettings.value("skip-menu").toInt() == 1; if (skipMenu) { skipMenuCheckBox->setCheckState(Qt::Checked); } From 6931f6cadc14128df681c66ee269cee739aba31c Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Wed, 7 Mar 2018 18:37:43 -0600 Subject: [PATCH 04/17] Adding message indicating the purpose of the "Testing" block --- files/ui/settingspage.ui | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/files/ui/settingspage.ui b/files/ui/settingspage.ui index eed723adb..f1b833c60 100644 --- a/files/ui/settingspage.ui +++ b/files/ui/settingspage.ui @@ -23,9 +23,9 @@ 0 - 0 + -44 473 - 510 + 567 @@ -170,6 +170,23 @@ Testing + + + + These settings are intended for testing mods and may cause issues if used for normal gameplay. + + + true + + + + + + + Qt::Horizontal + + + From f07a12af733d6cabd3ce66cb49fedba474d7a8cd Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Thu, 8 Mar 2018 18:09:18 -0600 Subject: [PATCH 05/17] Changing label "and may cause issues" to "and will cause issues" --- files/ui/settingspage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/ui/settingspage.ui b/files/ui/settingspage.ui index f1b833c60..d0c77f4b7 100644 --- a/files/ui/settingspage.ui +++ b/files/ui/settingspage.ui @@ -173,7 +173,7 @@ - These settings are intended for testing mods and may cause issues if used for normal gameplay. + These settings are intended for testing mods and will cause issues if used for normal gameplay. true From d42791e26056e7dd98ab639f24b0627b2cff83a9 Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Thu, 15 Mar 2018 22:11:54 -0500 Subject: [PATCH 06/17] Moving testing options to Advanced page --- apps/launcher/advancedpage.cpp | 58 ++++- apps/launcher/advancedpage.hpp | 9 +- apps/launcher/maindialog.cpp | 2 +- apps/launcher/settingspage.cpp | 51 ----- apps/launcher/settingspage.hpp | 3 - files/ui/advancedpage.ui | 99 ++++++++- files/ui/settingspage.ui | 384 +++++++++++++-------------------- 7 files changed, 300 insertions(+), 306 deletions(-) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index 0abefcc8f..bc3308da0 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -1,10 +1,14 @@ #include "advancedpage.hpp" -#include +#include +#include -Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, Settings::Manager &engineSettings, QWidget *parent) +Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, + Config::GameSettings &gameSettings, + Settings::Manager &engineSettings, QWidget *parent) : QWidget(parent) , mCfgMgr(cfg) + , mGameSettings(gameSettings) , mEngineSettings(engineSettings) { setObjectName ("AdvancedPage"); @@ -13,8 +17,45 @@ Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, Settings: loadSettings(); } +void Launcher::AdvancedPage::on_skipMenuCheckBox_stateChanged(int state) { + startDefaultCharacterAtLabel->setEnabled(state == Qt::Checked); + startDefaultCharacterAtField->setEnabled(state == Qt::Checked); +} + +void Launcher::AdvancedPage::on_runScriptAfterStartupBrowseButton_clicked() +{ + QString scriptFile = QFileDialog::getOpenFileName( + this, + QObject::tr("Select script file"), + QDir::currentPath(), + QString(tr("Text file (*.txt)"))); + + + if (scriptFile.isEmpty()) + return; + + QFileInfo info(scriptFile); + + if (!info.exists() || !info.isReadable()) + return; + + const QString path(QDir::toNativeSeparators(info.absoluteFilePath())); + +} + bool Launcher::AdvancedPage::loadSettings() { + // Testing + bool skipMenu = mGameSettings.value("skip-menu").toInt() == 1; + if (skipMenu) { + skipMenuCheckBox->setCheckState(Qt::Checked); + } + startDefaultCharacterAtLabel->setEnabled(skipMenu); + startDefaultCharacterAtField->setEnabled(skipMenu); + + startDefaultCharacterAtField->setText(mGameSettings.value("start")); + runScriptAfterStartupField->setText(mGameSettings.value("script-run")); + // Game Settings loadSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game"); loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game"); @@ -53,6 +94,19 @@ void Launcher::AdvancedPage::saveSettings() // Ensure we only set the new settings if they changed. This is to avoid cluttering the // user settings file (which by definition should only contain settings the user has touched) + // Testing + int skipMenu = skipMenuCheckBox->checkState() == Qt::Checked; + if (skipMenu != mGameSettings.value("skip-menu").toInt()) + mGameSettings.setValue("skip-menu", QString::number(skipMenu)); + + QString startCell = startDefaultCharacterAtField->text(); + if (startCell != mGameSettings.value("start")) { + mGameSettings.setValue("start", startCell); + } + QString scriptRun = runScriptAfterStartupField->text(); + if (scriptRun != mGameSettings.value("script-run")) + mGameSettings.setValue("script-run", scriptRun); + // Game Settings saveSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game"); saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game"); diff --git a/apps/launcher/advancedpage.hpp b/apps/launcher/advancedpage.hpp index a8361c98e..0a9957b9c 100644 --- a/apps/launcher/advancedpage.hpp +++ b/apps/launcher/advancedpage.hpp @@ -8,6 +8,7 @@ #include namespace Files { struct ConfigurationManager; } +namespace Config { class GameSettings; } namespace Launcher { @@ -16,13 +17,19 @@ namespace Launcher Q_OBJECT public: - AdvancedPage(Files::ConfigurationManager &cfg, Settings::Manager &engineSettings, QWidget *parent = 0); + AdvancedPage(Files::ConfigurationManager &cfg, Config::GameSettings &gameSettings, + Settings::Manager &engineSettings, QWidget *parent = 0); bool loadSettings(); void saveSettings(); + private slots: + void on_skipMenuCheckBox_stateChanged(int state); + void on_runScriptAfterStartupBrowseButton_clicked(); + private: Files::ConfigurationManager &mCfgMgr; + Config::GameSettings &mGameSettings; Settings::Manager &mEngineSettings; void loadSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 1a210ccc5..356863d03 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -119,7 +119,7 @@ void Launcher::MainDialog::createPages() mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this); mGraphicsPage = new GraphicsPage(mCfgMgr, mEngineSettings, this); mSettingsPage = new SettingsPage(mCfgMgr, mGameSettings, mLauncherSettings, this); - mAdvancedPage = new AdvancedPage(mCfgMgr, mEngineSettings, this); + mAdvancedPage = new AdvancedPage(mCfgMgr, mGameSettings, mEngineSettings, this); // Set the combobox of the play page to imitate the combobox on the datafilespage mPlayPage->setProfilesModel(mDataFilesPage->profilesModel()); diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp index 986aee048..843b51391 100644 --- a/apps/launcher/settingspage.cpp +++ b/apps/launcher/settingspage.cpp @@ -247,33 +247,6 @@ void Launcher::SettingsPage::updateOkButton(const QString &text) : mProfileDialog->setOkButtonEnabled(true); } -void Launcher::SettingsPage::on_skipMenuCheckBox_stateChanged(int state) { - startDefaultCharacterAtLabel->setEnabled(state == Qt::Checked); - startDefaultCharacterAtField->setEnabled(state == Qt::Checked); -} - -void Launcher::SettingsPage::on_runScriptAfterStartupBrowseButton_clicked() -{ - QString scriptFile = QFileDialog::getOpenFileName( - this, - QObject::tr("Select script file"), - QDir::currentPath(), - QString(tr("Text file (*.txt)"))); - - - if (scriptFile.isEmpty()) - return; - - QFileInfo info(scriptFile); - - if (!info.exists() || !info.isReadable()) - return; - - const QString path(QDir::toNativeSeparators(info.absoluteFilePath())); - - runScriptAfterStartupField->setText(path); -} - void Launcher::SettingsPage::saveSettings() { QString language(languageComboBox->currentText()); @@ -287,19 +260,6 @@ void Launcher::SettingsPage::saveSettings() } else { mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1252")); } - - // Testing - int skipMenu = skipMenuCheckBox->checkState() == Qt::Checked; - if (skipMenu != mGameSettings.value("skip-menu").toInt()) - mGameSettings.setValue("skip-menu", QString::number(skipMenu)); - - QString startCell = startDefaultCharacterAtField->text(); - if (startCell != mGameSettings.value("start")) { - mGameSettings.setValue("start", startCell); - } - QString scriptRun = runScriptAfterStartupField->text(); - if (scriptRun != mGameSettings.value("script-run")) - mGameSettings.setValue("script-run", scriptRun); } bool Launcher::SettingsPage::loadSettings() @@ -311,16 +271,5 @@ bool Launcher::SettingsPage::loadSettings() if (index != -1) languageComboBox->setCurrentIndex(index); - // Testing - bool skipMenu = mGameSettings.value("skip-menu").toInt() == 1; - if (skipMenu) { - skipMenuCheckBox->setCheckState(Qt::Checked); - } - startDefaultCharacterAtLabel->setEnabled(skipMenu); - startDefaultCharacterAtField->setEnabled(skipMenu); - - startDefaultCharacterAtField->setText(mGameSettings.value("start")); - runScriptAfterStartupField->setText(mGameSettings.value("script-run")); - return true; } diff --git a/apps/launcher/settingspage.hpp b/apps/launcher/settingspage.hpp index a9de974ff..ccc2061dd 100644 --- a/apps/launcher/settingspage.hpp +++ b/apps/launcher/settingspage.hpp @@ -47,9 +47,6 @@ namespace Launcher void updateOkButton(const QString &text); - void on_skipMenuCheckBox_stateChanged(int state); - void on_runScriptAfterStartupBrowseButton_clicked(); - private: Process::ProcessInvoker *mWizardInvoker; diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index 6832b86df..f2224ff13 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -11,13 +11,6 @@ - - - - <html><head/><body><p>This temporary page contains new settings that will be available in-game in a post-1.0 release of OpenMW.</p></body></html> - - - @@ -27,9 +20,9 @@ 0 - -187 + 0 630 - 510 + 746 @@ -266,6 +259,94 @@ + + + + Testing + + + + + + These settings are intended for testing mods and will cause issues if used for normal gameplay. + + + true + + + + + + + Qt::Horizontal + + + + + + + Skip menu and generate default character + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Start default character at + + + + + + + default cell + + + + + + + + + Run script after startup: + + + + + + + + + + + + Browse… + + + + + + + + diff --git a/files/ui/settingspage.ui b/files/ui/settingspage.ui index d0c77f4b7..f4f41f839 100644 --- a/files/ui/settingspage.ui +++ b/files/ui/settingspage.ui @@ -7,7 +7,7 @@ 0 0 514 - 532 + 397 @@ -15,247 +15,153 @@ - - - true + + + Morrowind Content Language - - - - 0 - -44 - 473 - 567 - - - - - - - Morrowind Content Language - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 250 - 0 - - - - - - - - - - - Morrowind Installation Wizard - - - - - - Run &Installation Wizard - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Morrowind Settings Importer - - - - - - - - File to import settings from: - - - - - - - - - - Browse... - - - - - - - - - Import add-on and plugin selection (creates a new Content List) - - - true - - - - - - - - - Run &Settings Importer - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 4 - - - false - - - - - - - - - - Testing - - - - - - These settings are intended for testing mods and will cause issues if used for normal gameplay. - - - true - - - - - - - Qt::Horizontal - - - - - - - Skip menu and generate default character - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - Start default character at - - - - - - - default cell - - - - - - - - - Run script after startup: - - - - - - - - - - - - Browse… - - - - - - - - - - + + + + + + 250 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Morrowind Installation Wizard + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Run &Installation Wizard + + + + + + + + + + Morrowind Settings Importer + + + + + + + + File to import settings from: + + + + + + + + + + Browse... + + + + + + + + + Import add-on and plugin selection (creates a new Content List) + + + true + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Run &Settings Importer + + + + + + + + + 4 + + + false + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + From fb27f34a32ed87ea757dd591af6526ede2604aa7 Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Sat, 7 Apr 2018 21:27:36 -0500 Subject: [PATCH 07/17] Add autocomplete to the "Start default character at" field --- apps/launcher/CMakeLists.txt | 3 ++ apps/launcher/advancedpage.cpp | 18 ++++++++++ apps/launcher/advancedpage.hpp | 6 ++++ apps/launcher/datafilespage.cpp | 11 ++++++ apps/launcher/datafilespage.hpp | 6 ++++ apps/launcher/maindialog.cpp | 3 ++ apps/launcher/utils/cellnameloader.cpp | 48 ++++++++++++++++++++++++++ apps/launcher/utils/cellnameloader.hpp | 41 ++++++++++++++++++++++ 8 files changed, 136 insertions(+) create mode 100644 apps/launcher/utils/cellnameloader.cpp create mode 100644 apps/launcher/utils/cellnameloader.hpp diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index aec8c2533..54d7c3ece 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -8,6 +8,7 @@ set(LAUNCHER settingspage.cpp advancedpage.cpp + utils/cellnameloader.cpp utils/profilescombobox.cpp utils/textinputdialog.cpp utils/lineedit.cpp @@ -24,6 +25,7 @@ set(LAUNCHER_HEADER settingspage.hpp advancedpage.hpp + utils/cellnameloader.hpp utils/profilescombobox.hpp utils/textinputdialog.hpp utils/lineedit.hpp @@ -39,6 +41,7 @@ set(LAUNCHER_HEADER_MOC settingspage.hpp advancedpage.hpp + utils/cellnameloader.hpp utils/textinputdialog.hpp utils/profilescombobox.hpp utils/lineedit.hpp diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index bc3308da0..bd077c12f 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -1,7 +1,12 @@ #include "advancedpage.hpp" #include +#include +#include #include +#include +#include +#include Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, Config::GameSettings &gameSettings, @@ -17,6 +22,19 @@ Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, loadSettings(); } +void Launcher::AdvancedPage::loadCellsForAutocomplete(QStringList filePaths) { + CellNameLoader cellNameLoader; + QStringList cellNamesList = QStringList::fromSet(cellNameLoader.getCellNames(filePaths)); + std::sort(cellNamesList.begin(), cellNamesList.end()); + + // Set up an auto-completer for the "Start default character at" field + auto *completer = new QCompleter(cellNamesList); + completer->setCompletionMode(QCompleter::PopupCompletion); + completer->setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive); + startDefaultCharacterAtField->setCompleter(completer); + +} + void Launcher::AdvancedPage::on_skipMenuCheckBox_stateChanged(int state) { startDefaultCharacterAtLabel->setEnabled(state == Qt::Checked); startDefaultCharacterAtField->setEnabled(state == Qt::Checked); diff --git a/apps/launcher/advancedpage.hpp b/apps/launcher/advancedpage.hpp index 0a9957b9c..654214f29 100644 --- a/apps/launcher/advancedpage.hpp +++ b/apps/launcher/advancedpage.hpp @@ -23,6 +23,12 @@ namespace Launcher bool loadSettings(); void saveSettings(); + /** + * Load the cells associated with the given content files for use in autocomplete + * @param filePaths the file paths of the content files to be examined + */ + void loadCellsForAutocomplete(QStringList filePaths); + private slots: void on_skipMenuCheckBox_stateChanged(int state); void on_runScriptAfterStartupBrowseButton_clicked(); diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 0b0f8c75e..484c8c56b 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -142,6 +142,17 @@ void Launcher::DataFilesPage::saveSettings(const QString &profile) mGameSettings.setContentList(fileNames); } +QStringList Launcher::DataFilesPage::selectedFilePaths() +{ + //retrieve the files selected for the profile + ContentSelectorModel::ContentFileList items = mSelector->selectedFiles(); + QStringList filePaths; + foreach(const ContentSelectorModel::EsmFile *item, items) { + filePaths.append(item->filePath()); + } + return filePaths; +} + void Launcher::DataFilesPage::removeProfile(const QString &profile) { mLauncherSettings.removeContentList(profile); diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index d25d20fc9..9955737d5 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -41,6 +41,12 @@ namespace Launcher void saveSettings(const QString &profile = ""); bool loadSettings(); + /** + * Returns the file paths of all selected content files + * @return the file paths of all selected content files + */ + QStringList selectedFilePaths(); + signals: void signalProfileChanged (int index); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 356863d03..9967cbddc 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -125,6 +125,9 @@ void Launcher::MainDialog::createPages() mPlayPage->setProfilesModel(mDataFilesPage->profilesModel()); mPlayPage->setProfilesIndex(mDataFilesPage->profilesIndex()); + // Load cells for the "Start default character at" field + mAdvancedPage->loadCellsForAutocomplete(mDataFilesPage->selectedFilePaths()); + // Add the pages to the stacked widget pagesWidget->addWidget(mPlayPage); pagesWidget->addWidget(mDataFilesPage); diff --git a/apps/launcher/utils/cellnameloader.cpp b/apps/launcher/utils/cellnameloader.cpp new file mode 100644 index 000000000..6d1ed2f49 --- /dev/null +++ b/apps/launcher/utils/cellnameloader.cpp @@ -0,0 +1,48 @@ +#include "cellnameloader.hpp" + +#include +#include + +QSet CellNameLoader::getCellNames(QStringList &contentPaths) +{ + QSet cellNames; + ESM::ESMReader esmReader; + + // Loop through all content files + for (auto &contentPath : contentPaths) { + esmReader.open(contentPath.toStdString()); + + // Loop through all records + while(esmReader.hasMoreRecs()) + { + ESM::NAME recordName = esmReader.getRecName(); + esmReader.getRecHeader(); + + if (isCellRecord(recordName)) { + QString cellName = getCellName(esmReader); + if (!cellName.isEmpty()) { + cellNames.insert(cellName); + } + } + + // Stop loading content for this record and continue to the next + esmReader.skipRecord(); + } + } + + return cellNames; +} + +bool CellNameLoader::isCellRecord(ESM::NAME &recordName) +{ + return recordName.intval == ESM::REC_CELL; +} + +QString CellNameLoader::getCellName(ESM::ESMReader &esmReader) +{ + ESM::Cell cell; + bool isDeleted = false; + cell.loadNameAndData(esmReader, isDeleted); + + return QString::fromStdString(cell.mName); +} \ No newline at end of file diff --git a/apps/launcher/utils/cellnameloader.hpp b/apps/launcher/utils/cellnameloader.hpp new file mode 100644 index 000000000..c58d09226 --- /dev/null +++ b/apps/launcher/utils/cellnameloader.hpp @@ -0,0 +1,41 @@ +#ifndef OPENMW_CELLNAMELOADER_H +#define OPENMW_CELLNAMELOADER_H + +#include +#include +#include + +#include + +namespace ESM {class ESMReader; struct Cell;} +namespace ContentSelectorView {class ContentSelector;} + +class CellNameLoader { + +public: + + /** + * Returns the names of all cells contained within the given content files + * @param contentPaths the file paths of each content file to be examined + * @return the names of all cells + */ + QSet getCellNames(QStringList &contentPaths); + +private: + /** + * Returns whether or not the given record is of type "Cell" + * @param name The name associated with the record + * @return whether or not the given record is of type "Cell" + */ + bool isCellRecord(ESM::NAME &name); + + /** + * Returns the name of the cell + * @param esmReader the reader currently pointed to a loaded cell + * @return the name of the cell + */ + QString getCellName(ESM::ESMReader &esmReader); +}; + + +#endif //OPENMW_CELLNAMELOADER_H From d58cce9c727dd6ddccea3bcee44338457615338f Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Tue, 22 May 2018 20:50:31 -0500 Subject: [PATCH 08/17] Adding WIP code to dynamically change the autocomplete fields --- apps/launcher/advancedpage.cpp | 5 +++++ apps/launcher/advancedpage.hpp | 3 +++ apps/launcher/datafilespage.cpp | 7 +++++++ apps/launcher/datafilespage.hpp | 3 +++ apps/launcher/maindialog.cpp | 1 + components/contentselector/view/contentselector.cpp | 13 +++++++++++++ components/contentselector/view/contentselector.hpp | 2 ++ 7 files changed, 34 insertions(+) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index bd077c12f..383799e2a 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -162,4 +162,9 @@ void Launcher::AdvancedPage::saveSettingBool(QCheckBox *checkbox, const std::str bool cValue = checkbox->checkState(); if (cValue != mEngineSettings.getBool(setting, group)) mEngineSettings.setBool(setting, group, cValue); +} + +void Launcher::AdvancedPage::slotSelectedDataFilesChanged(QStringList selectedFiles) +{ + loadCellsForAutocomplete(selectedFiles); } \ No newline at end of file diff --git a/apps/launcher/advancedpage.hpp b/apps/launcher/advancedpage.hpp index 654214f29..c40ae2da1 100644 --- a/apps/launcher/advancedpage.hpp +++ b/apps/launcher/advancedpage.hpp @@ -29,6 +29,9 @@ namespace Launcher */ void loadCellsForAutocomplete(QStringList filePaths); + public slots: + void slotSelectedDataFilesChanged(QStringList selectedFiles); + private slots: void on_skipMenuCheckBox_stateChanged(int state); void on_runScriptAfterStartupBrowseButton_clicked(); diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 484c8c56b..8d4d2422f 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -37,6 +37,8 @@ Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config: connect(mProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString))); + connect(mSelector, SIGNAL(signalSelectedFilesChanged(QStringList)), + this, SLOT(slotSelectedFilesChanged(QStringList))); buildView(); loadSettings(); @@ -319,3 +321,8 @@ bool Launcher::DataFilesPage::showDeleteMessageBox (const QString &text) return (msgBox.clickedButton() == deleteButton); } + +void Launcher::DataFilesPage::slotSelectedFilesChanged(QStringList selectedFilesChanged) +{ + emit signalSelectedFilesChanged(selectedFilesChanged); +} \ No newline at end of file diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index 9955737d5..fb9f9e04f 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -7,6 +7,7 @@ #include #include +#include class QSortFilterProxyModel; class QAbstractItemModel; @@ -49,6 +50,7 @@ namespace Launcher signals: void signalProfileChanged (int index); + void signalSelectedFilesChanged(QStringList selectedFiles); public slots: void slotProfileChanged (int index); @@ -58,6 +60,7 @@ namespace Launcher void slotProfileChangedByUser(const QString &previous, const QString ¤t); void slotProfileRenamed(const QString &previous, const QString ¤t); void slotProfileDeleted(const QString &item); + void slotSelectedFilesChanged (QStringList selectedFiles); void updateOkButton(const QString &text); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 9967cbddc..f3afb2732 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -142,6 +142,7 @@ void Launcher::MainDialog::createPages() connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(int))); connect(mDataFilesPage, SIGNAL(signalProfileChanged(int)), mPlayPage, SLOT(setProfilesIndex(int))); + connect(mDataFilesPage, SIGNAL(signalSelectedFilesChanged(QStringList)), mAdvancedPage, SLOT(slotSelectedDataFilesChanged(QStringList))); } diff --git a/components/contentselector/view/contentselector.cpp b/components/contentselector/view/contentselector.cpp index f4da7e6ad..4798d160c 100644 --- a/components/contentselector/view/contentselector.cpp +++ b/components/contentselector/view/contentselector.cpp @@ -216,6 +216,8 @@ void ContentSelectorView::ContentSelector::slotShowContextMenu(const QPoint& pos { QPoint globalPos = ui.addonView->viewport()->mapToGlobal(pos); mContextMenu->exec(globalPos); + // TODO This is a temporary workaround to demonstrate that the selected files signal can be sent + emitSelectedFilesChanged(); } void ContentSelectorView::ContentSelector::setCheckStateForMultiSelectedItems(bool checked) @@ -240,3 +242,14 @@ void ContentSelectorView::ContentSelector::slotCheckMultiSelectedItems() { setCheckStateForMultiSelectedItems(true); } + +void ContentSelectorView::ContentSelector::emitSelectedFilesChanged() +{ + //retrieve the files selected for the profile + ContentSelectorModel::ContentFileList items = selectedFiles(); + QStringList filePaths; + foreach(const ContentSelectorModel::EsmFile *item, items) { + filePaths.append(item->filePath()); + } + emit signalSelectedFilesChanged(filePaths); +} \ No newline at end of file diff --git a/components/contentselector/view/contentselector.hpp b/components/contentselector/view/contentselector.hpp index 9f775d597..5015306ab 100644 --- a/components/contentselector/view/contentselector.hpp +++ b/components/contentselector/view/contentselector.hpp @@ -56,11 +56,13 @@ namespace ContentSelectorView void buildContextMenu(); void setGameFileSelected(int index, bool selected); void setCheckStateForMultiSelectedItems(bool checked); + void emitSelectedFilesChanged(); signals: void signalCurrentGamefileIndexChanged (int); void signalAddonDataChanged (const QModelIndex& topleft, const QModelIndex& bottomright); + void signalSelectedFilesChanged(QStringList selectedFiles); private slots: From c2fff61ccdc9c8397e7cae28f8c48bea5f6ab588 Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Sat, 26 May 2018 20:35:28 -0500 Subject: [PATCH 09/17] Changing so that data changes happen only after the addon is checked --- apps/launcher/datafilespage.cpp | 15 +++++++++++---- apps/launcher/datafilespage.hpp | 4 ++-- .../contentselector/view/contentselector.cpp | 13 ------------- .../contentselector/view/contentselector.hpp | 2 -- 4 files changed, 13 insertions(+), 21 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 8d4d2422f..25a09ab1b 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -37,11 +37,14 @@ Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config: connect(mProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(updateOkButton(QString))); - connect(mSelector, SIGNAL(signalSelectedFilesChanged(QStringList)), - this, SLOT(slotSelectedFilesChanged(QStringList))); buildView(); loadSettings(); + + // Connect signal and slot after the settings have been loaded. We only care about the user changing + // the addons and don't want to get signals of the system doing it during startup. + connect(mSelector, SIGNAL(signalAddonDataChanged(QModelIndex,QModelIndex)), + this, SLOT(slotAddonDataChanged())); } void Launcher::DataFilesPage::buildView() @@ -322,7 +325,11 @@ bool Launcher::DataFilesPage::showDeleteMessageBox (const QString &text) return (msgBox.clickedButton() == deleteButton); } -void Launcher::DataFilesPage::slotSelectedFilesChanged(QStringList selectedFilesChanged) +void Launcher::DataFilesPage::slotAddonDataChanged() { - emit signalSelectedFilesChanged(selectedFilesChanged); + QStringList selectedFiles = selectedFilePaths(); + if (previousSelectedFiles != selectedFiles) { + previousSelectedFiles = selectedFiles; + emit signalSelectedFilesChanged(selectedFiles); + } } \ No newline at end of file diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index fb9f9e04f..8893412be 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -60,7 +60,7 @@ namespace Launcher void slotProfileChangedByUser(const QString &previous, const QString ¤t); void slotProfileRenamed(const QString &previous, const QString ¤t); void slotProfileDeleted(const QString &item); - void slotSelectedFilesChanged (QStringList selectedFiles); + void slotAddonDataChanged (); void updateOkButton(const QString &text); @@ -81,7 +81,7 @@ namespace Launcher Config::LauncherSettings &mLauncherSettings; QString mPreviousProfile; - + QStringList previousSelectedFiles; QString mDataLocal; void setPluginsCheckstates(Qt::CheckState state); diff --git a/components/contentselector/view/contentselector.cpp b/components/contentselector/view/contentselector.cpp index 4798d160c..5e16064f4 100644 --- a/components/contentselector/view/contentselector.cpp +++ b/components/contentselector/view/contentselector.cpp @@ -216,8 +216,6 @@ void ContentSelectorView::ContentSelector::slotShowContextMenu(const QPoint& pos { QPoint globalPos = ui.addonView->viewport()->mapToGlobal(pos); mContextMenu->exec(globalPos); - // TODO This is a temporary workaround to demonstrate that the selected files signal can be sent - emitSelectedFilesChanged(); } void ContentSelectorView::ContentSelector::setCheckStateForMultiSelectedItems(bool checked) @@ -241,15 +239,4 @@ void ContentSelectorView::ContentSelector::slotUncheckMultiSelectedItems() void ContentSelectorView::ContentSelector::slotCheckMultiSelectedItems() { setCheckStateForMultiSelectedItems(true); -} - -void ContentSelectorView::ContentSelector::emitSelectedFilesChanged() -{ - //retrieve the files selected for the profile - ContentSelectorModel::ContentFileList items = selectedFiles(); - QStringList filePaths; - foreach(const ContentSelectorModel::EsmFile *item, items) { - filePaths.append(item->filePath()); - } - emit signalSelectedFilesChanged(filePaths); } \ No newline at end of file diff --git a/components/contentselector/view/contentselector.hpp b/components/contentselector/view/contentselector.hpp index 5015306ab..323f926ed 100644 --- a/components/contentselector/view/contentselector.hpp +++ b/components/contentselector/view/contentselector.hpp @@ -15,7 +15,6 @@ namespace ContentSelectorView Q_OBJECT QMenu *mContextMenu; - QStringList mFilePaths; protected: @@ -56,7 +55,6 @@ namespace ContentSelectorView void buildContextMenu(); void setGameFileSelected(int index, bool selected); void setCheckStateForMultiSelectedItems(bool checked); - void emitSelectedFilesChanged(); signals: void signalCurrentGamefileIndexChanged (int); From 78234e9468c2467a90e6a0bcf9101cebee76bb32 Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Sun, 27 May 2018 16:47:09 -0500 Subject: [PATCH 10/17] Moving autocomplete code to thread --- apps/launcher/advancedpage.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index 383799e2a..bc0378314 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -166,5 +167,8 @@ void Launcher::AdvancedPage::saveSettingBool(QCheckBox *checkbox, const std::str void Launcher::AdvancedPage::slotSelectedDataFilesChanged(QStringList selectedFiles) { - loadCellsForAutocomplete(selectedFiles); + // Loading cells for core Morrowind + Expansions takes about 0.2 seconds, which is enough to cause a + // barely perceptible UI lag. Splitting into its own thread to alleviate that. + std::thread loadCellsThread(&AdvancedPage::loadCellsForAutocomplete, this, selectedFiles); + loadCellsThread.join(); } \ No newline at end of file From 26dfef797040e6e944495ab017c0c8c4e6770748 Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Sun, 27 May 2018 17:15:36 -0500 Subject: [PATCH 11/17] Changing where we are loading cells to prevent Qt access issue --- apps/launcher/advancedpage.cpp | 17 ++++------------- apps/launcher/advancedpage.hpp | 2 +- apps/launcher/datafilespage.cpp | 15 ++++++++++++++- apps/launcher/datafilespage.hpp | 1 + apps/launcher/maindialog.cpp | 2 +- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index bc0378314..3fe7c1f89 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -2,10 +2,8 @@ #include #include -#include #include #include -#include #include #include @@ -23,13 +21,9 @@ Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, loadSettings(); } -void Launcher::AdvancedPage::loadCellsForAutocomplete(QStringList filePaths) { - CellNameLoader cellNameLoader; - QStringList cellNamesList = QStringList::fromSet(cellNameLoader.getCellNames(filePaths)); - std::sort(cellNamesList.begin(), cellNamesList.end()); - +void Launcher::AdvancedPage::loadCellsForAutocomplete(QStringList cellNames) { // Set up an auto-completer for the "Start default character at" field - auto *completer = new QCompleter(cellNamesList); + auto *completer = new QCompleter(cellNames); completer->setCompletionMode(QCompleter::PopupCompletion); completer->setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive); startDefaultCharacterAtField->setCompleter(completer); @@ -165,10 +159,7 @@ void Launcher::AdvancedPage::saveSettingBool(QCheckBox *checkbox, const std::str mEngineSettings.setBool(setting, group, cValue); } -void Launcher::AdvancedPage::slotSelectedDataFilesChanged(QStringList selectedFiles) +void Launcher::AdvancedPage::slotLoadedCellsChanged(QStringList cellNames) { - // Loading cells for core Morrowind + Expansions takes about 0.2 seconds, which is enough to cause a - // barely perceptible UI lag. Splitting into its own thread to alleviate that. - std::thread loadCellsThread(&AdvancedPage::loadCellsForAutocomplete, this, selectedFiles); - loadCellsThread.join(); + loadCellsForAutocomplete(cellNames); } \ No newline at end of file diff --git a/apps/launcher/advancedpage.hpp b/apps/launcher/advancedpage.hpp index c40ae2da1..82b9c3b65 100644 --- a/apps/launcher/advancedpage.hpp +++ b/apps/launcher/advancedpage.hpp @@ -30,7 +30,7 @@ namespace Launcher void loadCellsForAutocomplete(QStringList filePaths); public slots: - void slotSelectedDataFilesChanged(QStringList selectedFiles); + void slotLoadedCellsChanged(QStringList cellNames); private slots: void on_skipMenuCheckBox_stateChanged(int state); diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 25a09ab1b..1f46c7156 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -7,7 +7,9 @@ #include #include #include +#include +#include #include #include @@ -330,6 +332,17 @@ void Launcher::DataFilesPage::slotAddonDataChanged() QStringList selectedFiles = selectedFilePaths(); if (previousSelectedFiles != selectedFiles) { previousSelectedFiles = selectedFiles; - emit signalSelectedFilesChanged(selectedFiles); + // Loading cells for core Morrowind + Expansions takes about 0.2 seconds, which is enough to cause a + // barely perceptible UI lag. Splitting into its own thread to alleviate that. + std::thread loadCellsThread(&DataFilesPage::reloadCells, this, selectedFiles); + loadCellsThread.join(); } +} + +void Launcher::DataFilesPage::reloadCells(QStringList selectedFiles) +{ + CellNameLoader cellNameLoader; + QStringList cellNamesList = QStringList::fromSet(cellNameLoader.getCellNames(selectedFiles)); + std::sort(cellNamesList.begin(), cellNamesList.end()); + emit signalSelectedFilesChanged(cellNamesList); } \ No newline at end of file diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index 8893412be..d871eeee0 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -96,6 +96,7 @@ namespace Launcher void addProfile (const QString &profile, bool setAsCurrent); void checkForDefaultProfile(); void populateFileViews(const QString& contentModelName); + void reloadCells(QStringList selectedFiles); class PathIterator { diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index f3afb2732..79f3e5c67 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -142,7 +142,7 @@ void Launcher::MainDialog::createPages() connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(int))); connect(mDataFilesPage, SIGNAL(signalProfileChanged(int)), mPlayPage, SLOT(setProfilesIndex(int))); - connect(mDataFilesPage, SIGNAL(signalSelectedFilesChanged(QStringList)), mAdvancedPage, SLOT(slotSelectedDataFilesChanged(QStringList))); + connect(mDataFilesPage, SIGNAL(signalSelectedFilesChanged(QStringList)), mAdvancedPage, SLOT(slotLoadedCellsChanged(QStringList))); } From e26c67582920709344036f54bb245086195408f7 Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Sat, 2 Jun 2018 17:29:35 -0500 Subject: [PATCH 12/17] Changing join to detach so that the thread will not block the UI --- apps/launcher/datafilespage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 1f46c7156..bcb2966d5 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -335,7 +335,7 @@ void Launcher::DataFilesPage::slotAddonDataChanged() // Loading cells for core Morrowind + Expansions takes about 0.2 seconds, which is enough to cause a // barely perceptible UI lag. Splitting into its own thread to alleviate that. std::thread loadCellsThread(&DataFilesPage::reloadCells, this, selectedFiles); - loadCellsThread.join(); + loadCellsThread.detach(); } } From 103a7ac62882d196b9fd12c9afa374f17a5e856f Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Sun, 3 Jun 2018 16:32:12 -0500 Subject: [PATCH 13/17] Using a mutex lock to prevent race conditions --- apps/launcher/datafilespage.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index bcb2966d5..76ca893c4 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -339,8 +339,16 @@ void Launcher::DataFilesPage::slotAddonDataChanged() } } +// Mutex lock to run reloadCells synchronously. +std::mutex _reloadCellsMutex; + void Launcher::DataFilesPage::reloadCells(QStringList selectedFiles) { + // Use a mutex lock so that we can prevent two threads from executing the rest of this code at the same time + // Based on https://stackoverflow.com/a/5429695/531762 + std::unique_lock lock(_reloadCellsMutex); + + // The following code will run only if there is not another thread currently running it CellNameLoader cellNameLoader; QStringList cellNamesList = QStringList::fromSet(cellNameLoader.getCellNames(selectedFiles)); std::sort(cellNamesList.begin(), cellNamesList.end()); From e282ece3d14bda73938cce38412a932d74826246 Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Sun, 3 Jun 2018 16:58:18 -0500 Subject: [PATCH 14/17] Fixing bug with autocomplete not loading correctly during startup --- apps/launcher/advancedpage.hpp | 11 +++++------ apps/launcher/datafilespage.cpp | 3 +++ apps/launcher/maindialog.cpp | 3 --- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/launcher/advancedpage.hpp b/apps/launcher/advancedpage.hpp index 82b9c3b65..59de3d319 100644 --- a/apps/launcher/advancedpage.hpp +++ b/apps/launcher/advancedpage.hpp @@ -23,12 +23,6 @@ namespace Launcher bool loadSettings(); void saveSettings(); - /** - * Load the cells associated with the given content files for use in autocomplete - * @param filePaths the file paths of the content files to be examined - */ - void loadCellsForAutocomplete(QStringList filePaths); - public slots: void slotLoadedCellsChanged(QStringList cellNames); @@ -41,6 +35,11 @@ namespace Launcher Config::GameSettings &mGameSettings; Settings::Manager &mEngineSettings; + /** + * Load the cells associated with the given content files for use in autocomplete + * @param filePaths the file paths of the content files to be examined + */ + void loadCellsForAutocomplete(QStringList filePaths); void loadSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group); void saveSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group); }; diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 76ca893c4..b3c8fb14a 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "utils/textinputdialog.hpp" #include "utils/profilescombobox.hpp" @@ -47,6 +48,8 @@ Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config: // the addons and don't want to get signals of the system doing it during startup. connect(mSelector, SIGNAL(signalAddonDataChanged(QModelIndex,QModelIndex)), this, SLOT(slotAddonDataChanged())); + // Call manually to indicate all changes to addon data during startup. + slotAddonDataChanged(); } void Launcher::DataFilesPage::buildView() diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 79f3e5c67..a70f6ff7f 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -125,9 +125,6 @@ void Launcher::MainDialog::createPages() mPlayPage->setProfilesModel(mDataFilesPage->profilesModel()); mPlayPage->setProfilesIndex(mDataFilesPage->profilesIndex()); - // Load cells for the "Start default character at" field - mAdvancedPage->loadCellsForAutocomplete(mDataFilesPage->selectedFilePaths()); - // Add the pages to the stacked widget pagesWidget->addWidget(mPlayPage); pagesWidget->addWidget(mDataFilesPage); From d46590934af75c265b6fd1894acbdc306b470c7d Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Sun, 3 Jun 2018 16:59:27 -0500 Subject: [PATCH 15/17] Importing mutex --- apps/launcher/datafilespage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index b3c8fb14a..6c23b3285 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include From 62c4eb8d6abbb4b3ebf5af951801dc0ce17bbc1f Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Fri, 8 Jun 2018 19:16:24 -0500 Subject: [PATCH 16/17] Explicitly flagging loaded cells changed as queued --- apps/launcher/maindialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index a70f6ff7f..90197b157 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -139,7 +139,8 @@ void Launcher::MainDialog::createPages() connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(int))); connect(mDataFilesPage, SIGNAL(signalProfileChanged(int)), mPlayPage, SLOT(setProfilesIndex(int))); - connect(mDataFilesPage, SIGNAL(signalSelectedFilesChanged(QStringList)), mAdvancedPage, SLOT(slotLoadedCellsChanged(QStringList))); + // Using Qt::QueuedConnection because signal is emitted in a subthread and slot is in the main thread + connect(mDataFilesPage, SIGNAL(signalSelectedFilesChanged(QStringList)), mAdvancedPage, SLOT(slotLoadedCellsChanged(QStringList)), Qt::QueuedConnection); } From dfa99685658318a27fa79e59f7060aa8fbebb68c Mon Sep 17 00:00:00 2001 From: Thunderforge Date: Fri, 8 Jun 2018 19:18:23 -0500 Subject: [PATCH 17/17] Renaming Launcher::DataFilesPage::signalSelectedFilesChanged to signalLoadedCellsChanged --- apps/launcher/datafilespage.cpp | 2 +- apps/launcher/datafilespage.hpp | 2 +- apps/launcher/maindialog.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 6c23b3285..7b703a924 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -356,5 +356,5 @@ void Launcher::DataFilesPage::reloadCells(QStringList selectedFiles) CellNameLoader cellNameLoader; QStringList cellNamesList = QStringList::fromSet(cellNameLoader.getCellNames(selectedFiles)); std::sort(cellNamesList.begin(), cellNamesList.end()); - emit signalSelectedFilesChanged(cellNamesList); + emit signalLoadedCellsChanged(cellNamesList); } \ No newline at end of file diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index d871eeee0..2cbace38e 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -50,7 +50,7 @@ namespace Launcher signals: void signalProfileChanged (int index); - void signalSelectedFilesChanged(QStringList selectedFiles); + void signalLoadedCellsChanged(QStringList selectedFiles); public slots: void slotProfileChanged (int index); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 90197b157..27fa2d903 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -140,7 +140,7 @@ void Launcher::MainDialog::createPages() connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(int))); connect(mDataFilesPage, SIGNAL(signalProfileChanged(int)), mPlayPage, SLOT(setProfilesIndex(int))); // Using Qt::QueuedConnection because signal is emitted in a subthread and slot is in the main thread - connect(mDataFilesPage, SIGNAL(signalSelectedFilesChanged(QStringList)), mAdvancedPage, SLOT(slotLoadedCellsChanged(QStringList)), Qt::QueuedConnection); + connect(mDataFilesPage, SIGNAL(signalLoadedCellsChanged(QStringList)), mAdvancedPage, SLOT(slotLoadedCellsChanged(QStringList)), Qt::QueuedConnection); }