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/mainwindow.cpp | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 205ab7cc..38b2ed3f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -741,7 +741,7 @@ void MainWindow::updatePinnedExecutables() hasLinks = true; QAction *exeAction = new QAction( - iconForExecutable(iter->m_BinaryInfo.filePath()), iter->m_Title); + iconForExecutable(iter->binaryInfo().filePath()), iter->title()); exeAction->setObjectName(QString("custom__") + iter->m_Title); exeAction->setStatusTip(iter->m_BinaryInfo.filePath()); @@ -1506,17 +1506,17 @@ 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.m_Title).toString(); - auto forcedLibraries = m_OrganizerCore.currentProfile()->determineForcedLibraries(selectedExecutable.m_Title); - if (!m_OrganizerCore.currentProfile()->forcedLibrariesEnabled(selectedExecutable.m_Title)) { + 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.m_BinaryInfo, selectedExecutable.m_Arguments, - selectedExecutable.m_WorkingDirectory.length() != 0 - ? selectedExecutable.m_WorkingDirectory - : selectedExecutable.m_BinaryInfo.absolutePath(), - selectedExecutable.m_SteamAppID, + selectedExecutable.binaryInfo(), selectedExecutable.arguments(), + selectedExecutable.workingDirectory().length() != 0 + ? selectedExecutable.workingDirectory() + : selectedExecutable.binaryInfo().absolutePath(), + selectedExecutable.steamAppID(), customOverwrite, forcedLibraries); } else { @@ -1792,8 +1792,8 @@ void MainWindow::refreshExecutablesList() std::vector::const_iterator current, end; m_OrganizerCore.executablesList()->getExecutables(current, end); for(int i = 0; current != end; ++current, ++i) { - QIcon icon = iconForExecutable(current->m_BinaryInfo.filePath()); - executablesList->addItem(icon, current->m_Title); + QIcon icon = iconForExecutable(current->binaryInfo().filePath()); + executablesList->addItem(icon, current->title()); model->setData(model->index(i, 0), QSize(0, executablesList->iconSize().height() + 4), Qt::SizeHintRole); } @@ -2359,17 +2359,17 @@ void MainWindow::on_startButton_clicked() { ui->startButton->setEnabled(false); try { const Executable &selectedExecutable(getSelectedExecutable()); - QString customOverwrite = m_OrganizerCore.currentProfile()->setting("custom_overwrites", selectedExecutable.m_Title).toString(); - auto forcedLibraries = m_OrganizerCore.currentProfile()->determineForcedLibraries(selectedExecutable.m_Title); - if (!m_OrganizerCore.currentProfile()->forcedLibrariesEnabled(selectedExecutable.m_Title)) { + 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.m_BinaryInfo, selectedExecutable.m_Arguments, - selectedExecutable.m_WorkingDirectory.length() != 0 - ? selectedExecutable.m_WorkingDirectory - : selectedExecutable.m_BinaryInfo.absolutePath(), - selectedExecutable.m_SteamAppID, + selectedExecutable.binaryInfo(), selectedExecutable.arguments(), + selectedExecutable.workingDirectory().length() != 0 + ? selectedExecutable.workingDirectory() + : selectedExecutable.binaryInfo().absolutePath(), + selectedExecutable.steamAppID(), customOverwrite, forcedLibraries); } catch (...) { @@ -5204,7 +5204,7 @@ void MainWindow::on_savegameList_customContextMenuRequested(const QPoint &pos) void MainWindow::linkToolbar() { Executable &exe(getSelectedExecutable()); - exe.showOnToolbar(!exe.isShownOnToolbar()); + exe.setShownOnToolbar(!exe.isShownOnToolbar()); ui->linkButton->menu()->actions().at(static_cast(ShortcutType::Toolbar))->setIcon(exe.isShownOnToolbar() ? QIcon(":/MO/gui/remove") : QIcon(":/MO/gui/link")); updatePinnedExecutables(); } @@ -5212,7 +5212,7 @@ void MainWindow::linkToolbar() namespace { QString getLinkfile(const QString &dir, const Executable &exec) { - return QDir::fromNativeSeparators(dir) + "/" + exec.m_Title + ".lnk"; + return QDir::fromNativeSeparators(dir) + "/" + exec.title() + ".lnk"; } QString getDesktopLinkfile(const Executable &exec) @@ -5241,12 +5241,12 @@ void MainWindow::addWindowsLink(const ShortcutType mapping) } else { QFileInfo const exeInfo(qApp->applicationFilePath()); // create link - QString executable = QDir::toNativeSeparators(selectedExecutable.m_BinaryInfo.absoluteFilePath()); + QString executable = QDir::toNativeSeparators(selectedExecutable.binaryInfo().absoluteFilePath()); std::wstring targetFile = ToWString(exeInfo.absoluteFilePath()); std::wstring parameter = ToWString( - QString("\"moshortcut://%1:%2\"").arg(InstanceManager::instance().currentInstance(),selectedExecutable.m_Title)); - std::wstring description = ToWString(QString("Run %1 with ModOrganizer").arg(selectedExecutable.m_Title)); + QString("\"moshortcut://%1:%2\"").arg(InstanceManager::instance().currentInstance(),selectedExecutable.title())); + std::wstring description = ToWString(QString("Run %1 with ModOrganizer").arg(selectedExecutable.title())); std::wstring iconFile = ToWString(executable); std::wstring currentDirectory = ToWString(QDir::toNativeSeparators(qApp->applicationDirPath())); @@ -6391,7 +6391,7 @@ void MainWindow::removeFromToolbar() { try { Executable &exe = m_OrganizerCore.executablesList()->find(m_ContextAction->text()); - exe.showOnToolbar(false); + exe.setShownOnToolbar(false); } catch (const std::runtime_error&) { qDebug("executable doesn't exist any more"); } -- 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/mainwindow.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 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/mainwindow.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 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/mainwindow.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 626045511160b9d44a4ffd29f6dce11f5db6096b Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sun, 9 Jun 2019 10:37:08 -0400 Subject: removed old, unused stuff have mainwindow save all the new settings once the dialog closes --- src/editexecutablesdialog.cpp | 281 ++++++++---------------------------------- src/editexecutablesdialog.h | 13 +- src/mainwindow.cpp | 38 +++++- 3 files changed, 86 insertions(+), 246 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index 6f63416d..28a6b148 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -63,11 +63,49 @@ EditExecutablesDialog::EditExecutablesDialog( connect(ui->mods, &QComboBox::currentTextChanged, [&]{ save(); }); connect(ui->useApplicationIcon, &QCheckBox::toggled, [&]{ save(); }); - updateUI(nullptr); + // select the first one in the list, if any + if (ui->list->count() > 0) { + ui->list->item(0)->setSelected(true); + } else { + updateUI(nullptr); + } } EditExecutablesDialog::~EditExecutablesDialog() = default; +ExecutablesList EditExecutablesDialog::getExecutablesList() const +{ + ExecutablesList newList; + + // make sure the executables are in the same order as in the list + for (int i = 0; i < ui->list->count(); ++i) { + const auto& title = ui->list->item(i)->text(); + + auto itor = m_executablesList.find(title); + + if (itor == m_executablesList.end()) { + qWarning().nospace() + << "getExecutablesList(): executable '" << title << "' not found"; + + continue; + } + + newList.setExecutable(*itor); + } + + return newList; +} + +const CustomOverwrites& EditExecutablesDialog::getCustomOverwrites() const +{ + return m_customOverwrites; +} + +const ForcedLibraries& EditExecutablesDialog::getForcedLibraries() const +{ + return m_forcedLibraries; +} + QListWidgetItem* EditExecutablesDialog::selectedItem() { const auto selection = ui->list->selectedItems(); @@ -429,6 +467,16 @@ void EditExecutablesDialog::on_configureLibraries_clicked() } } +void EditExecutablesDialog::on_buttons_accepted() +{ + accept(); +} + +void EditExecutablesDialog::on_buttons_rejected() +{ + reject(); +} + void EditExecutablesDialog::setJarBinary(const QString& binaryName) { auto java = OrganizerCore::findJavaInstallation(binaryName); @@ -471,237 +519,6 @@ QString EditExecutablesDialog::newExecutableTitle() } - -ExecutablesList EditExecutablesDialog::getExecutablesList() const -{ - ExecutablesList newList; - for (int i = 0; i < ui->list->count(); ++i) { - const auto& title = ui->list->item(i)->text(); - auto itor = m_executablesList.find(title); - - if (itor == m_executablesList.end()) { - qWarning().nospace() - << "getExecutablesList(): executable '" << title << "' not found"; - - continue; - } - - newList.setExecutable(*itor); - } - - return newList; -} - - -void EditExecutablesDialog::updateButtonStates() -{ - bool enabled = true; - - QString filePath(ui->binary->text()); - QFileInfo fileInfo(filePath); - if (!fileInfo.exists()) - enabled = false; - if (!fileInfo.isFile()) - enabled = false; - - QString dirPath(ui->workingDirectory->text()); - if (!dirPath.isEmpty()) { - QDir dirInfo(dirPath); - if (!dirInfo.exists()) - enabled = false; - } - - //ui->addButton->setEnabled(enabled); -} - - -void EditExecutablesDialog::saveExecutable() -{ - Executable::Flags flags = Executable::CustomExecutable; - if (ui->useApplicationIcon->isChecked()) - flags |= Executable::UseApplicationIcon; - - m_executablesList.setExecutable(Executable() - .title(ui->title->text()) - .binaryInfo(QDir::fromNativeSeparators(ui->binary->text())) - .arguments(ui->arguments->text()) - .steamAppID(ui->overwriteSteamAppID->isChecked() ? ui->steamAppID->text() : "") - .workingDirectory(QDir::fromNativeSeparators(ui->workingDirectory->text())) - .flags(flags)); - - if (ui->createFilesInMod->isChecked()) { - m_profile->storeSetting("custom_overwrites", ui->title->text(), - ui->mods->currentText()); - } - else { - m_profile->removeSetting("custom_overwrites", ui->title->text()); - } - - //m_profile->removeForcedLibraries(ui->title->text()); - //m_profile->storeForcedLibraries(ui->title->text(), m_forcedLibraries); - //m_profile->setForcedLibrariesEnabled(ui->title->text(), ui->forceLoadLibraries->isChecked()); -} - - -void EditExecutablesDialog::delayedRefresh() -{ - /*QModelIndex index = ui->executablesListBox->currentIndex(); - resetInput(); - refreshExecutablesWidget(); - on_executablesListBox_clicked(index);*/ -} - - - - - - - -bool EditExecutablesDialog::executableChanged() -{ - /*if (m_currentItem != nullptr) { - 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(); - - bool forcedLibrariesDirty = false; - auto forcedLibaries = m_profile->determineForcedLibraries(selectedExecutable.title()); - forcedLibrariesDirty |= !std::equal(forcedLibaries.begin(), forcedLibaries.end(), - m_forcedLibraries.begin(), m_forcedLibraries.end(), - [](const ExecutableForcedLoadSetting &lhs, const ExecutableForcedLoadSetting &rhs) - { - return lhs.enabled() == rhs.enabled() && - lhs.forced() == rhs.forced() && - lhs.library() == rhs.library() && - lhs.process() == rhs.process(); - }); - forcedLibrariesDirty |= m_profile->setting("forced_libraries", ui->title->text() + "/enabled", false).toBool() != - ui->forceLoadLibraries->isChecked(); - - return selectedExecutable.title() != ui->title->text() - || selectedExecutable.arguments() != ui->arguments->text() - || selectedExecutable.steamAppID() != ui->steamAppID->text() - || !storedCustomOverwrite.isEmpty() != ui->createFilesInMod->isChecked() - || !storedCustomOverwrite.isEmpty() && (storedCustomOverwrite != ui->mods->currentText()) - || selectedExecutable.workingDirectory() != QDir::fromNativeSeparators(ui->workingDirectory->text()) - || selectedExecutable.binaryInfo().absoluteFilePath() != QDir::fromNativeSeparators(ui->binary->text()) - || selectedExecutable.usesOwnIcon() != ui->useApplicationIcon->isChecked() - || forcedLibrariesDirty - ; - } else { - QFileInfo fileInfo(ui->binary->text()); - return !ui->binary->text().isEmpty() - && !ui->title->text().isEmpty() - && fileInfo.exists() - && fileInfo.isFile(); - }*/ - - return false; -} - -void EditExecutablesDialog::on_buttons_accepted() -{ - if (executableChanged()) { - QMessageBox::StandardButton res = QMessageBox::question(this, tr("Save Changes?"), - tr("You made changes to the current executable, do you want to save them?"), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - if (res == QMessageBox::Cancel) { - return; - } else if (res == QMessageBox::Yes) { - saveExecutable(); - // the executable list returned to callers is generated from the user data in the widgets, - // NOT the list we just saved - //refreshExecutablesWidget(); - } - } - - accept(); -} - -void EditExecutablesDialog::on_buttons_rejected() -{ - reject(); -} - -/*void EditExecutablesDialog::on_executablesListBox_clicked(const QModelIndex ¤t) -{ - if (current.isValid()) { - - if (executableChanged()) { - QMessageBox::StandardButton res = QMessageBox::question(this, tr("Save Changes?"), - tr("You made changes to the current executable, do you want to save them?"), - QMessageBox::Yes | QMessageBox::No); - if (res == QMessageBox::Yes) { - saveExecutable(); - - //This is necessary if we're adding a new item, but it doesn't look very nice. - //Ideally we'd end up with the correct row displayed - ui->executablesListBox->selectionModel()->clearSelection(); - ui->executablesListBox->selectionModel()->select(current, QItemSelectionModel::SelectCurrent); - QTimer::singleShot(50, this, SLOT(delayedRefresh())); - return; - } - } - - ui->executablesListBox->selectionModel()->clearSelection(); - ui->executablesListBox->selectionModel()->select(current, QItemSelectionModel::SelectCurrent); - - m_CurrentItem = ui->executablesListBox->item(current.row()); - - 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())); - ui->argumentsEdit->setText(selectedExecutable.arguments()); - ui->workingDirEdit->setText(QDir::toNativeSeparators(selectedExecutable.workingDirectory())); - ui->removeButton->setEnabled(selectedExecutable.isCustom()); - ui->overwriteAppIDBox->setChecked(!selectedExecutable.steamAppID().isEmpty()); - if (!selectedExecutable.steamAppID().isEmpty()) { - ui->appIDOverwriteEdit->setText(selectedExecutable.steamAppID()); - } else { - ui->appIDOverwriteEdit->clear(); - } - ui->useAppIconCheckBox->setChecked(selectedExecutable.usesOwnIcon()); - - int index = -1; - - QString customOverwrite = m_Profile->setting("custom_overwrites", selectedExecutable.title()).toString(); - if (!customOverwrite.isEmpty()) { - index = ui->newFilesModBox->findText(customOverwrite); - qDebug("find %s -> %d", qUtf8Printable(customOverwrite), index); - } - - ui->newFilesModCheckBox->setChecked(index != -1); - if (index != -1) { - ui->newFilesModBox->setCurrentIndex(index); - } - - m_ForcedLibraries = m_Profile->determineForcedLibraries(ui->titleEdit->text()); - bool forcedLibraries = m_Profile->forcedLibrariesEnabled(ui->titleEdit->text()); - ui->forceLoadButton->setEnabled(forcedLibraries); - ui->forceLoadCheckBox->setChecked(forcedLibraries); - } -}*/ - - void CustomOverwrites::load(Profile* p, const ExecutablesList& exes) { for (const auto& e : exes) { diff --git a/src/editexecutablesdialog.h b/src/editexecutablesdialog.h index f8382915..5199537c 100644 --- a/src/editexecutablesdialog.h +++ b/src/editexecutablesdialog.h @@ -91,11 +91,9 @@ public: ~EditExecutablesDialog(); - /** - * @brief retrieve the updated list of executables - * @return updated list of executables - **/ ExecutablesList getExecutablesList() const; + const CustomOverwrites& getCustomOverwrites() const; + const ForcedLibraries& getForcedLibraries() const; private slots: void on_list_itemSelectionChanged(); @@ -115,8 +113,6 @@ private slots: void on_buttons_accepted(); void on_buttons_rejected(); - void delayedRefresh(); - private: std::unique_ptr ui; ExecutablesList m_executablesList; @@ -140,11 +136,6 @@ private: void save(); void setJarBinary(const QString& binaryName); QString newExecutableTitle(); - - bool executableChanged(); - void updateButtonStates(); - void saveExecutable(); - }; #endif // EDITEXECUTABLESDIALOG_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 267a2971..05417f51 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2479,24 +2479,56 @@ static HRESULT CreateShortcut(LPCWSTR targetFileName, LPCWSTR arguments, bool MainWindow::modifyExecutablesDialog() { bool result = false; + try { - EditExecutablesDialog dialog(*m_OrganizerCore.executablesList(), + const auto oldExecutables = *m_OrganizerCore.executablesList(); + auto* profile = m_OrganizerCore.currentProfile(); + + EditExecutablesDialog dialog(oldExecutables, *m_OrganizerCore.modList(), - m_OrganizerCore.currentProfile(), + profile, m_OrganizerCore.managedGame(), this); QSettings &settings = m_OrganizerCore.settings().directInterface(); QString key = QString("geometry/%1").arg(dialog.objectName()); + if (settings.contains(key)) { dialog.restoreGeometry(settings.value(key).toByteArray()); } + if (dialog.exec() == QDialog::Accepted) { - m_OrganizerCore.setExecutablesList(dialog.getExecutablesList()); + const auto newExecutables = dialog.getExecutablesList(); + + // remove all the custom overwrites and forced libraries + for (const auto& e : oldExecutables) { + profile->removeSetting("custom_overwrites", e.title()); + profile->removeForcedLibraries(e.title()); + } + + // set the new custom overwrites and forced libraries + for (const auto& e : newExecutables) { + if (auto modName=dialog.getCustomOverwrites().find(e.title())) { + profile->storeSetting("custom_overwrites", e.title(), *modName); + } + + if (auto list=dialog.getForcedLibraries().find(e.title())) { + if (!list->empty()) { + profile->setForcedLibrariesEnabled(e.title(), true); + profile->storeForcedLibraries(e.title(), *list); + } + } + } + + // set the new executables list + m_OrganizerCore.setExecutablesList(newExecutables); + result = true; } + settings.setValue(key, dialog.saveGeometry()); refreshExecutablesList(); + updatePinnedExecutables(); } catch (const std::exception &e) { reportError(e.what()); } -- cgit v1.3.1 From e86224ee7ffdb18b7c7d17bc2c5cef2457665103 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sun, 9 Jun 2019 11:38:44 -0400 Subject: moved commiting changes to EditExecutablesDialog itself instead of doing it from the main window use a separate enabled state for custom overwrites and forced libraries, this remembers the values even when unchecking the checkbox, as long as the dialog stays opened pass the whole OrganizerCore to EditExecutablesDialog, simplifies a bunch of things --- src/editexecutablesdialog.cpp | 147 ++++++++++++++++++++++++++++++++---------- src/editexecutablesdialog.h | 39 +++++++---- src/mainwindow.cpp | 36 +---------- 3 files changed, 139 insertions(+), 83 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index 102ac4d5..cb6ec6e8 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -33,15 +33,12 @@ along with Mod Organizer. If not, see . using namespace MOBase; using namespace MOShared; -EditExecutablesDialog::EditExecutablesDialog( - const ExecutablesList &executablesList, const ModList &modList, - Profile *profile, const IPluginGame *game, QWidget *parent) +EditExecutablesDialog::EditExecutablesDialog(OrganizerCore& oc, QWidget* parent) : TutorableDialog("EditExecutables", parent) , ui(new Ui::EditExecutablesDialog) - , m_currentItem(nullptr) - , m_executablesList(executablesList) - , m_profile(profile) - , m_gamePlugin(game) + , m_organizerCore(oc) + , m_originalExecutables(*oc.executablesList()) + , m_executablesList(*oc.executablesList()) , m_settingUI(false) { ui->setupUi(this); @@ -49,11 +46,11 @@ EditExecutablesDialog::EditExecutablesDialog( ui->splitter->setStretchFactor(0, 0); ui->splitter->setStretchFactor(1, 1); - m_customOverwrites.load(profile, m_executablesList); - m_forcedLibraries.load(profile, m_executablesList); + m_customOverwrites.load(m_organizerCore.currentProfile(), m_executablesList); + m_forcedLibraries.load(m_organizerCore.currentProfile(), m_executablesList); fillExecutableList(); - ui->mods->addItems(modList.allMods()); + ui->mods->addItems(m_organizerCore.modList()->allMods()); // some widgets need to do more than just save() and have their own handler connect(ui->binary, &QLineEdit::textChanged, [&]{ save(); }); @@ -106,6 +103,37 @@ const ForcedLibraries& EditExecutablesDialog::getForcedLibraries() const return m_forcedLibraries; } +void EditExecutablesDialog::commitChanges() +{ + const auto newExecutables = getExecutablesList(); + auto* profile = m_organizerCore.currentProfile(); + + // remove all the custom overwrites and forced libraries + for (const auto& e : m_originalExecutables) { + profile->removeSetting("custom_overwrites", e.title()); + profile->removeForcedLibraries(e.title()); + } + + // set the new custom overwrites and forced libraries + for (const auto& e : newExecutables) { + if (auto info=m_customOverwrites.find(e.title())) { + if (info && info->enabled) { + profile->storeSetting("custom_overwrites", e.title(), info->modName); + } + } + + if (auto info=m_forcedLibraries.find(e.title())) { + if (info && info->enabled && !info->list.empty()) { + profile->setForcedLibrariesEnabled(e.title(), true); + profile->storeForcedLibraries(e.title(), info->list); + } + } + } + + // set the new executables list + m_organizerCore.setExecutablesList(newExecutables); +} + QListWidgetItem* EditExecutablesDialog::selectedItem() { const auto selection = ui->list->selectedItems(); @@ -215,23 +243,28 @@ void EditExecutablesDialog::setEdits(const Executable& e) { int modIndex = -1; - if (const auto mod=m_customOverwrites.find(e.title())) { - modIndex = ui->mods->findText(*mod); + const auto info = m_customOverwrites.find(e.title()); + + if (info && !info->modName.isEmpty()) { + modIndex = ui->mods->findText(info->modName); if (modIndex == -1) { qWarning().nospace() - << "executable '" << e.title() << "' uses mod '" << *mod << "' " + << "executable '" << e.title() << "' uses mod '" << info->modName << "' " << "as a custom overwrite, but that mod doesn't exist"; } } - ui->createFilesInMod->setChecked(modIndex != -1); - ui->mods->setEnabled(modIndex != -1); + const bool hasCustomOverwrites = (info && info->enabled); + + ui->createFilesInMod->setChecked(hasCustomOverwrites); + ui->mods->setEnabled(hasCustomOverwrites); ui->mods->setCurrentIndex(modIndex); } { - const auto hasForcedLibraries = m_forcedLibraries.find(e.title()).has_value(); + const auto info = m_forcedLibraries.find(e.title()); + const bool hasForcedLibraries = (info && info->enabled); ui->forceLoadLibraries->setChecked(hasForcedLibraries); ui->configureLibraries->setEnabled(hasForcedLibraries); @@ -269,25 +302,32 @@ void EditExecutablesDialog::save() qDebug().nospace() << "saving '" << e->title() << "'"; // title may have changed, start with the stuff using it + + // custom overwrites if (ui->createFilesInMod->isChecked()) { - m_customOverwrites.set(e->title(), ui->mods->currentText()); + m_customOverwrites.setEnabled(e->title(), true); + m_customOverwrites.setMod(e->title(), ui->mods->currentText()); } else { - m_customOverwrites.remove(e->title()); + m_customOverwrites.setEnabled(e->title(), false); } + // forced libraries + m_forcedLibraries.setEnabled(e->title(), ui->forceLoadLibraries->isChecked()); + + // get the new title, but ignore it if it's conflicting with an already + // existing executable QString newTitle = ui->title->text(); if (isTitleConflicting(newTitle)) { - // don't save conflicting titles newTitle = e->title(); } - // forced libraries are saved in on_configureLibraries_clicked() - - // now rename both the custom overwrites and forced libraries if the title - // is being changed if (e->title() != newTitle) { + // now rename both the custom overwrites and forced libraries if the title + // is being changed m_customOverwrites.rename(e->title(), newTitle); m_forcedLibraries.rename(e->title(), newTitle); + + // save the new title e->title(newTitle); } @@ -485,20 +525,21 @@ void EditExecutablesDialog::on_configureLibraries_clicked() return; } - ForcedLoadDialog dialog(m_gamePlugin, this); + ForcedLoadDialog dialog(m_organizerCore.managedGame(), this); - if (auto list=m_forcedLibraries.find(e->title())) { - dialog.setValues(*list); + if (auto info=m_forcedLibraries.find(e->title())) { + dialog.setValues(info->list); } if (dialog.exec() == QDialog::Accepted) { - m_forcedLibraries.set(e->title(), dialog.values()); + m_forcedLibraries.setList(e->title(), dialog.values()); save(); } } void EditExecutablesDialog::on_buttons_accepted() { + commitChanges(); accept(); } @@ -556,12 +597,13 @@ void CustomOverwrites::load(Profile* p, const ExecutablesList& exes) const auto s = p->setting("custom_overwrites", e.title()).toString(); if (!s.isEmpty()) { - m_map[e.title()] = s; + m_map[e.title()] = {true, s}; } } } -std::optional CustomOverwrites::find(const QString& title) const +std::optional CustomOverwrites::find( + const QString& title) const { auto itor = m_map.find(title); if (itor == m_map.end()) { @@ -571,9 +613,26 @@ std::optional CustomOverwrites::find(const QString& title) const return itor->second; } -void CustomOverwrites::set(const QString& title, const QString& mod) +void CustomOverwrites::setEnabled(const QString& title, bool b) { - m_map[title] = mod; + auto itor = m_map.find(title); + + if (itor == m_map.end()) { + m_map[title] = {b, {}}; + } else { + itor->second.enabled = b; + } +} + +void CustomOverwrites::setMod(const QString& title, const QString& mod) +{ + auto itor = m_map.find(title); + + if (itor == m_map.end()) { + m_map[title] = {true, mod}; + } else { + itor->second.modName = mod; + } } void CustomOverwrites::rename(const QString& oldTitle, const QString& newTitle) @@ -602,12 +661,13 @@ void ForcedLibraries::load(Profile* p, const ExecutablesList& exes) { for (const auto& e : exes) { if (p->forcedLibrariesEnabled(e.title())) { - m_map[e.title()] = p->determineForcedLibraries(e.title()); + m_map[e.title()] = {true, p->determineForcedLibraries(e.title())}; } } } -std::optional ForcedLibraries::find(const QString& title) const +std::optional ForcedLibraries::find( + const QString& title) const { auto itor = m_map.find(title); if (itor == m_map.end()) { @@ -617,9 +677,26 @@ std::optional ForcedLibraries::find(const QString& t return itor->second; } -void ForcedLibraries::set(const QString& title, const list_type& mod) +void ForcedLibraries::setEnabled(const QString& title, bool b) +{ + auto itor = m_map.find(title); + + if (itor == m_map.end()) { + m_map[title] = {b, {}}; + } else { + itor->second.enabled = b; + } +} + +void ForcedLibraries::setList(const QString& title, const list_type& list) { - m_map[title] = mod; + auto itor = m_map.find(title); + + if (itor == m_map.end()) { + m_map[title] = {true, list}; + } else { + itor->second.list = list; + } } void ForcedLibraries::rename(const QString& oldTitle, const QString& newTitle) diff --git a/src/editexecutablesdialog.h b/src/editexecutablesdialog.h index 6e006ae2..4957ebff 100644 --- a/src/editexecutablesdialog.h +++ b/src/editexecutablesdialog.h @@ -34,7 +34,7 @@ namespace Ui { } class ModList; - +class OrganizerCore; /** helper class to manage custom overwrites within the edit executables * dialog @@ -42,15 +42,22 @@ class ModList; class CustomOverwrites { public: + struct Info + { + bool enabled; + QString modName; + }; + void load(Profile* p, const ExecutablesList& exes); - std::optional find(const QString& title) const; + std::optional find(const QString& title) const; - void set(const QString& title, const QString& mod); + void setEnabled(const QString& title, bool b); + void setMod(const QString& title, const QString& mod); void rename(const QString& oldTitle, const QString& newTitle); void remove(const QString& title); private: - std::map m_map; + std::map m_map; }; @@ -61,15 +68,22 @@ class ForcedLibraries public: using list_type = QList; + struct Info + { + bool enabled; + list_type list; + }; + void load(Profile* p, const ExecutablesList& exes); - std::optional find(const QString& title) const; + std::optional find(const QString& title) const; - void set(const QString& title, const list_type& list); + void setEnabled(const QString& title, bool b); + void setList(const QString& title, const list_type& list); void rename(const QString& oldTitle, const QString& newTitle); void remove(const QString& title); private: - std::map m_map; + std::map m_map; }; @@ -85,9 +99,7 @@ public: * @param executablesList current list of executables * @param parent parent widget **/ - explicit EditExecutablesDialog( - const ExecutablesList &executablesList, const ModList &modList, - Profile *profile, const MOBase::IPluginGame *game, QWidget *parent = 0); + explicit EditExecutablesDialog(OrganizerCore& oc, QWidget* parent=nullptr); ~EditExecutablesDialog(); @@ -115,15 +127,13 @@ private slots: private: std::unique_ptr ui; + OrganizerCore& m_organizerCore; + const ExecutablesList m_originalExecutables; ExecutablesList m_executablesList; CustomOverwrites m_customOverwrites; ForcedLibraries m_forcedLibraries; - Profile *m_profile; - const MOBase::IPluginGame *m_gamePlugin; bool m_settingUI; - QListWidgetItem *m_currentItem; - QListWidgetItem* selectedItem(); Executable* selectedExe(); @@ -137,6 +147,7 @@ private: void setJarBinary(const QString& binaryName); std::optional makeNonConflictingTitle(const QString& prefix); bool isTitleConflicting(const QString& s); + void commitChanges(); }; #endif // EDITEXECUTABLESDIALOG_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 05417f51..15a6eb62 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2482,13 +2482,8 @@ bool MainWindow::modifyExecutablesDialog() try { const auto oldExecutables = *m_OrganizerCore.executablesList(); - auto* profile = m_OrganizerCore.currentProfile(); - EditExecutablesDialog dialog(oldExecutables, - *m_OrganizerCore.modList(), - profile, - m_OrganizerCore.managedGame(), - this); + EditExecutablesDialog dialog(m_OrganizerCore, this); QSettings &settings = m_OrganizerCore.settings().directInterface(); QString key = QString("geometry/%1").arg(dialog.objectName()); @@ -2497,34 +2492,7 @@ bool MainWindow::modifyExecutablesDialog() dialog.restoreGeometry(settings.value(key).toByteArray()); } - if (dialog.exec() == QDialog::Accepted) { - const auto newExecutables = dialog.getExecutablesList(); - - // remove all the custom overwrites and forced libraries - for (const auto& e : oldExecutables) { - profile->removeSetting("custom_overwrites", e.title()); - profile->removeForcedLibraries(e.title()); - } - - // set the new custom overwrites and forced libraries - for (const auto& e : newExecutables) { - if (auto modName=dialog.getCustomOverwrites().find(e.title())) { - profile->storeSetting("custom_overwrites", e.title(), *modName); - } - - if (auto list=dialog.getForcedLibraries().find(e.title())) { - if (!list->empty()) { - profile->setForcedLibrariesEnabled(e.title(), true); - profile->storeForcedLibraries(e.title(), *list); - } - } - } - - // set the new executables list - m_OrganizerCore.setExecutablesList(newExecutables); - - result = true; - } + result = (dialog.exec() == QDialog::Accepted); settings.setValue(key, dialog.saveGeometry()); refreshExecutablesList(); -- 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/mainwindow.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 30ce0ba5ef5256f42b36d6f4194bf444941ad66d Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 15 Jun 2019 14:48:59 -0400 Subject: rebase to statusbar --- src/mainwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b5e9c320..4ba5e6ad 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -740,8 +740,8 @@ void MainWindow::updatePinnedExecutables() QAction *exeAction = new QAction( iconForExecutable(exe.binaryInfo().filePath()), exe.title()); - exeAction->setObjectName(QString("custom__") + iter->m_Title); - exeAction->setStatusTip(iter->m_BinaryInfo.filePath()); + exeAction->setObjectName(QString("custom__") + exe.title()); + exeAction->setStatusTip(exe.binaryInfo().filePath()); if (!connect(exeAction, SIGNAL(triggered()), this, SLOT(startExeAction()))) { qDebug("failed to connect trigger?"); -- cgit v1.3.1