From 5fb26b2dcbfae9d6a1aaac9d61f017bacf572f09 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 7 Jun 2019 17:15:44 -0400 Subject: made Executable members private, added member function to get and set them --- src/executableslist.cpp | 149 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 116 insertions(+), 33 deletions(-) (limited to 'src/executableslist.cpp') diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 4b2e380b..79b17f5b 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -84,7 +84,7 @@ void ExecutablesList::getExecutables(std::vector::const_iterator &be const Executable &ExecutablesList::find(const QString &title) const { for (Executable const &exe : m_Executables) { - if (exe.m_Title == title) { + if (exe.title() == title) { return exe; } } @@ -95,7 +95,7 @@ const Executable &ExecutablesList::find(const QString &title) const Executable &ExecutablesList::find(const QString &title) { for (Executable &exe : m_Executables) { - if (exe.m_Title == title) { + if (exe.title() == title) { return exe; } } @@ -106,7 +106,7 @@ Executable &ExecutablesList::find(const QString &title) Executable &ExecutablesList::findByBinary(const QFileInfo &info) { for (Executable &exe : m_Executables) { - if (info == exe.m_BinaryInfo) { + if (exe.binaryInfo() == info) { return exe; } } @@ -117,7 +117,7 @@ Executable &ExecutablesList::findByBinary(const QFileInfo &info) std::vector::iterator ExecutablesList::findExe(const QString &title) { for (std::vector::iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) { - if (iter->m_Title == title) { + if (iter->title() == title) { return iter; } } @@ -127,14 +127,14 @@ std::vector::iterator ExecutablesList::findExe(const QString &title) bool ExecutablesList::titleExists(const QString &title) const { - auto test = [&] (const Executable &exe) { return exe.m_Title == title; }; + auto test = [&] (const Executable &exe) { return exe.title() == title; }; return std::find_if(m_Executables.begin(), m_Executables.end(), test) != m_Executables.end(); } void ExecutablesList::addExecutable(const Executable &executable) { - auto existingExe = findExe(executable.m_Title); + auto existingExe = findExe(executable.title()); if (existingExe != m_Executables.end()) { *existingExe = executable; } else { @@ -157,31 +157,32 @@ void ExecutablesList::updateExecutable(const QString &title, flags &= mask; if (existingExe != m_Executables.end()) { - existingExe->m_Title = title; - existingExe->m_Flags &= ~mask; - existingExe->m_Flags |= flags; + existingExe->setTitle(title); + + auto newFlags = existingExe->flags(); + newFlags &= ~mask; + newFlags |= flags; + + existingExe->setFlags(newFlags); + // for pre-configured executables don't overwrite settings we didn't store if (flags & Executable::CustomExecutable) { if (file.exists()) { // don't overwrite a valid binary with an invalid one - existingExe->m_BinaryInfo = file; + existingExe->setBinaryInfo(file); } + if (dir.exists()) { // don't overwrite a valid working directory with an invalid one - existingExe->m_WorkingDirectory = workingDirectory; + existingExe->setWorkingDirectory(workingDirectory); } - existingExe->m_Arguments = arguments; - existingExe->m_SteamAppID = steamAppID; + existingExe->setArguments(arguments); + existingExe->setSteamAppID(steamAppID); } } else { - Executable newExe; - newExe.m_Title = title; - newExe.m_BinaryInfo = file; - newExe.m_Arguments = arguments; - newExe.m_WorkingDirectory = workingDirectory; - newExe.m_SteamAppID = steamAppID; - newExe.m_Flags = Executable::CustomExecutable | flags; - m_Executables.push_back(newExe); + m_Executables.push_back({ + title, file, arguments, workingDirectory, steamAppID, + Executable::CustomExecutable | flags}); } } @@ -189,7 +190,7 @@ void ExecutablesList::updateExecutable(const QString &title, void ExecutablesList::remove(const QString &title) { for (std::vector::iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) { - if (iter->isCustom() && (iter->m_Title == title)) { + if (iter->isCustom() && (iter->title() == title)) { m_Executables.erase(iter); break; } @@ -203,23 +204,105 @@ void ExecutablesList::addExecutableInternal(const QString &title, const QString { QFileInfo file(executableName); if (file.exists()) { - Executable newExe; - newExe.m_BinaryInfo = file; - newExe.m_Title = title; - newExe.m_Arguments = arguments; - newExe.m_WorkingDirectory = workingDirectory; - newExe.m_SteamAppID = steamAppID; - newExe.m_Flags = Executable::UseApplicationIcon; - m_Executables.push_back(newExe); + m_Executables.push_back({ + title, file, arguments, steamAppID, + workingDirectory, Executable::UseApplicationIcon}); } } -void Executable::showOnToolbar(bool state) +Executable::Executable( + QString title, QFileInfo binaryInfo, QString arguments, + QString steamAppID, QString workingDirectory, Flags flags) : + m_title(std::move(title)), + m_binaryInfo(std::move(binaryInfo)), + m_arguments(std::move(arguments)), + m_steamAppID(std::move(steamAppID)), + m_workingDirectory(std::move(workingDirectory)), + m_flags(flags) +{ +} + +const QString& Executable::title() const +{ + return m_title; +} + +void Executable::setTitle(const QString& s) +{ + m_title = s; +} + +const QFileInfo& Executable::binaryInfo() const +{ + return m_binaryInfo; +} + +void Executable::setBinaryInfo(const QFileInfo& fi) +{ + m_binaryInfo = fi; +} + +const QString& Executable::arguments() const +{ + return m_arguments; +} + +void Executable::setArguments(const QString& s) +{ + m_arguments = s; +} + +const QString& Executable::steamAppID() const +{ + return m_steamAppID; +} + +void Executable::setSteamAppID(const QString& s) +{ + m_steamAppID = s; +} + +const QString& Executable::workingDirectory() const +{ + return m_workingDirectory; +} + +void Executable::setWorkingDirectory(const QString& s) +{ + m_workingDirectory = s; +} + +Executable::Flags Executable::flags() const +{ + return m_flags; +} + +void Executable::setFlags(Flags f) +{ + m_flags = f; +} + +bool Executable::isCustom() const +{ + return m_flags.testFlag(CustomExecutable); +} + +bool Executable::isShownOnToolbar() const +{ + return m_flags.testFlag(ShowInToolbar); +} + +void Executable::setShownOnToolbar(bool state) { if (state) { - m_Flags |= ShowInToolbar; + m_flags |= ShowInToolbar; } else { - m_Flags &= ~ShowInToolbar; + m_flags &= ~ShowInToolbar; } } + +bool Executable::usesOwnIcon() const +{ + return m_flags.testFlag(UseApplicationIcon); +} -- cgit v1.3.1 From 4f01b94f01180989abbdf0407cdf95483970dba8 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 7 Jun 2019 17:53:42 -0400 Subject: replaced ExecutablesList::getExecutables() by a standard container interface renamed ExecutablesList::init() to addFromPlugin() renamed ExecutablesList::find() to get() and added a find() that returns an iterator changed some calls from get() to find() so they can handle failure because they didn't seem to handle std::runtime_error at all --- src/editexecutablesdialog.cpp | 43 ++++++++++++++++---- src/executableslist.cpp | 84 +++++++++++++++++++-------------------- src/executableslist.h | 63 +++++++++++------------------ src/mainwindow.cpp | 92 ++++++++++++++++++++++++++----------------- src/organizercore.cpp | 16 ++++---- 5 files changed, 164 insertions(+), 134 deletions(-) (limited to 'src/executableslist.cpp') diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index 67fbff31..9dbc6bae 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -59,20 +59,29 @@ ExecutablesList EditExecutablesDialog::getExecutablesList() const { ExecutablesList newList; for (int i = 0; i < ui->executablesListBox->count(); ++i) { - newList.addExecutable(m_ExecutablesList.find(ui->executablesListBox->item(i)->text())); + const auto& title = ui->executablesListBox->item(i)->text(); + auto itor = m_ExecutablesList.find(title); + + if (itor == m_ExecutablesList.end()) { + qWarning().nospace() + << "getExecutablesList(): executable '" << title << "' not found"; + + continue; + } + + newList.addExecutable(*itor); } + return newList; } void EditExecutablesDialog::refreshExecutablesWidget() { ui->executablesListBox->clear(); - std::vector::const_iterator current, end; - m_ExecutablesList.getExecutables(current, end); - for(; current != end; ++current) { - QListWidgetItem *newItem = new QListWidgetItem(current->title()); - newItem->setTextColor(current->isCustom() ? QColor(Qt::black) : QColor(Qt::darkGray)); + for(const auto& exe : m_ExecutablesList) { + QListWidgetItem *newItem = new QListWidgetItem(exe.title()); + newItem->setTextColor(exe.isCustom() ? QColor(Qt::black) : QColor(Qt::darkGray)); ui->executablesListBox->addItem(newItem); } @@ -282,7 +291,17 @@ void EditExecutablesDialog::on_titleEdit_textChanged(const QString &arg1) bool EditExecutablesDialog::executableChanged() { if (m_CurrentItem != nullptr) { - Executable const &selectedExecutable(m_ExecutablesList.find(m_CurrentItem->text())); + const auto& title = m_CurrentItem->text(); + auto itor = m_ExecutablesList.find(title); + + if (itor == m_ExecutablesList.end()) { + qWarning().nospace() + << "executableChanged(): title '" << title << "' not found"; + + return false; + } + + const Executable& selectedExecutable = *itor; QString storedCustomOverwrite = m_Profile->setting("custom_overwrites", selectedExecutable.title()).toString(); @@ -374,7 +393,15 @@ void EditExecutablesDialog::on_executablesListBox_clicked(const QModelIndex &cur m_CurrentItem = ui->executablesListBox->item(current.row()); - Executable const &selectedExecutable(m_ExecutablesList.find(m_CurrentItem->text())); + const auto& title = m_CurrentItem->text(); + auto itor = m_ExecutablesList.find(title); + + if (itor == m_ExecutablesList.end()) { + qWarning().nospace() << "selection: executable '" << title << "' not found"; + return; + } + + const Executable& selectedExecutable = *itor; ui->titleEdit->setText(selectedExecutable.title()); ui->binaryEdit->setText(QDir::toNativeSeparators(selectedExecutable.binaryInfo().absoluteFilePath())); diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 79b17f5b..2ea9c3d9 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -33,19 +33,40 @@ along with Mod Organizer. If not, see . using namespace MOBase; +ExecutablesList::iterator ExecutablesList::begin() +{ + return m_Executables.begin(); +} + +ExecutablesList::const_iterator ExecutablesList::begin() const +{ + return m_Executables.begin(); +} + +ExecutablesList::iterator ExecutablesList::end() +{ + return m_Executables.end(); +} + +ExecutablesList::const_iterator ExecutablesList::end() const +{ + return m_Executables.end(); +} -ExecutablesList::ExecutablesList() +std::size_t ExecutablesList::size() const { + return m_Executables.size(); } -ExecutablesList::~ExecutablesList() +bool ExecutablesList::empty() const { + return m_Executables.empty(); } -void ExecutablesList::init(IPluginGame const *game) +void ExecutablesList::addFromPlugin(IPluginGame const *game) { Q_ASSERT(game != nullptr); - m_Executables.clear(); + for (const ExecutableInfo &info : game->executables()) { if (info.isValid()) { addExecutableInternal(info.title(), @@ -55,6 +76,7 @@ void ExecutablesList::init(IPluginGame const *game) info.steamAppID()); } } + ExecutableInfo explorerpp = ExecutableInfo("Explore Virtual Folder", QFileInfo(QCoreApplication::applicationDirPath() + "/explorer++/Explorer++.exe" )) .withArgument(QString("\"%1\"").arg(QDir::toNativeSeparators(game->dataDirectory().absolutePath()))); @@ -65,45 +87,25 @@ void ExecutablesList::init(IPluginGame const *game) explorerpp.workingDirectory().absolutePath(), explorerpp.steamAppID()); } - } -void ExecutablesList::getExecutables(std::vector::iterator &begin, std::vector::iterator &end) +const Executable &ExecutablesList::get(const QString &title) const { - begin = m_Executables.begin(); - end = m_Executables.end(); -} - -void ExecutablesList::getExecutables(std::vector::const_iterator &begin, - std::vector::const_iterator &end) const -{ - begin = m_Executables.begin(); - end = m_Executables.end(); -} - -const Executable &ExecutablesList::find(const QString &title) const -{ - for (Executable const &exe : m_Executables) { + for (const auto& exe : m_Executables) { if (exe.title() == title) { return exe; } } - throw std::runtime_error(QString("invalid executable name: %1").arg(title).toLocal8Bit().constData()); -} + throw std::runtime_error(QString("executable not found: %1").arg(title).toLocal8Bit().constData()); +} -Executable &ExecutablesList::find(const QString &title) +Executable &ExecutablesList::get(const QString &title) { - for (Executable &exe : m_Executables) { - if (exe.title() == title) { - return exe; - } - } - throw std::runtime_error(QString("invalid executable name: %1").arg(title).toLocal8Bit().constData()); + return const_cast(std::as_const(*this).get(title)); } - -Executable &ExecutablesList::findByBinary(const QFileInfo &info) +Executable &ExecutablesList::getByBinary(const QFileInfo &info) { for (Executable &exe : m_Executables) { if (exe.binaryInfo() == info) { @@ -113,17 +115,15 @@ Executable &ExecutablesList::findByBinary(const QFileInfo &info) throw std::runtime_error("invalid info"); } - -std::vector::iterator ExecutablesList::findExe(const QString &title) +ExecutablesList::iterator ExecutablesList::find(const QString &title) { - for (std::vector::iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) { - if (iter->title() == title) { - return iter; - } - } - return m_Executables.end(); + return std::find_if(begin(), end(), [&](auto&& e) { return e.title() == title; }); } +ExecutablesList::const_iterator ExecutablesList::find(const QString &title) const +{ + return std::find_if(begin(), end(), [&](auto&& e) { return e.title() == title; }); +} bool ExecutablesList::titleExists(const QString &title) const { @@ -131,10 +131,9 @@ bool ExecutablesList::titleExists(const QString &title) const return std::find_if(m_Executables.begin(), m_Executables.end(), test) != m_Executables.end(); } - void ExecutablesList::addExecutable(const Executable &executable) { - auto existingExe = findExe(executable.title()); + auto existingExe = find(executable.title()); if (existingExe != m_Executables.end()) { *existingExe = executable; } else { @@ -142,7 +141,6 @@ void ExecutablesList::addExecutable(const Executable &executable) } } - void ExecutablesList::updateExecutable(const QString &title, const QString &executableName, const QString &arguments, @@ -153,7 +151,7 @@ void ExecutablesList::updateExecutable(const QString &title, { QFileInfo file(executableName); QDir dir(workingDirectory); - auto existingExe = findExe(title); + auto existingExe = find(title); flags &= mask; if (existingExe != m_Executables.end()) { diff --git a/src/executableslist.h b/src/executableslist.h index 0e43b337..b8e4cf77 100644 --- a/src/executableslist.h +++ b/src/executableslist.h @@ -88,28 +88,33 @@ private: **/ class ExecutablesList { public: + using vector_type = std::vector; + using iterator = vector_type::iterator; + using const_iterator = vector_type::const_iterator; /** - * @brief constructor - * - **/ - ExecutablesList(); - - ~ExecutablesList(); + * standard container interface + */ + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; + std::size_t size() const; + bool empty() const; /** - * @brief initialise the list with the executables preconfigured for this game + * @brief add the executables preconfigured for this game **/ - void init(MOBase::IPluginGame const *game); + void addFromPlugin(MOBase::IPluginGame const *game); /** - * @brief find an executable by its name + * @brief get an executable by name * * @param title the title of the executable to look up * @return the executable - * @exception runtime_error will throw an exception if the name is not correct + * @exception runtime_error will throw an exception if the executable is not found **/ - const Executable &find(const QString &title) const; + const Executable &get(const QString &title) const; /** * @brief find an executable by its name @@ -118,7 +123,7 @@ public: * @return the executable * @exception runtime_error will throw an exception if the name is not correct **/ - Executable &find(const QString &title); + Executable &get(const QString &title); /** * @brief find an executable by a fileinfo structure @@ -126,7 +131,13 @@ public: * @return the executable * @exception runtime_error will throw an exception if the name is not correct */ - Executable &findByBinary(const QFileInfo &info); + Executable &getByBinary(const QFileInfo &info); + + /** + * @brief returns an iterator for the given executable by title, or end() + */ + iterator find(const QString &title); + const_iterator find(const QString &title) const; /** * @brief determine if an executable exists @@ -183,33 +194,7 @@ public: **/ void remove(const QString &title); - /** - * @brief retrieve begin and end iterators of the configured executables - * - * @param begin iterator to the first executable - * @param end iterator one past the last executable - **/ - void getExecutables(std::vector::const_iterator &begin, std::vector::const_iterator &end) const; - - /** - * @brief retrieve begin and end iterators of the configured executables - * - * @param begin iterator to the first executable - * @param end iterator one past the last executable - **/ - void getExecutables(std::vector::iterator &begin, std::vector::iterator &end); - - /** - * @brief get the number of executables (custom or otherwise) - **/ - size_t size() const { - return m_Executables.size(); - } - private: - - std::vector::iterator findExe(const QString &title); - void addExecutableInternal(const QString &title, const QString &executableName, const QString &arguments, const QString &workingDirectory, const QString &steamAppID); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 38b2ed3f..2fbdbec7 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -733,15 +733,12 @@ void MainWindow::updatePinnedExecutables() bool hasLinks = false; - std::vector::iterator begin, end; - m_OrganizerCore.executablesList()->getExecutables(begin, end); - - for (auto iter = begin; iter != end; ++iter) { - if (iter->isShownOnToolbar()) { + for (const auto& exe : *m_OrganizerCore.executablesList()) { + if (exe.isShownOnToolbar()) { hasLinks = true; QAction *exeAction = new QAction( - iconForExecutable(iter->binaryInfo().filePath()), iter->title()); + iconForExecutable(exe.binaryInfo().filePath()), exe.title()); exeAction->setObjectName(QString("custom__") + iter->m_Title); exeAction->setStatusTip(iter->m_BinaryInfo.filePath()); @@ -1504,24 +1501,42 @@ void MainWindow::registerModPage(IPluginModPage *modPage) void MainWindow::startExeAction() { QAction *action = qobject_cast(sender()); - if (action != nullptr) { - const Executable &selectedExecutable(m_OrganizerCore.executablesList()->find(action->text())); - QString customOverwrite = m_OrganizerCore.currentProfile()->setting("custom_overwrites", selectedExecutable.title()).toString(); - auto forcedLibraries = m_OrganizerCore.currentProfile()->determineForcedLibraries(selectedExecutable.title()); - if (!m_OrganizerCore.currentProfile()->forcedLibrariesEnabled(selectedExecutable.title())) { - forcedLibraries.clear(); - } - m_OrganizerCore.spawnBinary( - selectedExecutable.binaryInfo(), selectedExecutable.arguments(), - selectedExecutable.workingDirectory().length() != 0 - ? selectedExecutable.workingDirectory() - : selectedExecutable.binaryInfo().absolutePath(), - selectedExecutable.steamAppID(), - customOverwrite, - forcedLibraries); - } else { + + if (action == nullptr) { qCritical("not an action?"); + return; } + + const auto& list = *m_OrganizerCore.executablesList(); + + const auto title = action->text(); + auto itor = list.find(title); + + if (itor == list.end()) { + qWarning().nospace() + << "startExeAction(): executable '" << title << "' not found"; + + return; + } + + const Executable& exe = *itor; + auto& profile = *m_OrganizerCore.currentProfile(); + + QString customOverwrite = profile.setting("custom_overwrites", exe.title()).toString(); + auto forcedLibraries = profile.determineForcedLibraries(exe.title()); + + if (!profile.forcedLibrariesEnabled(exe.title())) { + forcedLibraries.clear(); + } + + m_OrganizerCore.spawnBinary( + exe.binaryInfo(), exe.arguments(), + exe.workingDirectory().length() != 0 + ? exe.workingDirectory() + : exe.binaryInfo().absolutePath(), + exe.steamAppID(), + customOverwrite, + forcedLibraries); } @@ -1789,12 +1804,12 @@ void MainWindow::refreshExecutablesList() QAbstractItemModel *model = executablesList->model(); - std::vector::const_iterator current, end; - m_OrganizerCore.executablesList()->getExecutables(current, end); - for(int i = 0; current != end; ++current, ++i) { - QIcon icon = iconForExecutable(current->binaryInfo().filePath()); - executablesList->addItem(icon, current->title()); + int i = 0; + for (const auto& exe : *m_OrganizerCore.executablesList()) { + QIcon icon = iconForExecutable(exe.binaryInfo().filePath()); + executablesList->addItem(icon, exe.title()); model->setData(model->index(i, 0), QSize(0, executablesList->iconSize().height() + 4), Qt::SizeHintRole); + ++i; } setExecutableIndex(1); @@ -6389,13 +6404,18 @@ void MainWindow::unlockESPIndex() void MainWindow::removeFromToolbar() { - try { - Executable &exe = m_OrganizerCore.executablesList()->find(m_ContextAction->text()); - exe.setShownOnToolbar(false); - } catch (const std::runtime_error&) { - qDebug("executable doesn't exist any more"); + const auto& title = m_ContextAction->text(); + auto& list = *m_OrganizerCore.executablesList(); + + auto itor = list.find(title); + if (itor == list.end()) { + qWarning().nospace() + << "removeFromToolbar(): executable '" << title << "' not found"; + + return; } + itor->setShownOnToolbar(false); updatePinnedExecutables(); } @@ -6520,14 +6540,14 @@ void MainWindow::on_groupCombo_currentIndexChanged(int index) const Executable &MainWindow::getSelectedExecutable() const { - QString name = ui->executablesListBox->itemText(ui->executablesListBox->currentIndex()); - return m_OrganizerCore.executablesList()->find(name); + const QString name = ui->executablesListBox->itemText(ui->executablesListBox->currentIndex()); + return m_OrganizerCore.executablesList()->get(name); } Executable &MainWindow::getSelectedExecutable() { - QString name = ui->executablesListBox->itemText(ui->executablesListBox->currentIndex()); - return m_OrganizerCore.executablesList()->find(name); + const QString name = ui->executablesListBox->itemText(ui->executablesListBox->currentIndex()); + return m_OrganizerCore.executablesList()->get(name); } void MainWindow::on_linkButton_pressed() diff --git a/src/organizercore.cpp b/src/organizercore.cpp index cfbcad39..4d11a35f 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -375,11 +375,10 @@ QSettings::Status OrganizerCore::storeSettings(const QString &fileName) settings.remove("customExecutables"); settings.beginWriteArray("customExecutables"); - std::vector::const_iterator current, end; - m_ExecutablesList.getExecutables(current, end); + int count = 0; - for (; current != end; ++current) { - const Executable &item = *current; + + for (const auto& item : m_ExecutablesList) { settings.setArrayIndex(count++); settings.setValue("title", item.title()); settings.setValue("custom", item.isCustom()); @@ -508,7 +507,7 @@ void OrganizerCore::updateExecutablesList(QSettings &settings) return; } - m_ExecutablesList.init(managedGame()); + m_ExecutablesList.addFromPlugin(managedGame()); qDebug("setting up configured executables"); @@ -1735,7 +1734,8 @@ HANDLE OrganizerCore::runShortcut(const MOShortcut& shortcut) .arg(shortcut.instance(),shortcut.executable()) .toLocal8Bit().constData()); - Executable& exe = m_ExecutablesList.find(shortcut.executable()); + const Executable& exe = m_ExecutablesList.get(shortcut.executable()); + auto forcedLibaries = m_CurrentProfile->determineForcedLibraries(shortcut.executable()); if (!m_CurrentProfile->forcedLibrariesEnabled(shortcut.executable())) { forcedLibaries.clear(); @@ -1786,7 +1786,7 @@ HANDLE OrganizerCore::startApplication(const QString &executable, currentDirectory = binary.absolutePath(); } try { - const Executable &exe = m_ExecutablesList.findByBinary(binary); + const Executable &exe = m_ExecutablesList.getByBinary(binary); steamAppID = exe.steamAppID(); customOverwrite = m_CurrentProfile->setting("custom_overwrites", exe.title()) @@ -1800,7 +1800,7 @@ HANDLE OrganizerCore::startApplication(const QString &executable, } else { // only a file name, search executables list try { - const Executable &exe = m_ExecutablesList.find(executable); + const Executable &exe = m_ExecutablesList.get(executable); steamAppID = exe.steamAppID(); customOverwrite = m_CurrentProfile->setting("custom_overwrites", exe.title()) -- cgit v1.3.1 From 26786da96d37914ca91eff633de751acf1a3b9d8 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 7 Jun 2019 18:04:31 -0400 Subject: moved store/load to ExecutablesList --- src/executableslist.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ src/executableslist.h | 21 ++++++++++++------- src/organizercore.cpp | 47 ++++-------------------------------------- 3 files changed, 72 insertions(+), 50 deletions(-) (limited to 'src/executableslist.cpp') diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 2ea9c3d9..43a30f02 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -63,6 +63,60 @@ bool ExecutablesList::empty() const return m_Executables.empty(); } +void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings) +{ + addFromPlugin(game); + + qDebug("setting up configured executables"); + + int numCustomExecutables = settings.beginReadArray("customExecutables"); + for (int i = 0; i < numCustomExecutables; ++i) { + settings.setArrayIndex(i); + + Executable::Flags flags; + if (settings.value("custom", true).toBool()) + flags |= Executable::CustomExecutable; + if (settings.value("toolbar", false).toBool()) + flags |= Executable::ShowInToolbar; + if (settings.value("ownicon", false).toBool()) + flags |= Executable::UseApplicationIcon; + + addExecutable( + settings.value("title").toString(), settings.value("binary").toString(), + settings.value("arguments").toString(), + settings.value("workingDirectory", "").toString(), + settings.value("steamAppID", "").toString(), flags); + } + + settings.endArray(); +} + +void ExecutablesList::store(QSettings& settings) +{ + settings.remove("customExecutables"); + settings.beginWriteArray("customExecutables"); + + int count = 0; + + for (const auto& item : *this) { + settings.setArrayIndex(count++); + + settings.setValue("title", item.title()); + settings.setValue("custom", item.isCustom()); + settings.setValue("toolbar", item.isShownOnToolbar()); + settings.setValue("ownicon", item.usesOwnIcon()); + + if (item.isCustom()) { + settings.setValue("binary", item.binaryInfo().absoluteFilePath()); + settings.setValue("arguments", item.arguments()); + settings.setValue("workingDirectory", item.workingDirectory()); + settings.setValue("steamAppID", item.steamAppID()); + } + } + + settings.endArray(); +} + void ExecutablesList::addFromPlugin(IPluginGame const *game) { Q_ASSERT(game != nullptr); diff --git a/src/executableslist.h b/src/executableslist.h index b8e4cf77..136f70bf 100644 --- a/src/executableslist.h +++ b/src/executableslist.h @@ -103,9 +103,14 @@ public: bool empty() const; /** - * @brief add the executables preconfigured for this game - **/ - void addFromPlugin(MOBase::IPluginGame const *game); + * @brief initializes the list from the settings and the given plugin + */ + void load(const MOBase::IPluginGame* game, QSettings& settings); + + /** + * @brief writes the current list to the settings + */ + void store(QSettings& settings); /** * @brief get an executable by name @@ -195,14 +200,16 @@ public: void remove(const QString &title); private: + std::vector m_Executables; + void addExecutableInternal(const QString &title, const QString &executableName, const QString &arguments, const QString &workingDirectory, const QString &steamAppID); -private: - - std::vector m_Executables; - + /** + * @brief add the executables preconfigured for this game + **/ + void addFromPlugin(MOBase::IPluginGame const *game); }; Q_DECLARE_OPERATORS_FOR_FLAGS(Executable::Flags) diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 4d11a35f..2172538e 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -365,33 +365,17 @@ QString OrganizerCore::commitSettings(const QString &iniFile) QSettings::Status OrganizerCore::storeSettings(const QString &fileName) { QSettings settings(fileName, QSettings::IniFormat); + if (m_UserInterface != nullptr) { m_UserInterface->storeSettings(settings); } + if (m_CurrentProfile != nullptr) { settings.setValue("selected_profile", m_CurrentProfile->name().toUtf8().constData()); } - settings.remove("customExecutables"); - settings.beginWriteArray("customExecutables"); - - int count = 0; - - for (const auto& item : m_ExecutablesList) { - settings.setArrayIndex(count++); - settings.setValue("title", item.title()); - settings.setValue("custom", item.isCustom()); - settings.setValue("toolbar", item.isShownOnToolbar()); - settings.setValue("ownicon", item.usesOwnIcon()); - if (item.isCustom()) { - settings.setValue("binary", item.binaryInfo().absoluteFilePath()); - settings.setValue("arguments", item.arguments()); - settings.setValue("workingDirectory", item.workingDirectory()); - settings.setValue("steamAppID", item.steamAppID()); - } - } - settings.endArray(); + m_ExecutablesList.store(settings); FileDialogMemory::save(settings); @@ -507,30 +491,7 @@ void OrganizerCore::updateExecutablesList(QSettings &settings) return; } - m_ExecutablesList.addFromPlugin(managedGame()); - - qDebug("setting up configured executables"); - - int numCustomExecutables = settings.beginReadArray("customExecutables"); - for (int i = 0; i < numCustomExecutables; ++i) { - settings.setArrayIndex(i); - - Executable::Flags flags; - if (settings.value("custom", true).toBool()) - flags |= Executable::CustomExecutable; - if (settings.value("toolbar", false).toBool()) - flags |= Executable::ShowInToolbar; - if (settings.value("ownicon", false).toBool()) - flags |= Executable::UseApplicationIcon; - - m_ExecutablesList.addExecutable( - settings.value("title").toString(), settings.value("binary").toString(), - settings.value("arguments").toString(), - settings.value("workingDirectory", "").toString(), - settings.value("steamAppID", "").toString(), flags); - } - - settings.endArray(); + m_ExecutablesList.load(managedGame(), settings); // TODO this has nothing to do with executables list move to an appropriate // function! -- cgit v1.3.1 From 617a6005451aba1d45f13228f13f1cc150a78bb4 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 7 Jun 2019 18:24:41 -0400 Subject: ExecutablesList: - merged addExecutable(), updateExecutable() and addExecutableInternal() into a new setExecutable() - setExecutable() adds the executable to the list if not found, or forwards to Executable::mergeFrom() - mergeFrom() handles merging from/to plugin executables --- src/editexecutablesdialog.cpp | 24 ++++---- src/executableslist.cpp | 125 ++++++++++++++++++------------------------ src/executableslist.h | 48 +++------------- src/mainwindow.cpp | 10 ++-- 4 files changed, 77 insertions(+), 130 deletions(-) (limited to 'src/executableslist.cpp') diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index 9dbc6bae..83756ac8 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -69,7 +69,7 @@ ExecutablesList EditExecutablesDialog::getExecutablesList() const continue; } - newList.addExecutable(*itor); + newList.setExecutable(*itor); } return newList; @@ -138,17 +138,17 @@ void EditExecutablesDialog::resetInput() void EditExecutablesDialog::saveExecutable() { - m_ExecutablesList.updateExecutable( - ui->titleEdit->text(), - QDir::fromNativeSeparators(ui->binaryEdit->text()), - ui->argumentsEdit->text(), - QDir::fromNativeSeparators(ui->workingDirEdit->text()), - ui->overwriteAppIDBox->isChecked() ? - ui->appIDOverwriteEdit->text() : "", - Executable::UseApplicationIcon | Executable::CustomExecutable, - (ui->useAppIconCheckBox->isChecked() ? - Executable::UseApplicationIcon : Executable::Flags()) - | Executable::CustomExecutable); + Executable::Flags flags = Executable::CustomExecutable; + if (ui->useAppIconCheckBox->isChecked()) + flags |= Executable::UseApplicationIcon; + + m_ExecutablesList.setExecutable({ + ui->titleEdit->text(), + QDir::fromNativeSeparators(ui->binaryEdit->text()), + ui->argumentsEdit->text(), + QDir::fromNativeSeparators(ui->workingDirEdit->text()), + ui->overwriteAppIDBox->isChecked() ? ui->appIDOverwriteEdit->text() : "", + flags}); if (ui->newFilesModCheckBox->isChecked()) { m_Profile->storeSetting("custom_overwrites", ui->titleEdit->text(), diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 43a30f02..062ee28e 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -81,11 +81,13 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings) if (settings.value("ownicon", false).toBool()) flags |= Executable::UseApplicationIcon; - addExecutable( - settings.value("title").toString(), settings.value("binary").toString(), + setExecutable({ + settings.value("title").toString(), + settings.value("binary").toString(), settings.value("arguments").toString(), settings.value("workingDirectory", "").toString(), - settings.value("steamAppID", "").toString(), flags); + settings.value("steamAppID", "").toString(), + flags}); } settings.endArray(); @@ -123,11 +125,13 @@ void ExecutablesList::addFromPlugin(IPluginGame const *game) for (const ExecutableInfo &info : game->executables()) { if (info.isValid()) { - addExecutableInternal(info.title(), - info.binary().absoluteFilePath(), - info.arguments().join(" "), - info.workingDirectory().absolutePath(), - info.steamAppID()); + setExecutable({ + info.title(), + info.binary().absoluteFilePath(), + info.arguments().join(" "), + info.workingDirectory().absolutePath(), + info.steamAppID(), + Executable::UseApplicationIcon}); } } @@ -135,11 +139,13 @@ void ExecutablesList::addFromPlugin(IPluginGame const *game) .withArgument(QString("\"%1\"").arg(QDir::toNativeSeparators(game->dataDirectory().absolutePath()))); if (explorerpp.isValid()) { - addExecutableInternal(explorerpp.title(), + setExecutable({ + explorerpp.title(), explorerpp.binary().absoluteFilePath(), explorerpp.arguments().join(" "), explorerpp.workingDirectory().absolutePath(), - explorerpp.steamAppID()); + explorerpp.steamAppID(), + Executable::UseApplicationIcon}); } } @@ -185,60 +191,17 @@ bool ExecutablesList::titleExists(const QString &title) const return std::find_if(m_Executables.begin(), m_Executables.end(), test) != m_Executables.end(); } -void ExecutablesList::addExecutable(const Executable &executable) +void ExecutablesList::setExecutable(const Executable &executable) { - auto existingExe = find(executable.title()); - if (existingExe != m_Executables.end()) { - *existingExe = executable; - } else { - m_Executables.push_back(executable); - } -} + auto itor = find(executable.title()); -void ExecutablesList::updateExecutable(const QString &title, - const QString &executableName, - const QString &arguments, - const QString &workingDirectory, - const QString &steamAppID, - Executable::Flags mask, - Executable::Flags flags) -{ - QFileInfo file(executableName); - QDir dir(workingDirectory); - auto existingExe = find(title); - flags &= mask; - - if (existingExe != m_Executables.end()) { - existingExe->setTitle(title); - - auto newFlags = existingExe->flags(); - newFlags &= ~mask; - newFlags |= flags; - - existingExe->setFlags(newFlags); - - // for pre-configured executables don't overwrite settings we didn't store - if (flags & Executable::CustomExecutable) { - if (file.exists()) { - // don't overwrite a valid binary with an invalid one - existingExe->setBinaryInfo(file); - } - - if (dir.exists()) { - // don't overwrite a valid working directory with an invalid one - existingExe->setWorkingDirectory(workingDirectory); - } - existingExe->setArguments(arguments); - existingExe->setSteamAppID(steamAppID); - } + if (itor == m_Executables.end()) { + m_Executables.push_back(executable); } else { - m_Executables.push_back({ - title, file, arguments, workingDirectory, steamAppID, - Executable::CustomExecutable | flags}); + itor->mergeFrom(executable); } } - void ExecutablesList::remove(const QString &title) { for (std::vector::iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) { @@ -250,19 +213,6 @@ void ExecutablesList::remove(const QString &title) } -void ExecutablesList::addExecutableInternal(const QString &title, const QString &executableName, - const QString &arguments, const QString &workingDirectory, - const QString &steamAppID) -{ - QFileInfo file(executableName); - if (file.exists()) { - m_Executables.push_back({ - title, file, arguments, steamAppID, - workingDirectory, Executable::UseApplicationIcon}); - } -} - - Executable::Executable( QString title, QFileInfo binaryInfo, QString arguments, QString steamAppID, QString workingDirectory, Flags flags) : @@ -358,3 +308,36 @@ bool Executable::usesOwnIcon() const { return m_flags.testFlag(UseApplicationIcon); } + +void Executable::mergeFrom(const Executable& other) +{ + if (!isCustom()) { + // this happens when the user is trying to modify a plugin executable + + // only change some of the flags + const auto allow = ShowInToolbar; + + m_flags |= (other.flags() & allow); + } else { + // this happens after executables are loaded from settings and plugin + // executables are being added, or when users are modifying executables + + m_title = other.title(); + m_arguments = other.arguments(); + m_steamAppID = other.steamAppID(); + m_workingDirectory = other.workingDirectory(); + + // don't overwrite a valid binary with an invalid one + if (other.binaryInfo().exists()) { + m_binaryInfo = other.binaryInfo(); + } + + if (!other.isCustom()) { + // overwriting a custom executable with a plugin, merge all the flags + m_flags |= other.flags(); + } else { + // overwriting a custom with another custom, just replace the flags + m_flags = other.flags(); + } + } +} diff --git a/src/executableslist.h b/src/executableslist.h index 136f70bf..4965dbf9 100644 --- a/src/executableslist.h +++ b/src/executableslist.h @@ -73,6 +73,8 @@ public: void setShownOnToolbar(bool state); bool usesOwnIcon() const; + void mergeFrom(const Executable& other); + private: QString m_title; QFileInfo m_binaryInfo; @@ -155,57 +157,21 @@ public: * @brief add a new executable to the list * @param executable */ - void addExecutable(const Executable &executable); - - /** - * @brief add a new executable to the list - * - * @param title name displayed in the UI - * @param executableName the actual filename to execute - * @param arguments arguments to pass to the executable - **/ - void addExecutable(const QString &title, - const QString &executableName, - const QString &arguments, - const QString &workingDirectory, - const QString &steamAppID, - Executable::Flags flags) - { - updateExecutable(title, executableName, arguments, workingDirectory, - steamAppID, Executable::AllFlags, flags); - } - - /** - * @brief Update an executable to the list - * - * @param title name displayed in the UI - * @param executableName the actual filename to execute - * @param arguments arguments to pass to the executable - * @param closeMO if true, MO will be closed when the binary is started - **/ - void updateExecutable(const QString &title, - const QString &executableName, - const QString &arguments, - const QString &workingDirectory, - const QString &steamAppID, - Executable::Flags mask, - Executable::Flags flags); + void setExecutable(const Executable &executable); /** - * @brief remove the executable with the specified file name. This needs to be an absolute file path + * @brief remove the executable with the specified file name. This needs to + * be an absolute file path * * @param title title of the executable to remove - * @note if the executable name is invalid, nothing happens. There is no way to determine if this was successful + * @note if the executable name is invalid, nothing happens. There is no way + * to determine if this was successful **/ void remove(const QString &title); private: std::vector m_Executables; - void addExecutableInternal(const QString &title, const QString &executableName, const QString &arguments, - const QString &workingDirectory, - const QString &steamAppID); - /** * @brief add the executables preconfigured for this game **/ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2fbdbec7..926ba43c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -5507,12 +5507,10 @@ void MainWindow::addAsExecutable() if (!name.isEmpty()) { //Note: If this already exists, you'll lose custom settings - m_OrganizerCore.executablesList()->addExecutable(name, - binaryInfo.absoluteFilePath(), - arguments, - targetInfo.absolutePath(), - QString(), - Executable::CustomExecutable); + m_OrganizerCore.executablesList()->setExecutable({ + name, binaryInfo, arguments, targetInfo.absolutePath(), QString(), + Executable::CustomExecutable}); + refreshExecutablesList(); } -- cgit v1.3.1 From 65ad374d9769524a62ac423b7d73661e42163265 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 7 Jun 2019 18:29:20 -0400 Subject: removed temporary setters in Executable, unnecessary now that it has mergeFrom() --- src/executableslist.cpp | 30 ------------------------------ src/executableslist.h | 15 +-------------- 2 files changed, 1 insertion(+), 44 deletions(-) (limited to 'src/executableslist.cpp') diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 062ee28e..9c291708 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -230,61 +230,31 @@ const QString& Executable::title() const return m_title; } -void Executable::setTitle(const QString& s) -{ - m_title = s; -} - const QFileInfo& Executable::binaryInfo() const { return m_binaryInfo; } -void Executable::setBinaryInfo(const QFileInfo& fi) -{ - m_binaryInfo = fi; -} - const QString& Executable::arguments() const { return m_arguments; } -void Executable::setArguments(const QString& s) -{ - m_arguments = s; -} - const QString& Executable::steamAppID() const { return m_steamAppID; } -void Executable::setSteamAppID(const QString& s) -{ - m_steamAppID = s; -} - const QString& Executable::workingDirectory() const { return m_workingDirectory; } -void Executable::setWorkingDirectory(const QString& s) -{ - m_workingDirectory = s; -} - Executable::Flags Executable::flags() const { return m_flags; } -void Executable::setFlags(Flags f) -{ - m_flags = f; -} - bool Executable::isCustom() const { return m_flags.testFlag(CustomExecutable); diff --git a/src/executableslist.h b/src/executableslist.h index 4965dbf9..e35cb550 100644 --- a/src/executableslist.h +++ b/src/executableslist.h @@ -39,9 +39,7 @@ public: { CustomExecutable = 0x01, ShowInToolbar = 0x02, - UseApplicationIcon = 0x04, - - AllFlags = 0xff //I know, I know + UseApplicationIcon = 0x04 }; Q_DECLARE_FLAGS(Flags, Flag); @@ -51,22 +49,11 @@ public: QString steamAppID, QString workingDirectory, Flags flags); const QString& title() const; - void setTitle(const QString& s); - const QFileInfo& binaryInfo() const; - void setBinaryInfo(const QFileInfo& fi); - const QString& arguments() const; - void setArguments(const QString& s); - const QString& steamAppID() const; - void setSteamAppID(const QString& s); - const QString& workingDirectory() const; - void setWorkingDirectory(const QString& s); - Flags flags() const; - void setFlags(Flags f); bool isCustom() const; bool isShownOnToolbar() const; -- cgit v1.3.1 From fafdb146004401355db5245cc1f7c241c00cf991 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 7 Jun 2019 19:26:54 -0400 Subject: fixed EditExecutablesDialog being opened without a parent removed Executable's constructor with values, replaced with default ctor + setters, all these strings were much too error-prone added Executable ctor overload to convert from ExecutableInfo plugin executables now override most of the custom changes renamed browseButton to browseBinaryButton to avoid confusion with the other browseDirButton fixed both browse dialogs not handling cancel EditExecutablesDialog's list used to change the text color for custom executables, replaced with italics --- src/editexecutablesdialog.cpp | 35 +++++++++---- src/editexecutablesdialog.h | 2 +- src/editexecutablesdialog.ui | 4 +- src/executableslist.cpp | 118 ++++++++++++++++++++++++++++-------------- src/executableslist.h | 18 +++++-- src/mainwindow.cpp | 13 +++-- 6 files changed, 132 insertions(+), 58 deletions(-) (limited to 'src/executableslist.cpp') diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index 83756ac8..a3b2808a 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -81,7 +81,14 @@ void EditExecutablesDialog::refreshExecutablesWidget() for(const auto& exe : m_ExecutablesList) { QListWidgetItem *newItem = new QListWidgetItem(exe.title()); - newItem->setTextColor(exe.isCustom() ? QColor(Qt::black) : QColor(Qt::darkGray)); + + if (!exe.isCustom()) { + auto f = newItem->font(); + f.setItalic(true); + + newItem->setFont(f); + } + ui->executablesListBox->addItem(newItem); } @@ -142,13 +149,13 @@ void EditExecutablesDialog::saveExecutable() if (ui->useAppIconCheckBox->isChecked()) flags |= Executable::UseApplicationIcon; - m_ExecutablesList.setExecutable({ - ui->titleEdit->text(), - QDir::fromNativeSeparators(ui->binaryEdit->text()), - ui->argumentsEdit->text(), - QDir::fromNativeSeparators(ui->workingDirEdit->text()), - ui->overwriteAppIDBox->isChecked() ? ui->appIDOverwriteEdit->text() : "", - flags}); + m_ExecutablesList.setExecutable(Executable() + .title(ui->titleEdit->text()) + .binaryInfo(QDir::fromNativeSeparators(ui->binaryEdit->text())) + .arguments(ui->argumentsEdit->text()) + .steamAppID(ui->overwriteAppIDBox->isChecked() ? ui->appIDOverwriteEdit->text() : "") + .workingDirectory(QDir::fromNativeSeparators(ui->workingDirEdit->text())) + .flags(flags)); if (ui->newFilesModCheckBox->isChecked()) { m_Profile->storeSetting("custom_overwrites", ui->titleEdit->text(), @@ -198,12 +205,17 @@ void EditExecutablesDialog::on_addButton_clicked() refreshExecutablesWidget(); } -void EditExecutablesDialog::on_browseButton_clicked() +void EditExecutablesDialog::on_browseBinaryButton_clicked() { QString binaryName = FileDialogMemory::getOpenFileName( "editExecutableBinary", this, tr("Select a binary"), QString(), tr("Executable (%1)").arg("*.exe *.bat *.jar")); + if (binaryName.isNull()) { + // canceled + return; + } + if (binaryName.endsWith(".jar", Qt::CaseInsensitive)) { QString binaryPath; { // try to find java automatically @@ -250,6 +262,11 @@ void EditExecutablesDialog::on_browseDirButton_clicked() QString dirName = FileDialogMemory::getExistingDirectory("editExecutableDirectory", this, tr("Select a directory")); + if (dirName.isNull()) { + // canceled + return; + } + ui->workingDirEdit->setText(dirName); } diff --git a/src/editexecutablesdialog.h b/src/editexecutablesdialog.h index bee3cba6..3a856afa 100644 --- a/src/editexecutablesdialog.h +++ b/src/editexecutablesdialog.h @@ -78,7 +78,7 @@ private slots: void on_addButton_clicked(); - void on_browseButton_clicked(); + void on_browseBinaryButton_clicked(); void on_removeButton_clicked(); diff --git a/src/editexecutablesdialog.ui b/src/editexecutablesdialog.ui index 4f9223d5..adda050c 100644 --- a/src/editexecutablesdialog.ui +++ b/src/editexecutablesdialog.ui @@ -80,7 +80,7 @@ - + Browse filesystem @@ -310,7 +310,7 @@ Right now the only case I know of where this needs to be overwritten is for the executablesListBox titleEdit binaryEdit - browseButton + browseBinaryButton workingDirEdit browseDirButton argumentsEdit diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 9c291708..d884bdf2 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -81,13 +81,13 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings) if (settings.value("ownicon", false).toBool()) flags |= Executable::UseApplicationIcon; - setExecutable({ - settings.value("title").toString(), - settings.value("binary").toString(), - settings.value("arguments").toString(), - settings.value("workingDirectory", "").toString(), - settings.value("steamAppID", "").toString(), - flags}); + setExecutable(Executable() + .title(settings.value("title").toString()) + .binaryInfo(settings.value("binary").toString()) + .arguments(settings.value("arguments").toString()) + .steamAppID(settings.value("steamAppID", "").toString()) + .workingDirectory(settings.value("workingDirectory", "").toString()) + .flags(flags)); } settings.endArray(); @@ -125,27 +125,22 @@ void ExecutablesList::addFromPlugin(IPluginGame const *game) for (const ExecutableInfo &info : game->executables()) { if (info.isValid()) { - setExecutable({ - info.title(), - info.binary().absoluteFilePath(), - info.arguments().join(" "), - info.workingDirectory().absolutePath(), - info.steamAppID(), - Executable::UseApplicationIcon}); + setExecutable({info, Executable::UseApplicationIcon}); } } - ExecutableInfo explorerpp = ExecutableInfo("Explore Virtual Folder", QFileInfo(QCoreApplication::applicationDirPath() + "/explorer++/Explorer++.exe" )) - .withArgument(QString("\"%1\"").arg(QDir::toNativeSeparators(game->dataDirectory().absolutePath()))); - - if (explorerpp.isValid()) { - setExecutable({ - explorerpp.title(), - explorerpp.binary().absoluteFilePath(), - explorerpp.arguments().join(" "), - explorerpp.workingDirectory().absolutePath(), - explorerpp.steamAppID(), - Executable::UseApplicationIcon}); + const QFileInfo eppBin(QCoreApplication::applicationDirPath() + "/explorer++/Explorer++.exe"); + + if (eppBin.exists()) { + const auto args = QString("\"%1\"") + .arg(QDir::toNativeSeparators(game->dataDirectory().absolutePath())); + + setExecutable(Executable() + .title("Explore Virtual Folder") + .binaryInfo(eppBin) + .arguments(args) + .workingDirectory(eppBin.absolutePath()) + .flags(Executable::UseApplicationIcon)); } } @@ -213,15 +208,13 @@ void ExecutablesList::remove(const QString &title) } -Executable::Executable( - QString title, QFileInfo binaryInfo, QString arguments, - QString steamAppID, QString workingDirectory, Flags flags) : - m_title(std::move(title)), - m_binaryInfo(std::move(binaryInfo)), - m_arguments(std::move(arguments)), - m_steamAppID(std::move(steamAppID)), - m_workingDirectory(std::move(workingDirectory)), - m_flags(flags) +Executable::Executable(const MOBase::ExecutableInfo& info, Flags flags) : + m_title(info.title()), + m_binaryInfo(info.binary()), + m_arguments(info.arguments().join(" ")), + m_steamAppID(info.steamAppID()), + m_workingDirectory(info.workingDirectory().absolutePath()), + m_flags(flags) { } @@ -255,6 +248,42 @@ Executable::Flags Executable::flags() const return m_flags; } +Executable& Executable::title(const QString& s) +{ + m_title = s; + return *this; +} + +Executable& Executable::binaryInfo(const QFileInfo& fi) +{ + m_binaryInfo = fi; + return *this; +} + +Executable& Executable::arguments(const QString& s) +{ + m_arguments = s; + return *this; +} + +Executable& Executable::steamAppID(const QString& s) +{ + m_steamAppID = s; + return *this; +} + +Executable& Executable::workingDirectory(const QString& s) +{ + m_workingDirectory = s; + return *this; +} + +Executable& Executable::flags(Flags f) +{ + m_flags = f; + return *this; +} + bool Executable::isCustom() const { return m_flags.testFlag(CustomExecutable); @@ -281,12 +310,25 @@ bool Executable::usesOwnIcon() const void Executable::mergeFrom(const Executable& other) { - if (!isCustom()) { - // this happens when the user is trying to modify a plugin executable + // flags on plugin executables that the user is allowed to chnage + const auto allow = ShowInToolbar; + + + if (!isCustom() && !other.isCustom()) { + // this happens when loading plugin executables in addFromPlugin(), replace + // everything in case the plugin has changed - // only change some of the flags - const auto allow = ShowInToolbar; + // remember the flags though + const auto flags = m_flags; + // overwrite everything + *this = other; + + // set the user flags + m_flags |= (flags & allow); + } + else if (!isCustom()) { + // this happens when the user is trying to modify a plugin executable m_flags |= (other.flags() & allow); } else { // this happens after executables are loaded from settings and plugin diff --git a/src/executableslist.h b/src/executableslist.h index e35cb550..54a105d0 100644 --- a/src/executableslist.h +++ b/src/executableslist.h @@ -27,7 +27,7 @@ along with Mod Organizer. If not, see . #include #include -namespace MOBase { class IPluginGame; } +namespace MOBase { class IPluginGame; class ExecutableInfo; } /*! * @brief Information about an executable @@ -44,9 +44,12 @@ public: Q_DECLARE_FLAGS(Flags, Flag); - Executable( - QString title, QFileInfo binaryInfo, QString arguments, - QString steamAppID, QString workingDirectory, Flags flags); + Executable() = default; + + /** + * @brief Executable from plugin + */ + Executable(const MOBase::ExecutableInfo& info, Flags flags); const QString& title() const; const QFileInfo& binaryInfo() const; @@ -55,6 +58,13 @@ public: const QString& workingDirectory() const; Flags flags() const; + Executable& title(const QString& s); + Executable& binaryInfo(const QFileInfo& fi); + Executable& arguments(const QString& s); + Executable& steamAppID(const QString& s); + Executable& workingDirectory(const QString& s); + Executable& flags(Flags f); + bool isCustom() const; bool isShownOnToolbar() const; void setShownOnToolbar(bool state); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 926ba43c..267a2971 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2483,7 +2483,9 @@ bool MainWindow::modifyExecutablesDialog() EditExecutablesDialog dialog(*m_OrganizerCore.executablesList(), *m_OrganizerCore.modList(), m_OrganizerCore.currentProfile(), - m_OrganizerCore.managedGame()); + m_OrganizerCore.managedGame(), + this); + QSettings &settings = m_OrganizerCore.settings().directInterface(); QString key = QString("geometry/%1").arg(dialog.objectName()); if (settings.contains(key)) { @@ -5507,9 +5509,12 @@ void MainWindow::addAsExecutable() if (!name.isEmpty()) { //Note: If this already exists, you'll lose custom settings - m_OrganizerCore.executablesList()->setExecutable({ - name, binaryInfo, arguments, targetInfo.absolutePath(), QString(), - Executable::CustomExecutable}); + m_OrganizerCore.executablesList()->setExecutable(Executable() + .title(name) + .binaryInfo(binaryInfo) + .arguments(arguments) + .workingDirectory(targetInfo.absolutePath()) + .flags(Executable::CustomExecutable)); refreshExecutablesList(); } -- cgit v1.3.1 From 39d953c838d459085b4044c9ca5bda0248e47f6b Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 7 Jun 2019 21:03:25 -0400 Subject: load plugin executables after settings, allows for changing the order added warning that an executable is provided by a plugin, disable widgets that can't be changed refactoring EditExecutablesDialog --- src/editexecutablesdialog.cpp | 134 +++++++++++--- src/editexecutablesdialog.h | 9 +- src/editexecutablesdialog.ui | 405 ++++++++++++++++++++++-------------------- src/executableslist.cpp | 4 +- 4 files changed, 328 insertions(+), 224 deletions(-) (limited to 'src/executableslist.cpp') diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index f7348889..8494c892 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -47,15 +47,96 @@ EditExecutablesDialog::EditExecutablesDialog( ui->splitter->setStretchFactor(1, 1); refreshExecutablesWidget(); - ui->newFilesModBox->addItems(modList.allMods()); m_ForcedLibraries = m_Profile->determineForcedLibraries(ui->titleEdit->text()); + + updateUI(nullptr); +} + +EditExecutablesDialog::~EditExecutablesDialog() = default; + +void EditExecutablesDialog::updateUI(const Executable* e) +{ + if (e) { + setEdits(*e); + } else { + clearEdits(); + ui->removeButton->setEnabled(false); + } +} + +void EditExecutablesDialog::clearEdits() +{ + ui->titleEdit->clear(); + ui->binaryEdit->clear(); + ui->workingDirEdit->clear(); + ui->argumentsEdit->clear(); + ui->overwriteAppIDBox->setChecked(false); + ui->appIDOverwriteEdit->clear(); + ui->newFilesModCheckBox->setChecked(false); + ui->newFilesModBox->setCurrentIndex(-1); + ui->forceLoadCheckBox->setChecked(false); + ui->useAppIconCheckBox->setChecked(false); + + ui->pluginProvidedLabel->setVisible(false); } -EditExecutablesDialog::~EditExecutablesDialog() +void EditExecutablesDialog::setEdits(const Executable& e) { - delete ui; + ui->titleEdit->setText(e.title()); + ui->binaryEdit->setText(QDir::toNativeSeparators(e.binaryInfo().absoluteFilePath())); + ui->workingDirEdit->setText(QDir::toNativeSeparators(e.workingDirectory())); + ui->argumentsEdit->setText(e.arguments()); + ui->overwriteAppIDBox->setChecked(!e.steamAppID().isEmpty()); + ui->appIDOverwriteEdit->setText(e.steamAppID()); + ui->useAppIconCheckBox->setChecked(e.usesOwnIcon()); + + int modIndex = -1; + + QString customOverwrite = m_Profile->setting("custom_overwrites", e.title()).toString(); + if (!customOverwrite.isEmpty()) { + modIndex = ui->newFilesModBox->findText(customOverwrite); + } + + ui->newFilesModCheckBox->setChecked(modIndex != -1); + ui->newFilesModBox->setCurrentIndex(modIndex); + + const bool forcedLibraries = m_Profile->forcedLibrariesEnabled(e.title()); + ui->forceLoadCheckBox->setChecked(forcedLibraries); + ui->forceLoadButton->setEnabled(forcedLibraries); + + ui->pluginProvidedLabel->setVisible(!e.isCustom()); + + // only enabled for custom executables + ui->titleEdit->setEnabled(e.isCustom()); + ui->binaryEdit->setEnabled(e.isCustom()); + ui->browseBinaryButton->setEnabled(e.isCustom()); + ui->workingDirEdit->setEnabled(e.isCustom()); + ui->browseWorkingDirButton->setEnabled(e.isCustom()); + ui->argumentsEdit->setEnabled(e.isCustom()); + ui->overwriteAppIDBox->setEnabled(e.isCustom()); + ui->appIDOverwriteEdit->setEnabled(e.isCustom()); + ui->useAppIconCheckBox->setEnabled(e.isCustom()); + + // always enabled + ui->newFilesModCheckBox->setEnabled(true); + ui->newFilesModBox->setEnabled(true); + ui->forceLoadCheckBox->setEnabled(true); +} + +void EditExecutablesDialog::resetInput() +{ + ui->binaryEdit->setText(""); + ui->titleEdit->setText(""); + ui->workingDirEdit->clear(); + ui->argumentsEdit->setText(""); + ui->appIDOverwriteEdit->clear(); + ui->overwriteAppIDBox->setChecked(false); + ui->useAppIconCheckBox->setChecked(false); + ui->newFilesModCheckBox->setChecked(false); + ui->forceLoadCheckBox->setChecked(false); + m_CurrentItem = nullptr; } ExecutablesList EditExecutablesDialog::getExecutablesList() const @@ -95,8 +176,8 @@ void EditExecutablesDialog::refreshExecutablesWidget() ui->executablesListBox->addItem(newItem); } - ui->addButton->setEnabled(false); - ui->removeButton->setEnabled(false); + //ui->addButton->setEnabled(false); + //ui->removeButton->setEnabled(false); } @@ -131,20 +212,6 @@ void EditExecutablesDialog::updateButtonStates() ui->addButton->setEnabled(enabled); } -void EditExecutablesDialog::resetInput() -{ - ui->binaryEdit->setText(""); - ui->titleEdit->setText(""); - ui->workingDirEdit->clear(); - ui->argumentsEdit->setText(""); - ui->appIDOverwriteEdit->clear(); - ui->overwriteAppIDBox->setChecked(false); - ui->useAppIconCheckBox->setChecked(false); - ui->newFilesModCheckBox->setChecked(false); - ui->forceLoadCheckBox->setChecked(false); - m_CurrentItem = nullptr; -} - void EditExecutablesDialog::saveExecutable() { @@ -260,7 +327,7 @@ void EditExecutablesDialog::on_browseBinaryButton_clicked() } } -void EditExecutablesDialog::on_browseDirButton_clicked() +void EditExecutablesDialog::on_browseWorkingDirButton_clicked() { QString dirName = FileDialogMemory::getExistingDirectory("editExecutableDirectory", this, tr("Select a directory")); @@ -359,10 +426,27 @@ bool EditExecutablesDialog::executableChanged() } void EditExecutablesDialog::on_executablesListBox_itemSelectionChanged() { - if (ui->executablesListBox->selectedItems().size() == 0) { - // deselected - resetInput(); + const auto selection = ui->executablesListBox->selectedItems(); + + if (selection.empty()) { + updateUI(nullptr); + return; + } + + auto* item = selection[0]; + if (!item) { + return; } + + const auto& title = item->text(); + auto itor = m_ExecutablesList.find(title); + + if (itor == m_ExecutablesList.end()) { + qWarning().nospace() << "selection: executable '" << title << "' not found"; + return; + } + + updateUI(&*itor); } void EditExecutablesDialog::on_overwriteAppIDBox_toggled(bool checked) @@ -395,7 +479,7 @@ void EditExecutablesDialog::on_buttonBox_rejected() } void EditExecutablesDialog::on_executablesListBox_clicked(const QModelIndex ¤t) -{ +{/* if (current.isValid()) { if (executableChanged()) { @@ -459,7 +543,7 @@ void EditExecutablesDialog::on_executablesListBox_clicked(const QModelIndex &cur bool forcedLibraries = m_Profile->forcedLibrariesEnabled(ui->titleEdit->text()); ui->forceLoadButton->setEnabled(forcedLibraries); ui->forceLoadCheckBox->setChecked(forcedLibraries); - } + }*/ } void EditExecutablesDialog::on_newFilesModCheckBox_toggled(bool checked) diff --git a/src/editexecutablesdialog.h b/src/editexecutablesdialog.h index 7f389b24..bb1538ef 100644 --- a/src/editexecutablesdialog.h +++ b/src/editexecutablesdialog.h @@ -87,7 +87,7 @@ private slots: void on_overwriteAppIDBox_toggled(bool checked); - void on_browseDirButton_clicked(); + void on_browseWorkingDirButton_clicked(); void on_buttonBox_accepted(); void on_buttonBox_rejected(); @@ -113,7 +113,7 @@ private: void updateButtonStates(); private: - Ui::EditExecutablesDialog *ui; + std::unique_ptr ui; QListWidgetItem *m_CurrentItem; @@ -124,6 +124,11 @@ private: QList m_ForcedLibraries; const MOBase::IPluginGame *m_GamePlugin; + + + void updateUI(const Executable* e); + void clearEdits(); + void setEdits(const Executable& e); }; #endif // EDITEXECUTABLESDIALOG_H diff --git a/src/editexecutablesdialog.ui b/src/editexecutablesdialog.ui index 52bbf187..2c9a74f3 100644 --- a/src/editexecutablesdialog.ui +++ b/src/editexecutablesdialog.ui @@ -7,15 +7,9 @@ 0 0 710 - 293 + 348 - - - 200 - 200 - - Modify Executables @@ -77,9 +71,6 @@ Qt::TargetMoveAction - - QAbstractItemView::ExtendedSelection - @@ -163,197 +154,221 @@ 0 - - - 20 - - - - - Title - - - - - - - Name of the executable. This is only for display purposes. - - - Name of the executable. This is only for display purposes. - - - - - - - Binary - - - - - - - - - Binary to run - - - Binary to run - - - - - - - Browse filesystem - - - Browse filesystem for the executable to run. - - - ... - - - - - - - - - Start in - - - - - - - - - - - - ... - - - - - - - - - Arguments - - - - - - - Arguments to pass to the application - - - Arguments to pass to the application - - - - - - - - - - - Allow the Steam AppID to be used for this executable to be changed. - - - Allow the Steam AppID to be used for this executable to be changed. + + + + 10 + + + + + 20 + + + + + Title + + + + + + + Name of the executable. This is only for display purposes. + + + Name of the executable. This is only for display purposes. + + + + + + + Binary + + + + + + + + + Binary to run + + + Binary to run + + + + + + + Browse filesystem + + + Browse filesystem for the executable to run. + + + ... + + + + + + + + + Start in + + + + + + + + + + + + ... + + + + + + + + + Arguments + + + + + + + Arguments to pass to the application + + + Arguments to pass to the application + + + + + + + + + + + Allow the Steam AppID to be used for this executable to be changed. + + + Allow the Steam AppID to be used for this executable to be changed. Every game/tool distributed through Steam has a unique ID. MO needs to know this ID to start those programs directly, otherwise the program is started by steam and then MO will not work. By default, MO will use the AppID for the game. Right now the only case I know of where this needs to be overwritten is for the Skyrim Creation Kit which has its own AppID. This overwrite is already preconfigured. - - - Overwrite Steam AppID - - - - - - - false - - - Steam AppID to use for this executable that differs from the games AppID. - - - Steam AppID to use for this executable that differs from the games AppID. + + + Overwrite Steam AppID + + + + + + + false + + + Steam AppID to use for this executable that differs from the games AppID. + + + Steam AppID to use for this executable that differs from the games AppID. Every game/tool distributed through Steam has a unique ID. MO needs to know this ID to start those programs directly, otherwise the program is started by steam and then MO will not work. By default, MO will use the AppID for the game (usually 72850). Right now the only case I know of where this needs to be overwritten is for the Skyrim Creation Kit which has its own AppID (usually 202480). This overwrite is already preconfigured. - - - - - - - - - - - If this is enabled, new files are created in the specified mod instead of the "Overwrite" mod. - - - Create Files in Mod instead of Overwrite (*) - - - - - - - false - - - - - - - - - - - If this is enabled, the configured libraries will be automatically loaded when this executable is launched. - - - Force Load Libraries (Profile Specific) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - Configure Libraries - - - - + + + + + + + + + + + If this is enabled, new files are created in the specified mod instead of the "Overwrite" mod. + + + Create Files in Mod instead of Overwrite (*) + + + + + + + false + + + + + + + + + + + If this is enabled, the configured libraries will be automatically loaded when this executable is launched. + + + Force Load Libraries (Profile Specific) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + Configure Libraries + + + + + + + + + Use Application's Icon for shortcuts + + + + + - + + + + true + + - Use Application's Icon for shortcuts + This executable is provided by the game plugin + + + Qt::AlignCenter @@ -390,7 +405,7 @@ Right now the only case I know of where this needs to be overwritten is for the binaryEdit browseBinaryButton workingDirEdit - browseDirButton + browseWorkingDirButton overwriteAppIDBox appIDOverwriteEdit newFilesModCheckBox diff --git a/src/executableslist.cpp b/src/executableslist.cpp index d884bdf2..8174eb1b 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -65,8 +65,6 @@ bool ExecutablesList::empty() const void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings) { - addFromPlugin(game); - qDebug("setting up configured executables"); int numCustomExecutables = settings.beginReadArray("customExecutables"); @@ -91,6 +89,8 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings) } settings.endArray(); + + addFromPlugin(game); } void ExecutablesList::store(QSettings& settings) -- cgit v1.3.1 From cd2fefca1928f374c302c275efcc0bbaf36357bb Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 7 Jun 2019 22:24:43 -0400 Subject: save steam app id, custom overwrite and application icon custom overwrite directories now set locally, will be written to profile when closing the dialog --- src/editexecutablesdialog.cpp | 149 +++++++++++++++++++++++++++--------------- src/editexecutablesdialog.h | 6 +- src/executableslist.cpp | 2 + 3 files changed, 100 insertions(+), 57 deletions(-) (limited to 'src/executableslist.cpp') diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index 621c670f..2c376cd1 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -47,16 +47,28 @@ EditExecutablesDialog::EditExecutablesDialog( ui->splitter->setStretchFactor(0, 0); ui->splitter->setStretchFactor(1, 1); - refreshExecutablesWidget(); + for (const auto& e : m_executablesList) { + QString customOverwrite = m_profile->setting("custom_overwrites", e.title()).toString(); + + if (!customOverwrite.isEmpty()) { + m_customOverwrites[e.title()] = customOverwrite; + } + } + + + fillExecutableList(); ui->mods->addItems(modList.allMods()); m_forcedLibraries = m_profile->determineForcedLibraries(ui->title->text()); - // title textbox also has to change the list item, will call save manually - connect(ui->title, &QLineEdit::textChanged, [&](auto&& s){ onTitleChanged(s); }); + // some widgets need to do more than just save() and have their own handler + connect(ui->binary, &QLineEdit::textChanged, [&]{ save(); }); connect(ui->workingDirectory, &QLineEdit::textChanged, [&]{ save(); }); connect(ui->arguments, &QLineEdit::textChanged, [&]{ save(); }); + connect(ui->steamAppID, &QLineEdit::textChanged, [&]{ save(); }); + connect(ui->mods, &QComboBox::currentTextChanged, [&]{ save(); }); + connect(ui->useApplicationIcon, &QCheckBox::toggled, [&]{ save(); }); updateUI(nullptr); } @@ -91,8 +103,27 @@ Executable* EditExecutablesDialog::selectedExe() return &*itor; } +void EditExecutablesDialog::fillExecutableList() +{ + ui->list->clear(); + + for(const auto& exe : m_executablesList) { + QListWidgetItem *newItem = new QListWidgetItem(exe.title()); + + if (!exe.isCustom()) { + auto f = newItem->font(); + f.setItalic(true); + + newItem->setFont(f); + } + + ui->list->addItem(newItem); + } +} + void EditExecutablesDialog::updateUI(const Executable* e) { + // the ui is currently being set, ignore changes m_settingUI = true; if (e) { @@ -103,6 +134,7 @@ void EditExecutablesDialog::updateUI(const Executable* e) ui->remove->setEnabled(false); } + // any changes from now on are from the user m_settingUI = false; } @@ -113,10 +145,13 @@ void EditExecutablesDialog::clearEdits() ui->workingDirectory->clear(); ui->arguments->clear(); ui->overwriteSteamAppID->setChecked(false); + ui->steamAppID->setEnabled(false); ui->steamAppID->clear(); ui->createFilesInMod->setChecked(false); + ui->mods->setEnabled(false); ui->mods->setCurrentIndex(-1); ui->forceLoadLibraries->setChecked(false); + ui->configureLibraries->setEnabled(false); ui->useApplicationIcon->setChecked(false); ui->pluginProvidedLabel->setVisible(false); @@ -129,17 +164,25 @@ void EditExecutablesDialog::setEdits(const Executable& e) ui->workingDirectory->setText(QDir::toNativeSeparators(e.workingDirectory())); ui->arguments->setText(e.arguments()); ui->overwriteSteamAppID->setChecked(!e.steamAppID().isEmpty()); + ui->steamAppID->setEnabled(!e.steamAppID().isEmpty()); ui->steamAppID->setText(e.steamAppID()); ui->useApplicationIcon->setChecked(e.usesOwnIcon()); int modIndex = -1; - QString customOverwrite = m_profile->setting("custom_overwrites", e.title()).toString(); - if (!customOverwrite.isEmpty()) { - modIndex = ui->mods->findText(customOverwrite); + auto itor = m_customOverwrites.find(e.title()); + if (itor != m_customOverwrites.end()) { + modIndex = ui->mods->findText(itor->second); + + if (modIndex == -1) { + qWarning().nospace() + << "executable '" << e.title() << "' uses mod '" << itor->second << "' " + << "as a custom overwrite, but that mod doesn't exist"; + } } ui->createFilesInMod->setChecked(modIndex != -1); + ui->mods->setEnabled(modIndex != -1); ui->mods->setCurrentIndex(modIndex); const bool forcedLibraries = m_profile->forcedLibrariesEnabled(e.title()); @@ -156,19 +199,16 @@ void EditExecutablesDialog::setEdits(const Executable& e) ui->browseWorkingDirectory->setEnabled(e.isCustom()); ui->arguments->setEnabled(e.isCustom()); ui->overwriteSteamAppID->setEnabled(e.isCustom()); - ui->steamAppID->setEnabled(e.isCustom()); ui->useApplicationIcon->setEnabled(e.isCustom()); // always enabled ui->createFilesInMod->setEnabled(true); - ui->mods->setEnabled(true); ui->forceLoadLibraries->setEnabled(true); } void EditExecutablesDialog::save() { if (m_settingUI) { - // the ui is currently being set, ignore changes return; } @@ -180,6 +220,16 @@ void EditExecutablesDialog::save() qDebug().nospace() << "saving '" << e->title() << "'"; + // title may have changed, start with the stuff using it + if (ui->createFilesInMod->isChecked()) { + m_customOverwrites[e->title()] = ui->mods->currentText(); + } else { + auto itor = m_customOverwrites.find(e->title()); + if (itor != m_customOverwrites.end()) { + m_customOverwrites.erase(itor); + } + } + e->title(ui->title->text()); e->binaryInfo(ui->binary->text()); e->workingDirectory(ui->workingDirectory->text()); @@ -192,10 +242,9 @@ void EditExecutablesDialog::save() } } -void EditExecutablesDialog::onTitleChanged(const QString& s) +void EditExecutablesDialog::on_title_textChanged(const QString& s) { if (m_settingUI) { - // the ui is currently being set, ignore changes return; } @@ -210,6 +259,38 @@ void EditExecutablesDialog::onTitleChanged(const QString& s) } } +void EditExecutablesDialog::on_overwriteSteamAppID_toggled(bool checked) +{ + if (m_settingUI) { + return; + } + + ui->steamAppID->setEnabled(checked); + save(); +} + +void EditExecutablesDialog::on_createFilesInMod_toggled(bool checked) +{ + if (m_settingUI) { + return; + } + + ui->mods->setEnabled(checked); + save(); +} + +void EditExecutablesDialog::on_forceLoadLibraries_toggled(bool checked) +{ + if (m_settingUI) { + return; + } + + ui->configureLibraries->setEnabled(ui->forceLoadLibraries->isChecked()); + save(); +} + + + void EditExecutablesDialog::resetInput() { @@ -246,27 +327,6 @@ ExecutablesList EditExecutablesDialog::getExecutablesList() const return newList; } -void EditExecutablesDialog::refreshExecutablesWidget() -{ - ui->list->clear(); - - for(const auto& exe : m_executablesList) { - QListWidgetItem *newItem = new QListWidgetItem(exe.title()); - - if (!exe.isCustom()) { - auto f = newItem->font(); - f.setItalic(true); - - newItem->setFont(f); - } - - ui->list->addItem(newItem); - } - - //ui->addButton->setEnabled(false); - //ui->removeButton->setEnabled(false); -} - void EditExecutablesDialog::updateButtonStates() { @@ -336,11 +396,6 @@ void EditExecutablesDialog::on_configureLibraries_clicked() } } -void EditExecutablesDialog::on_forceLoadLibraries_toggled(bool checked) -{ - ui->configureLibraries->setEnabled(ui->forceLoadLibraries->isChecked()); -} - void EditExecutablesDialog::on_add_clicked() { @@ -349,7 +404,7 @@ void EditExecutablesDialog::on_add_clicked() } resetInput(); - refreshExecutablesWidget(); + //refreshExecutablesWidget(); } void EditExecutablesDialog::on_browseBinary_clicked() @@ -427,7 +482,7 @@ void EditExecutablesDialog::on_remove_clicked() } resetInput(); - refreshExecutablesWidget(); + //refreshExecutablesWidget(); } @@ -486,11 +541,6 @@ void EditExecutablesDialog::on_list_itemSelectionChanged() updateUI(selectedExe()); } -void EditExecutablesDialog::on_overwriteSteamAppID_toggled(bool checked) -{ - ui->steamAppID->setEnabled(checked); -} - void EditExecutablesDialog::on_buttons_accepted() { if (executableChanged()) { @@ -503,7 +553,7 @@ void EditExecutablesDialog::on_buttons_accepted() saveExecutable(); // the executable list returned to callers is generated from the user data in the widgets, // NOT the list we just saved - refreshExecutablesWidget(); + //refreshExecutablesWidget(); } } @@ -582,12 +632,3 @@ void EditExecutablesDialog::on_buttons_rejected() ui->forceLoadCheckBox->setChecked(forcedLibraries); } }*/ - -void EditExecutablesDialog::on_createFilesInMod_toggled(bool checked) -{ - ui->mods->setEnabled(checked); -} - -void EditExecutablesDialog::on_useApplicationIcon_toggled(bool checked) -{ -} diff --git a/src/editexecutablesdialog.h b/src/editexecutablesdialog.h index f28658e3..8ee56e3e 100644 --- a/src/editexecutablesdialog.h +++ b/src/editexecutablesdialog.h @@ -64,10 +64,10 @@ private slots: void on_add_clicked(); void on_remove_clicked(); + void on_title_textChanged(const QString& s); void on_overwriteSteamAppID_toggled(bool checked); void on_createFilesInMod_toggled(bool checked); void on_forceLoadLibraries_toggled(bool checked); - void on_useApplicationIcon_toggled(bool checked); void on_browseBinary_clicked(); void on_browseWorkingDirectory_clicked(); @@ -81,6 +81,7 @@ private slots: private: std::unique_ptr ui; ExecutablesList m_executablesList; + std::map m_customOverwrites; Profile *m_profile; const MOBase::IPluginGame *m_gamePlugin; bool m_settingUI; @@ -92,18 +93,17 @@ private: QListWidgetItem* selectedItem(); Executable* selectedExe(); + void fillExecutableList(); void updateUI(const Executable* e); void clearEdits(); void setEdits(const Executable& e); void save(); void resetInput(); - void refreshExecutablesWidget(); bool executableChanged(); void updateButtonStates(); void saveExecutable(); - void onTitleChanged(const QString& s); }; #endif // EDITEXECUTABLESDIALOG_H diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 8174eb1b..f592a2b7 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -67,6 +67,8 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings) { qDebug("setting up configured executables"); + m_Executables.clear(); + int numCustomExecutables = settings.beginReadArray("customExecutables"); for (int i = 0; i < numCustomExecutables; ++i) { settings.setArrayIndex(i); -- cgit v1.3.1 From 5e65325772ec427c0114dee29043d5cd78131cbc Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sun, 9 Jun 2019 11:43:20 -0400 Subject: fixed plugin executables not overriding if the custom attribute was inadvertently set --- src/executableslist.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/executableslist.cpp') diff --git a/src/executableslist.cpp b/src/executableslist.cpp index f592a2b7..0283a845 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -312,11 +312,11 @@ bool Executable::usesOwnIcon() const void Executable::mergeFrom(const Executable& other) { - // flags on plugin executables that the user is allowed to chnage + // flags on plugin executables that the user is allowed to change const auto allow = ShowInToolbar; - if (!isCustom() && !other.isCustom()) { + if (!other.isCustom()) { // this happens when loading plugin executables in addFromPlugin(), replace // everything in case the plugin has changed -- cgit v1.3.1 From 7671725436551b7254ea89ff6985c5491fcc743d Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 14 Jun 2019 04:30:33 -0400 Subject: removed concept of custom executables, everything is modifiable added apply button to dialog added reset button that re-adds plugin executables and renames existing ones if needed moved executables files to their filter in visual studio --- src/CMakeLists.txt | 11 +-- src/editexecutablesdialog.cpp | 143 ++++++++++++++++++++------------------ src/editexecutablesdialog.h | 9 +-- src/editexecutablesdialog.ui | 37 +++++----- src/executableslist.cpp | 156 ++++++++++++++++++++++++------------------ src/executableslist.h | 24 +++++-- src/mainwindow.cpp | 3 +- src/pch.h | 1 + 8 files changed, 221 insertions(+), 163 deletions(-) (limited to 'src/executableslist.cpp') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5623a851..645a5a73 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -293,7 +293,6 @@ set(core categories shared/directoryentry directoryrefresher - executableslist installationmanager instancemanager loadmechanism @@ -309,7 +308,6 @@ set(dialogs activatemodsdialog categoriesdialog credentialsdialog - editexecutablesdialog filedialogmemory forcedloaddialog forcedloaddialogwidget @@ -333,6 +331,11 @@ set(downloads downloadmanager ) +set(executables + executableslist + editexecutablesdialog +) + set(locking ilockedwaitingforprocess lockeddialog @@ -412,8 +415,8 @@ set(widgets ) set(src_filters - application core browser dialogs downloads locking modinfo modlist plugins - previews profiles settings utilities widgets + application core browser dialogs downloads executables locking modinfo + modlist plugins previews profiles settings utilities widgets ) foreach(filter in list ${src_filters}) diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index 6c0522e4..882bb8b5 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -49,8 +49,9 @@ EditExecutablesDialog::EditExecutablesDialog(OrganizerCore& oc, QWidget* parent) m_customOverwrites.load(m_organizerCore.currentProfile(), m_executablesList); m_forcedLibraries.load(m_organizerCore.currentProfile(), m_executablesList); - fillExecutableList(); + fillList(); ui->mods->addItems(m_organizerCore.modList()->allMods()); + setDirty(false); // some widgets need to do more than just save() and have their own handler connect(ui->binary, &QLineEdit::textChanged, [&]{ save(); }); @@ -59,13 +60,7 @@ EditExecutablesDialog::EditExecutablesDialog(OrganizerCore& oc, QWidget* parent) connect(ui->steamAppID, &QLineEdit::textChanged, [&]{ save(); }); connect(ui->mods, &QComboBox::currentTextChanged, [&]{ save(); }); connect(ui->useApplicationIcon, &QCheckBox::toggled, [&]{ save(); }); - - // select the first one in the list, if any - if (ui->list->count() > 0) { - ui->list->item(0)->setSelected(true); - } else { - updateUI(nullptr, nullptr); - } + connect(ui->list->model(), &QAbstractItemModel::rowsMoved, [&]{ saveOrder(); }); } EditExecutablesDialog::~EditExecutablesDialog() = default; @@ -132,6 +127,15 @@ void EditExecutablesDialog::commitChanges() // set the new executables list m_organizerCore.setExecutablesList(newExecutables); + + setDirty(false); +} + +void EditExecutablesDialog::setDirty(bool b) +{ + if (auto* button=ui->buttons->button(QDialogButtonBox::Apply)) { + button->setEnabled(b); + } } QListWidgetItem* EditExecutablesDialog::selectedItem() @@ -162,26 +166,25 @@ Executable* EditExecutablesDialog::selectedExe() return &*itor; } -void EditExecutablesDialog::fillExecutableList() +void EditExecutablesDialog::fillList() { ui->list->clear(); for(const auto& exe : m_executablesList) { ui->list->addItem(createListItem(exe)); } + + // select the first one in the list, if any + if (ui->list->count() > 0) { + ui->list->item(0)->setSelected(true); + } else { + updateUI(nullptr, nullptr); + } } QListWidgetItem* EditExecutablesDialog::createListItem(const Executable& exe) { - QListWidgetItem *newItem = new QListWidgetItem(exe.title()); - - if (!exe.isCustom()) { - auto f = newItem->font(); - f.setItalic(true); - newItem->setFont(f); - } - - return newItem; + return new QListWidgetItem(exe.title()); } void EditExecutablesDialog::updateUI( @@ -205,14 +208,12 @@ void EditExecutablesDialog::updateUI( void EditExecutablesDialog::setButtons( const QListWidgetItem* item, const Executable* e) { - // add is always enabled + // add and remove are always enabled if (item) { - ui->remove->setEnabled(e->isCustom()); ui->up->setEnabled(canMove(item, -1)); ui->down->setEnabled(canMove(item, +1)); } else { - ui->remove->setEnabled(false); ui->up->setEnabled(false); ui->down->setEnabled(false); } @@ -243,7 +244,6 @@ void EditExecutablesDialog::clearEdits() ui->configureLibraries->setEnabled(false); ui->useApplicationIcon->setEnabled(false); ui->useApplicationIcon->setChecked(false); - ui->pluginProvidedLabel->setVisible(false); } void EditExecutablesDialog::setEdits(const Executable& e) @@ -287,19 +287,15 @@ void EditExecutablesDialog::setEdits(const Executable& e) ui->configureLibraries->setEnabled(hasForcedLibraries); } - ui->pluginProvidedLabel->setVisible(!e.isCustom()); - - // only enabled for custom executables - ui->title->setEnabled(e.isCustom()); - ui->binary->setEnabled(e.isCustom()); - ui->browseBinary->setEnabled(e.isCustom()); - ui->workingDirectory->setEnabled(e.isCustom()); - ui->browseWorkingDirectory->setEnabled(e.isCustom()); - ui->arguments->setEnabled(e.isCustom()); - ui->overwriteSteamAppID->setEnabled(e.isCustom()); - ui->useApplicationIcon->setEnabled(e.isCustom()); - // always enabled + ui->title->setEnabled(true); + ui->binary->setEnabled(true); + ui->browseBinary->setEnabled(true); + ui->workingDirectory->setEnabled(true); + ui->browseWorkingDirectory->setEnabled(true); + ui->arguments->setEnabled(true); + ui->overwriteSteamAppID->setEnabled(true); + ui->useApplicationIcon->setEnabled(true); ui->createFilesInMod->setEnabled(true); ui->forceLoadLibraries->setEnabled(true); } @@ -361,6 +357,14 @@ void EditExecutablesDialog::save() } else { e->flags(e->flags() & (~Executable::UseApplicationIcon)); } + + setDirty(true); +} + +void EditExecutablesDialog::saveOrder() +{ + m_executablesList = getExecutablesList(); + setDirty(true); } bool EditExecutablesDialog::canMove(const QListWidgetItem* item, int direction) @@ -393,6 +397,8 @@ void EditExecutablesDialog::move(QListWidgetItem* item, int direction) ui->list->takeItem(row); ui->list->insertItem(row + (direction > 0 ? 1 : -1), item); item->setSelected(true); + + setDirty(true); } void EditExecutablesDialog::on_list_itemSelectionChanged() @@ -400,22 +406,43 @@ void EditExecutablesDialog::on_list_itemSelectionChanged() updateUI(selectedItem(), selectedExe()); } +void EditExecutablesDialog::on_reset_clicked() +{ + const auto title = tr("Reset plugin executables"); + + const auto text = tr( + "This will restore all the executables provided by the game plugin. If " + "there are existing executables with the same names, they will be " + "automatically renamed and left unchanged."); + + const auto buttons = QMessageBox::Ok | QMessageBox::Cancel; + + if (QMessageBox::question(this, title, text, buttons) != QMessageBox::Ok) { + return; + } + + m_executablesList.resetFromPlugin(m_organizerCore.managedGame()); + fillList(); + + setDirty(true); +} + void EditExecutablesDialog::on_add_clicked() { - auto title = makeNonConflictingTitle(tr("New Executable")); + auto title = m_executablesList.makeNonConflictingTitle(tr("New Executable")); if (!title) { return; } - auto e = Executable() - .title(*title) - .flags(Executable::CustomExecutable); + const Executable e(*title); m_executablesList.setExecutable(e); auto* item = createListItem(e); ui->list->addItem(item); item->setSelected(true); + + setDirty(true); } void EditExecutablesDialog::on_remove_clicked() @@ -453,6 +480,8 @@ void EditExecutablesDialog::on_remove_clicked() } else { ui->list->item(currentRow)->setSelected(true); } + + setDirty(true); } void EditExecutablesDialog::on_up_clicked() @@ -563,7 +592,7 @@ void EditExecutablesDialog::on_browseBinary_clicked() // setting title if currently empty if (ui->title->text().isEmpty()) { const auto prefix = QFileInfo(binaryName).baseName(); - const auto newTitle = makeNonConflictingTitle(prefix); + const auto newTitle = m_executablesList.makeNonConflictingTitle(prefix); if (newTitle) { ui->title->setText(*newTitle); @@ -607,15 +636,16 @@ void EditExecutablesDialog::on_configureLibraries_clicked() } } -void EditExecutablesDialog::on_buttons_accepted() +void EditExecutablesDialog::on_buttons_clicked(QAbstractButton* b) { - commitChanges(); - accept(); -} - -void EditExecutablesDialog::on_buttons_rejected() -{ - reject(); + if (b == ui->buttons->button(QDialogButtonBox::Ok)) { + commitChanges(); + accept(); + } else if (b == ui->buttons->button(QDialogButtonBox::Apply)) { + commitChanges(); + } else { + reject(); + } } void EditExecutablesDialog::setJarBinary(const QString& binaryName) @@ -641,25 +671,6 @@ void EditExecutablesDialog::setJarBinary(const QString& binaryName) save(); } -std::optional EditExecutablesDialog::makeNonConflictingTitle( - const QString& prefix) -{ - QString title = prefix; - - for (int i=1; i<100; ++i) { - if (!m_executablesList.titleExists(title)) { - return title; - } - - title = prefix + QString(" (%1)").arg(i); - } - - qCritical().nospace() - << "ran out of executable titles for prefix '" << prefix << "'"; - - return {}; -} - void CustomOverwrites::load(Profile* p, const ExecutablesList& exes) { diff --git a/src/editexecutablesdialog.h b/src/editexecutablesdialog.h index 10a6166f..4a04ef42 100644 --- a/src/editexecutablesdialog.h +++ b/src/editexecutablesdialog.h @@ -110,6 +110,7 @@ public: private slots: void on_list_itemSelectionChanged(); + void on_reset_clicked(); void on_add_clicked(); void on_remove_clicked(); void on_up_clicked(); @@ -124,8 +125,7 @@ private slots: void on_browseWorkingDirectory_clicked(); void on_configureLibraries_clicked(); - void on_buttons_accepted(); - void on_buttons_rejected(); + void on_buttons_clicked(QAbstractButton* b); private: std::unique_ptr ui; @@ -140,19 +140,20 @@ private: QListWidgetItem* selectedItem(); Executable* selectedExe(); - void fillExecutableList(); + void fillList(); QListWidgetItem* createListItem(const Executable& exe); void updateUI(const QListWidgetItem* item, const Executable* e); void clearEdits(); void setEdits(const Executable& e); void setButtons(const QListWidgetItem* item, const Executable* e); void save(); + void saveOrder(); bool canMove(const QListWidgetItem* item, int direction); void move(QListWidgetItem* item, int direction); void setJarBinary(const QString& binaryName); - std::optional makeNonConflictingTitle(const QString& prefix); bool isTitleConflicting(const QString& s); void commitChanges(); + void setDirty(bool b); }; #endif // EDITEXECUTABLESDIALOG_H diff --git a/src/editexecutablesdialog.ui b/src/editexecutablesdialog.ui index 9b6c8153..a42dbeed 100644 --- a/src/editexecutablesdialog.ui +++ b/src/editexecutablesdialog.ui @@ -168,6 +168,26 @@ + + + + Adds the executables provided by the game plugin and moves any existing executables out of the way + + + Adds the executables provided by the game plugin and moves any existing executables out of the way + + + Adds the executables provided by the game plugin and moves any existing executables out of the way + + + Reset + + + + :/MO/gui/edit_clear:/MO/gui/edit_clear + + + @@ -425,21 +445,6 @@ Right now the only case I know of where this needs to be overwritten is for the - - - - - true - - - - This executable is provided by the game plugin - - - Qt::AlignCenter - - - @@ -463,7 +468,7 @@ Right now the only case I know of where this needs to be overwritten is for the - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 0283a845..daf200a6 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -74,8 +74,6 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings) settings.setArrayIndex(i); Executable::Flags flags; - if (settings.value("custom", true).toBool()) - flags |= Executable::CustomExecutable; if (settings.value("toolbar", false).toBool()) flags |= Executable::ShowInToolbar; if (settings.value("ownicon", false).toBool()) @@ -92,7 +90,7 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings) settings.endArray(); - addFromPlugin(game); + addFromPlugin(game, IgnoreExisting); } void ExecutablesList::store(QSettings& settings) @@ -106,29 +104,33 @@ void ExecutablesList::store(QSettings& settings) settings.setArrayIndex(count++); settings.setValue("title", item.title()); - settings.setValue("custom", item.isCustom()); settings.setValue("toolbar", item.isShownOnToolbar()); settings.setValue("ownicon", item.usesOwnIcon()); - - if (item.isCustom()) { - settings.setValue("binary", item.binaryInfo().absoluteFilePath()); - settings.setValue("arguments", item.arguments()); - settings.setValue("workingDirectory", item.workingDirectory()); - settings.setValue("steamAppID", item.steamAppID()); - } + settings.setValue("binary", item.binaryInfo().absoluteFilePath()); + settings.setValue("arguments", item.arguments()); + settings.setValue("workingDirectory", item.workingDirectory()); + settings.setValue("steamAppID", item.steamAppID()); } settings.endArray(); } -void ExecutablesList::addFromPlugin(IPluginGame const *game) +void ExecutablesList::resetFromPlugin(MOBase::IPluginGame const *game) +{ + qDebug("resetting plugin executables"); + addFromPlugin(game, MoveExisting); +} + +void ExecutablesList::addFromPlugin(IPluginGame const *game, SetFlags flags) { Q_ASSERT(game != nullptr); for (const ExecutableInfo &info : game->executables()) { - if (info.isValid()) { - setExecutable({info, Executable::UseApplicationIcon}); + if (!info.isValid()) { + continue; } + + setExecutable({info, Executable::UseApplicationIcon}, flags); } const QFileInfo eppBin(QCoreApplication::applicationDirPath() + "/explorer++/Explorer++.exe"); @@ -137,12 +139,14 @@ void ExecutablesList::addFromPlugin(IPluginGame const *game) const auto args = QString("\"%1\"") .arg(QDir::toNativeSeparators(game->dataDirectory().absolutePath())); - setExecutable(Executable() + const auto exe = Executable() .title("Explore Virtual Folder") .binaryInfo(eppBin) .arguments(args) .workingDirectory(eppBin.absolutePath()) - .flags(Executable::UseApplicationIcon)); + .flags(Executable::UseApplicationIcon); + + setExecutable(exe, flags); } } @@ -188,28 +192,81 @@ bool ExecutablesList::titleExists(const QString &title) const return std::find_if(m_Executables.begin(), m_Executables.end(), test) != m_Executables.end(); } -void ExecutablesList::setExecutable(const Executable &executable) +void ExecutablesList::setExecutable(const Executable &exe) +{ + setExecutable(exe, MergeExisting); +} + +void ExecutablesList::setExecutable(const Executable &exe, SetFlags flags) { - auto itor = find(executable.title()); + auto itor = find(exe.title()); + + if (itor != end()) { + if (flags == IgnoreExisting) { + return; + } + + if (flags == MoveExisting) { + const auto newTitle = makeNonConflictingTitle(exe.title()); + if (!newTitle) { + qCritical().nospace() + << "executable '" << exe.title() << "' was in the way but could " + << "not be renamed"; + + return; + } + + qWarning().nospace() + << "executable '" << itor->title() << "' was in the way and was " + << "renamed to '" << *newTitle << "'"; + + itor->title(*newTitle); + itor = end(); + } + } if (itor == m_Executables.end()) { - m_Executables.push_back(executable); + m_Executables.push_back(exe); } else { - itor->mergeFrom(executable); + itor->mergeFrom(exe); } } void ExecutablesList::remove(const QString &title) { - for (std::vector::iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) { - if (iter->isCustom() && (iter->title() == title)) { - m_Executables.erase(iter); - break; + auto itor = find(title); + if (itor != m_Executables.end()) { + m_Executables.erase(itor); + } +} + +std::optional ExecutablesList::makeNonConflictingTitle( + const QString& prefix) +{ + const int max = 100; + + QString title = prefix; + + for (int i=1; i. #include "executableinfo.h" #include +#include #include #include @@ -37,14 +38,13 @@ class Executable public: enum Flag { - CustomExecutable = 0x01, ShowInToolbar = 0x02, UseApplicationIcon = 0x04 }; Q_DECLARE_FLAGS(Flags, Flag); - Executable() = default; + Executable(QString title={}); /** * @brief Executable from plugin @@ -65,7 +65,6 @@ public: Executable& workingDirectory(const QString& s); Executable& flags(Flags f); - bool isCustom() const; bool isShownOnToolbar() const; void setShownOnToolbar(bool state); bool usesOwnIcon() const; @@ -106,6 +105,8 @@ public: */ void load(const MOBase::IPluginGame* game, QSettings& settings); + void resetFromPlugin(MOBase::IPluginGame const *game); + /** * @brief writes the current list to the settings */ @@ -166,13 +167,28 @@ public: **/ void remove(const QString &title); + std::optional makeNonConflictingTitle(const QString& prefix); + private: + enum SetFlags + { + IgnoreExisting = 1, + MergeExisting, + MoveExisting + }; + std::vector m_Executables; /** * @brief add the executables preconfigured for this game **/ - void addFromPlugin(MOBase::IPluginGame const *game); + void addFromPlugin(MOBase::IPluginGame const *game, SetFlags flags); + + /** + * @brief add a new executable to the list + * @param executable + */ + void setExecutable(const Executable &exe, SetFlags flags); }; Q_DECLARE_OPERATORS_FOR_FLAGS(Executable::Flags) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 15a6eb62..b5e9c320 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -5513,8 +5513,7 @@ void MainWindow::addAsExecutable() .title(name) .binaryInfo(binaryInfo) .arguments(arguments) - .workingDirectory(targetInfo.absolutePath()) - .flags(Executable::CustomExecutable)); + .workingDirectory(targetInfo.absolutePath())); refreshExecutablesList(); } diff --git a/src/pch.h b/src/pch.h index e86c0da6..1d8df43a 100644 --- a/src/pch.h +++ b/src/pch.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include -- cgit v1.3.1 From d7dc13e3b9ac2932531d9518c9d303cd302e1539 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 14 Jun 2019 21:28:40 -0400 Subject: fixes plugin executables having empty fields when upgrading from 2.2.0 --- src/executableslist.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++----- src/executableslist.h | 21 +++++++++--- 2 files changed, 95 insertions(+), 13 deletions(-) (limited to 'src/executableslist.cpp') diff --git a/src/executableslist.cpp b/src/executableslist.cpp index daf200a6..077d2a93 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -69,6 +69,10 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings) m_Executables.clear(); + // whether the executable list in the .ini is still using the old custom + // executables from 2.2.0, see upgradeFromCustom() + bool needsUpgrade = false; + int numCustomExecutables = settings.beginReadArray("customExecutables"); for (int i = 0; i < numCustomExecutables; ++i) { settings.setArrayIndex(i); @@ -79,6 +83,11 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings) if (settings.value("ownicon", false).toBool()) flags |= Executable::UseApplicationIcon; + if (settings.contains("custom")) { + // the "custom" setting only exists in older versions + needsUpgrade = true; + } + setExecutable(Executable() .title(settings.value("title").toString()) .binaryInfo(settings.value("binary").toString()) @@ -91,6 +100,9 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings) settings.endArray(); addFromPlugin(game, IgnoreExisting); + + if (needsUpgrade) + upgradeFromCustom(game); } void ExecutablesList::store(QSettings& settings) @@ -115,22 +127,19 @@ void ExecutablesList::store(QSettings& settings) settings.endArray(); } -void ExecutablesList::resetFromPlugin(MOBase::IPluginGame const *game) -{ - qDebug("resetting plugin executables"); - addFromPlugin(game, MoveExisting); -} - -void ExecutablesList::addFromPlugin(IPluginGame const *game, SetFlags flags) +std::vector ExecutablesList::getPluginExecutables( + MOBase::IPluginGame const *game) const { Q_ASSERT(game != nullptr); + std::vector v; + for (const ExecutableInfo &info : game->executables()) { if (!info.isValid()) { continue; } - setExecutable({info, Executable::UseApplicationIcon}, flags); + v.push_back({info, Executable::UseApplicationIcon}); } const QFileInfo eppBin(QCoreApplication::applicationDirPath() + "/explorer++/Explorer++.exe"); @@ -146,6 +155,28 @@ void ExecutablesList::addFromPlugin(IPluginGame const *game, SetFlags flags) .workingDirectory(eppBin.absolutePath()) .flags(Executable::UseApplicationIcon); + v.push_back(exe); + } + + return v; +} + +void ExecutablesList::resetFromPlugin(MOBase::IPluginGame const *game) +{ + qDebug("resetting plugin executables"); + + Q_ASSERT(game != nullptr); + + for (const auto& exe : getPluginExecutables(game)) { + setExecutable(exe, MoveExisting); + } +} + +void ExecutablesList::addFromPlugin(IPluginGame const *game, SetFlags flags) +{ + Q_ASSERT(game != nullptr); + + for (const auto& exe : getPluginExecutables(game)) { setExecutable(exe, flags); } } @@ -261,6 +292,46 @@ std::optional ExecutablesList::makeNonConflictingTitle( return {}; } +void ExecutablesList::upgradeFromCustom(MOBase::IPluginGame const *game) +{ + qDebug() << "upgrading executables list"; + + Q_ASSERT(game != nullptr); + + // prior to 2.2.1, plugin executables were special in the sense that they + // did not store certain settings, like the binary info and working directory; + // those were filled in when MO started, but never saved + // + // this interferes with the new executables list, which is completely + // customizable, because plugin executables are only added to the list when + // they don't exist at all and are ignored otherwise, leaving some of the + // fields completely blank + // + // when the "custom" setting is found in the .ini file (see load()), it is + // assumed that the older scheme is still present; in that case, the plugin + // executables force their binary info and working directory into the existing + // executables one last time + // + // from that point on, plugin executables are ignored unless they're + // completely missing from the list, allowing users to customize them as they + // want + + for (const auto& exe : getPluginExecutables(game)) { + auto itor = find(exe.title()); + if (itor == end()){ + continue; + } + + if (!itor->binaryInfo().exists()) { + itor->binaryInfo(exe.binaryInfo()); + } + + if (itor->workingDirectory().isEmpty()) { + itor->workingDirectory(exe.workingDirectory()); + } + } +} + Executable::Executable(QString title) : m_title(title) diff --git a/src/executableslist.h b/src/executableslist.h index 61bf6734..2d1dd28e 100644 --- a/src/executableslist.h +++ b/src/executableslist.h @@ -194,15 +194,26 @@ private: /** - * @brief add the executables preconfigured for this game - **/ + * @brief add the executables preconfigured for this game + **/ void addFromPlugin(MOBase::IPluginGame const *game, SetFlags flags); /** - * @brief add a new executable to the list - * @param executable - */ + * @brief add a new executable to the list + * @param executable + */ void setExecutable(const Executable &exe, SetFlags flags); + + /** + * returns the executables provided by the game plugin + **/ + std::vector getPluginExecutables( + MOBase::IPluginGame const *game) const; + + /** + * called when MO is still using the old custom executables from 2.2.0 + **/ + void upgradeFromCustom(const MOBase::IPluginGame* game); }; Q_DECLARE_OPERATORS_FOR_FLAGS(Executable::Flags) -- cgit v1.3.1