summaryrefslogtreecommitdiff
path: root/src/editexecutablesdialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/editexecutablesdialog.cpp')
-rw-r--r--src/editexecutablesdialog.cpp799
1 files changed, 541 insertions, 258 deletions
diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp
index 177661ff..8929d207 100644
--- a/src/editexecutablesdialog.cpp
+++ b/src/editexecutablesdialog.cpp
@@ -22,394 +22,677 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "filedialogmemory.h"
#include "stackdata.h"
#include "modlist.h"
+#include "forcedloaddialog.h"
+#include "organizercore.h"
+
#include <QMessageBox>
#include <Shellapi.h>
#include <utility.h>
-#include "forcedloaddialog.h"
#include <algorithm>
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);
+ ui->splitter->setSizes({200, 1});
+ ui->splitter->setStretchFactor(0, 0);
+ ui->splitter->setStretchFactor(1, 1);
- refreshExecutablesWidget();
+ loadCustomOverwrites();
+ loadForcedLibraries();
- ui->newFilesModBox->addItems(modList.allMods());
+ ui->mods->addItems(m_organizerCore.modList()->allMods());
+ fillList();
+ setDirty(false);
- m_ForcedLibraries = m_Profile->determineForcedLibraries(ui->titleEdit->text());
+ // some widgets need to do more than just save() and have their own handler
+ connect(ui->binary, &QLineEdit::textChanged, [&]{ save(); });
+ connect(ui->workingDirectory, &QLineEdit::textChanged, [&]{ save(); });
+ connect(ui->arguments, &QLineEdit::textChanged, [&]{ save(); });
+ connect(ui->steamAppID, &QLineEdit::textChanged, [&]{ save(); });
+ connect(ui->mods, &QComboBox::currentTextChanged, [&]{ save(); });
+ connect(ui->useApplicationIcon, &QCheckBox::toggled, [&]{ save(); });
+ connect(ui->list->model(), &QAbstractItemModel::rowsMoved, [&]{ saveOrder(); });
}
-EditExecutablesDialog::~EditExecutablesDialog()
+EditExecutablesDialog::~EditExecutablesDialog() = default;
+
+
+void EditExecutablesDialog::loadCustomOverwrites()
{
- delete ui;
+ const auto* p = m_organizerCore.currentProfile();
+
+ for (const auto& e : m_executablesList) {
+ const auto s = p->setting("custom_overwrites", e.title()).toString();
+
+ if (!s.isEmpty()) {
+ m_customOverwrites.set(e.title(), true, s);
+ }
+ }
}
-ExecutablesList EditExecutablesDialog::getExecutablesList() const
+void EditExecutablesDialog::loadForcedLibraries()
{
- ExecutablesList newList;
- for (int i = 0; i < ui->executablesListBox->count(); ++i) {
- newList.addExecutable(m_ExecutablesList.find(ui->executablesListBox->item(i)->text()));
+ const auto* p = m_organizerCore.currentProfile();
+
+ for (const auto& e : m_executablesList) {
+ if (p->forcedLibrariesEnabled(e.title())) {
+ m_forcedLibraries.set(e.title(), true, p->determineForcedLibraries(e.title()));
+ }
}
- return newList;
}
-void EditExecutablesDialog::refreshExecutablesWidget()
+ExecutablesList EditExecutablesDialog::getExecutablesList() const
{
- ui->executablesListBox->clear();
- std::vector<Executable>::const_iterator current, end;
- m_ExecutablesList.getExecutables(current, end);
+ 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);
- for(; current != end; ++current) {
- QListWidgetItem *newItem = new QListWidgetItem(current->m_Title);
- newItem->setTextColor(current->isCustom() ? QColor(Qt::black) : QColor(Qt::darkGray));
- ui->executablesListBox->addItem(newItem);
+ if (itor == m_executablesList.end()) {
+ qWarning().nospace()
+ << "getExecutablesList(): executable '" << title << "' not found";
+
+ continue;
+ }
+
+ newList.setExecutable(*itor);
}
- ui->addButton->setEnabled(false);
- ui->removeButton->setEnabled(false);
+ return newList;
}
-
-void EditExecutablesDialog::on_binaryEdit_textChanged(const QString &name)
+const EditExecutablesDialog::CustomOverwrites&
+EditExecutablesDialog::getCustomOverwrites() const
{
- updateButtonStates();
+ return m_customOverwrites;
}
-void EditExecutablesDialog::on_workingDirEdit_textChanged(const QString &dir)
+const EditExecutablesDialog::ForcedLibraries&
+EditExecutablesDialog::getForcedLibraries() const
{
- updateButtonStates();
+ return m_forcedLibraries;
}
-void EditExecutablesDialog::updateButtonStates()
+void EditExecutablesDialog::commitChanges()
{
- bool enabled = true;
+ const auto newExecutables = getExecutablesList();
+ auto* profile = m_organizerCore.currentProfile();
- QString filePath(ui->binaryEdit->text());
- QFileInfo fileInfo(filePath);
- if (!fileInfo.exists())
- enabled = false;
- if (!fileInfo.isFile())
- enabled = false;
+ // 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 modName=m_customOverwrites.find(e.title())) {
+ if (modName && modName->enabled) {
+ profile->storeSetting("custom_overwrites", e.title(), modName->value);
+ }
+ }
- QString dirPath(ui->workingDirEdit->text());
- if (!dirPath.isEmpty()) {
- QDir dirInfo(dirPath);
- if (!dirInfo.exists())
- enabled = false;
+ if (auto libraryList=m_forcedLibraries.find(e.title())) {
+ if (libraryList && libraryList->enabled && !libraryList->value.empty()) {
+ profile->setForcedLibrariesEnabled(e.title(), true);
+ profile->storeForcedLibraries(e.title(), libraryList->value);
+ }
+ }
}
- ui->addButton->setEnabled(enabled);
+ // set the new executables list
+ m_organizerCore.setExecutablesList(newExecutables);
+
+ setDirty(false);
}
-void EditExecutablesDialog::resetInput()
+void EditExecutablesDialog::setDirty(bool b)
{
- ui->binaryEdit->setText("");
- ui->titleEdit->setText("");
- ui->workingDirEdit->clear();
- ui->argumentsEdit->setText("");
- ui->appIDOverwriteEdit->clear();
- ui->overwriteAppIDBox->setChecked(false);
- ui->useAppIconCheckBox->setChecked(false);
- ui->newFilesModCheckBox->setChecked(false);
- ui->forceLoadCheckBox->setChecked(false);
- m_CurrentItem = nullptr;
+ if (auto* button=ui->buttons->button(QDialogButtonBox::Apply)) {
+ button->setEnabled(b);
+ }
}
-
-void EditExecutablesDialog::saveExecutable()
+QListWidgetItem* EditExecutablesDialog::selectedItem()
{
- 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);
+ const auto selection = ui->list->selectedItems();
- if (ui->newFilesModCheckBox->isChecked()) {
- m_Profile->storeSetting("custom_overwrites", ui->titleEdit->text(),
- ui->newFilesModBox->currentText());
- }
- else {
- m_Profile->removeSetting("custom_overwrites", ui->titleEdit->text());
+ if (selection.empty()) {
+ return nullptr;
}
- m_Profile->removeForcedLibraries(ui->titleEdit->text());
- m_Profile->storeForcedLibraries(ui->titleEdit->text(), m_ForcedLibraries);
- m_Profile->setForcedLibrariesEnabled(ui->titleEdit->text(), ui->forceLoadCheckBox->isChecked());
+ return selection[0];
}
-
-void EditExecutablesDialog::delayedRefresh()
+Executable* EditExecutablesDialog::selectedExe()
{
- QModelIndex index = ui->executablesListBox->currentIndex();
- resetInput();
- refreshExecutablesWidget();
- on_executablesListBox_clicked(index);
-}
+ auto* item = selectedItem();
+ if (!item) {
+ return nullptr;
+ }
+
+ const auto& title = item->text();
+ auto itor = m_executablesList.find(title);
+ if (itor == m_executablesList.end()) {
+ return nullptr;
+ }
+
+ return &*itor;
+}
-void EditExecutablesDialog::on_forceLoadButton_clicked()
+void EditExecutablesDialog::fillList()
{
- ForcedLoadDialog dialog(m_GamePlugin, this);
- dialog.setValues(m_ForcedLibraries);
- if (dialog.exec() == QDialog::Accepted) {
- m_ForcedLibraries = dialog.values();
+ 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);
}
}
-void EditExecutablesDialog::on_forceLoadCheckBox_toggled()
+QListWidgetItem* EditExecutablesDialog::createListItem(const Executable& exe)
{
- ui->forceLoadButton->setEnabled(ui->forceLoadCheckBox->isChecked());
+ return new QListWidgetItem(exe.title());
}
+void EditExecutablesDialog::updateUI(
+ const QListWidgetItem* item, const Executable* e)
+{
+ // the ui is currently being set, ignore changes
+ m_settingUI = true;
+
+ if (e) {
+ setEdits(*e);
+ } else {
+ clearEdits();
+ }
+
+ setButtons(item, e);
-void EditExecutablesDialog::on_addButton_clicked()
+ // any changes from now on are from the user
+ m_settingUI = false;
+}
+
+void EditExecutablesDialog::setButtons(
+ const QListWidgetItem* item, const Executable* e)
{
- if (executableChanged()) {
- saveExecutable();
+ // add and remove are always enabled
+
+ if (item) {
+ ui->up->setEnabled(canMove(item, -1));
+ ui->down->setEnabled(canMove(item, +1));
+ } else {
+ ui->up->setEnabled(false);
+ ui->down->setEnabled(false);
}
+}
- resetInput();
- refreshExecutablesWidget();
+void EditExecutablesDialog::clearEdits()
+{
+ ui->title->clear();
+ ui->title->setEnabled(false);
+ ui->binary->clear();
+ ui->binary->setEnabled(false);
+ ui->browseBinary->setEnabled(false);
+ ui->workingDirectory->clear();
+ ui->workingDirectory->setEnabled(false);
+ ui->browseWorkingDirectory->setEnabled(false);
+ ui->arguments->clear();
+ ui->arguments->setEnabled(false);
+ ui->overwriteSteamAppID->setEnabled(false);
+ ui->overwriteSteamAppID->setChecked(false);
+ ui->steamAppID->setEnabled(false);
+ ui->steamAppID->clear();
+ ui->createFilesInMod->setEnabled(false);
+ ui->createFilesInMod->setChecked(false);
+ ui->mods->setEnabled(false);
+ ui->mods->setCurrentIndex(-1);
+ ui->forceLoadLibraries->setEnabled(false);
+ ui->forceLoadLibraries->setChecked(false);
+ ui->configureLibraries->setEnabled(false);
+ ui->useApplicationIcon->setEnabled(false);
+ ui->useApplicationIcon->setChecked(false);
}
-void EditExecutablesDialog::on_browseButton_clicked()
+void EditExecutablesDialog::setEdits(const Executable& e)
{
- QString binaryName = FileDialogMemory::getOpenFileName(
- "editExecutableBinary", this, tr("Select a binary"), QString(),
- tr("Executable (%1)").arg("*.exe *.bat *.jar"));
+ ui->title->setText(e.title());
+ ui->binary->setText(QDir::toNativeSeparators(e.binaryInfo().absoluteFilePath()));
+ ui->workingDirectory->setText(QDir::toNativeSeparators(e.workingDirectory()));
+ ui->arguments->setText(e.arguments());
+ ui->overwriteSteamAppID->setChecked(!e.steamAppID().isEmpty());
+ ui->steamAppID->setEnabled(!e.steamAppID().isEmpty());
+ ui->steamAppID->setText(e.steamAppID());
+ ui->useApplicationIcon->setChecked(e.usesOwnIcon());
- if (binaryName.endsWith(".jar", Qt::CaseInsensitive)) {
- QString binaryPath;
- { // try to find java automatically
- std::wstring binaryNameW = ToWString(binaryName);
- WCHAR buffer[MAX_PATH];
- if (::FindExecutableW(binaryNameW.c_str(), nullptr, buffer)
- > reinterpret_cast<HINSTANCE>(32)) {
- DWORD binaryType = 0UL;
- if (!::GetBinaryTypeW(binaryNameW.c_str(), &binaryType)) {
- qDebug("failed to determine binary type of \"%ls\": %lu", binaryNameW.c_str(), ::GetLastError());
- } else if (binaryType == SCS_32BIT_BINARY) {
- binaryPath = ToQString(buffer);
- }
- }
- }
- if (binaryPath.isEmpty()) {
- QSettings javaReg("HKEY_LOCAL_MACHINE\\Software\\JavaSoft\\Java Runtime Environment", QSettings::NativeFormat);
- if (javaReg.contains("CurrentVersion")) {
- QString currentVersion = javaReg.value("CurrentVersion").toString();
- binaryPath = javaReg.value(QString("%1/JavaHome").arg(currentVersion)).toString().append("\\bin\\javaw.exe");
+ {
+ int modIndex = -1;
+
+ const auto modName = m_customOverwrites.find(e.title());
+
+ if (modName && !modName->value.isEmpty()) {
+ modIndex = ui->mods->findText(modName->value);
+
+ if (modIndex == -1) {
+ qWarning().nospace()
+ << "executable '" << e.title() << "' uses mod '" << modName->value << "' "
+ << "as a custom overwrite, but that mod doesn't exist";
}
}
- if (binaryPath.isEmpty()) {
- QMessageBox::information(this, tr("Java (32-bit) required"),
- tr("MO requires 32-bit java to run this application. If you already have it installed, select javaw.exe "
- "from that installation as the binary."));
- } else {
- ui->binaryEdit->setText(binaryPath);
- }
- ui->workingDirEdit->setText(QDir::toNativeSeparators(QFileInfo(binaryName).absolutePath()));
- ui->argumentsEdit->setText("-jar \"" + QDir::toNativeSeparators(binaryName) + "\"");
+ const bool hasCustomOverwrites = (modName && modName->enabled);
+
+ ui->createFilesInMod->setChecked(hasCustomOverwrites);
+ ui->mods->setEnabled(hasCustomOverwrites);
+ ui->mods->setCurrentIndex(modIndex);
+ }
+
+ {
+ const auto libraryList = m_forcedLibraries.find(e.title());
+ const bool hasForcedLibraries = (libraryList && libraryList->enabled);
+
+ ui->forceLoadLibraries->setChecked(hasForcedLibraries);
+ ui->configureLibraries->setEnabled(hasForcedLibraries);
+ }
+
+ // 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);
+}
+
+void EditExecutablesDialog::save()
+{
+ if (m_settingUI) {
+ return;
+ }
+
+ auto* e = selectedExe();
+ if (!e) {
+ qWarning("trying to save but nothing is selected");
+ return;
+ }
+
+ // title may have changed, start with the stuff using it
+
+ // custom overwrites
+ if (ui->createFilesInMod->isChecked()) {
+ m_customOverwrites.set(e->title(), true, ui->mods->currentText());
+ } else {
+ 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)) {
+ newTitle = e->title();
+ }
+
+ 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);
+ }
+
+ e->binaryInfo(ui->binary->text());
+ e->workingDirectory(ui->workingDirectory->text());
+ e->arguments(ui->arguments->text());
+
+ if (ui->overwriteSteamAppID->isChecked()) {
+ e->steamAppID(ui->steamAppID->text());
} else {
- ui->binaryEdit->setText(QDir::toNativeSeparators(binaryName));
+ e->steamAppID("");
}
- if (ui->titleEdit->text().isEmpty()) {
- ui->titleEdit->setText(QFileInfo(binaryName).baseName());
+ if (ui->useApplicationIcon->isChecked()) {
+ e->flags(e->flags() | Executable::UseApplicationIcon);
+ } else {
+ e->flags(e->flags() & (~Executable::UseApplicationIcon));
}
+
+ setDirty(true);
}
-void EditExecutablesDialog::on_browseDirButton_clicked()
+void EditExecutablesDialog::saveOrder()
{
- QString dirName = FileDialogMemory::getExistingDirectory("editExecutableDirectory", this,
- tr("Select a directory"));
+ m_executablesList = getExecutablesList();
+ setDirty(true);
+}
+
+bool EditExecutablesDialog::canMove(const QListWidgetItem* item, int direction)
+{
+ if (!item) {
+ return false;
+ }
+
+ if (direction < 0) {
+ // moving up
+ return (ui->list->row(item) > 0);
- ui->workingDirEdit->setText(dirName);
+ } else if (direction > 0) {
+ // moving down
+ return (ui->list->row(item) < (ui->list->count() - 1));
+ }
+
+ return false;
}
-void EditExecutablesDialog::on_removeButton_clicked()
+void EditExecutablesDialog::move(QListWidgetItem* item, int direction)
{
- if (QMessageBox::question(this, tr("Confirm"), tr("Really remove \"%1\" from executables?").arg(ui->titleEdit->text()),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- m_Profile->removeSetting("custom_overwrites", ui->titleEdit->text());
- m_Profile->removeForcedLibraries(ui->titleEdit->text());
- m_ExecutablesList.remove(ui->titleEdit->text());
+ if (!canMove(item, direction)) {
+ return;
}
- resetInput();
- refreshExecutablesWidget();
+ const auto row = ui->list->row(item);
+
+ // removing item
+ ui->list->takeItem(row);
+ ui->list->insertItem(row + (direction > 0 ? 1 : -1), item);
+ item->setSelected(true);
+
+ setDirty(true);
}
-void EditExecutablesDialog::on_titleEdit_textChanged(const QString &arg1)
+void EditExecutablesDialog::on_list_itemSelectionChanged()
{
- QPushButton *addButton = findChild<QPushButton*>("addButton");
- QPushButton *removeButton = findChild<QPushButton*>("removeButton");
+ updateUI(selectedItem(), selectedExe());
+}
- QListWidget *executablesWidget = findChild<QListWidget*>("executablesListBox");
+void EditExecutablesDialog::on_reset_clicked()
+{
+ const auto title = tr("Reset plugin executables");
- QList<QListWidgetItem*> existingItems = executablesWidget->findItems(arg1, Qt::MatchFixedString);
+ 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.");
- addButton->setEnabled(arg1.length() != 0);
+ const auto buttons = QMessageBox::Ok | QMessageBox::Cancel;
- if (existingItems.count() == 0) {
- addButton->setText(tr("Add"));
- removeButton->setEnabled(false);
- } else {
- // existing item. is it a custom one?
- addButton->setText(tr("Modify"));
- removeButton->setEnabled(true);
+ 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 = m_executablesList.makeNonConflictingTitle(tr("New Executable"));
+ if (!title) {
+ return;
+ }
+
+ const Executable e(*title);
-bool EditExecutablesDialog::executableChanged()
+ m_executablesList.setExecutable(e);
+
+ auto* item = createListItem(e);
+ ui->list->addItem(item);
+ item->setSelected(true);
+
+ setDirty(true);
+}
+
+void EditExecutablesDialog::on_remove_clicked()
{
- if (m_CurrentItem != nullptr) {
- Executable const &selectedExecutable(m_ExecutablesList.find(m_CurrentItem->text()));
+ auto* item = selectedItem();
+ if (!item) {
+ qWarning("trying to remove entry but nothing is selected");
+ return;
+ }
+
+ auto* exe = selectedExe();
+ if (!exe) {
+ qWarning("trying to remove entry but nothing is selected");
+ return;
+ }
+
+ const int currentRow = ui->list->row(item);
+ delete item;
- QString storedCustomOverwrite = m_Profile->setting("custom_overwrites", selectedExecutable.m_Title).toString();
- bool forcedLibrariesDirty = false;
- auto forcedLibaries = m_Profile->determineForcedLibraries(selectedExecutable.m_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->titleEdit->text() + "/enabled", false).toBool() !=
- ui->forceLoadCheckBox->isChecked();
+ m_customOverwrites.remove(exe->title());
+ m_forcedLibraries.remove(exe->title());
- return selectedExecutable.m_Title != ui->titleEdit->text()
- || selectedExecutable.m_Arguments != ui->argumentsEdit->text()
- || selectedExecutable.m_SteamAppID != ui->appIDOverwriteEdit->text()
- || !storedCustomOverwrite.isEmpty() != ui->newFilesModCheckBox->isChecked()
- || !storedCustomOverwrite.isEmpty() && (storedCustomOverwrite != ui->newFilesModBox->currentText())
- || selectedExecutable.m_WorkingDirectory != QDir::fromNativeSeparators(ui->workingDirEdit->text())
- || selectedExecutable.m_BinaryInfo.absoluteFilePath() != QDir::fromNativeSeparators(ui->binaryEdit->text())
- || selectedExecutable.usesOwnIcon() != ui->useAppIconCheckBox->isChecked()
- || forcedLibrariesDirty
- ;
+ // removing from main list, must be done last because it invalidates the
+ // exe pointer
+ m_executablesList.remove(exe->title());
+
+
+ // reselecting the same row as before, or the last one
+ if (currentRow >= ui->list->count()) {
+ // that was the last item, select the new list item, if any
+ if (ui->list->count() > 0) {
+ ui->list->item(ui->list->count() - 1)->setSelected(true);
+ }
} else {
- QFileInfo fileInfo(ui->binaryEdit->text());
- return !ui->binaryEdit->text().isEmpty()
- && !ui->titleEdit->text().isEmpty()
- && fileInfo.exists()
- && fileInfo.isFile();
+ ui->list->item(currentRow)->setSelected(true);
}
+
+ setDirty(true);
}
-void EditExecutablesDialog::on_executablesListBox_itemSelectionChanged()
+
+void EditExecutablesDialog::on_up_clicked()
{
- if (ui->executablesListBox->selectedItems().size() == 0) {
- // deselected
- resetInput();
+ auto* item = selectedItem();
+ if (!item) {
+ return;
}
+
+ move(item, -1);
}
-void EditExecutablesDialog::on_overwriteAppIDBox_toggled(bool checked)
+void EditExecutablesDialog::on_down_clicked()
{
- ui->appIDOverwriteEdit->setEnabled(checked);
+ auto* item = selectedItem();
+ if (!item) {
+ return;
+ }
+
+ move(item, +1);
}
-void EditExecutablesDialog::on_closeButton_clicked()
+bool EditExecutablesDialog::isTitleConflicting(const QString& s)
{
- 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();
+ for (const auto& exe : m_executablesList) {
+ if (exe.title() == s) {
+ if (&exe != selectedExe()) {
+ // found an executable that's not the current one with the same title
+ return true;
+ }
}
}
- this->accept();
+
+ return false;
}
-void EditExecutablesDialog::on_executablesListBox_clicked(const QModelIndex &current)
+void EditExecutablesDialog::on_title_textChanged(const QString& s)
{
- if (current.isValid()) {
+ if (m_settingUI) {
+ return;
+ }
- 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();
+ // don't allow changing the title to something that already exists
+ if (isTitleConflicting(s)) {
+ return;
+ }
- //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;
- }
- }
+ // must save before modifying the item in the list widget because saving
+ // relies on the item's text being the same as an item in m_executablesList
+ save();
+
+ // once the executable is saved, the list item must be changed to match the
+ // new name
+ if (auto* i=selectedItem()) {
+ i->setText(s);
+ }
+}
+
+void EditExecutablesDialog::on_overwriteSteamAppID_toggled(bool checked)
+{
+ if (m_settingUI) {
+ return;
+ }
- ui->executablesListBox->selectionModel()->clearSelection();
- ui->executablesListBox->selectionModel()->select(current, QItemSelectionModel::SelectCurrent);
+ ui->steamAppID->setEnabled(checked);
+ save();
+}
- m_CurrentItem = ui->executablesListBox->item(current.row());
+void EditExecutablesDialog::on_createFilesInMod_toggled(bool checked)
+{
+ if (m_settingUI) {
+ return;
+ }
- Executable const &selectedExecutable(m_ExecutablesList.find(m_CurrentItem->text()));
+ ui->mods->setEnabled(checked);
+ save();
+}
- ui->titleEdit->setText(selectedExecutable.m_Title);
- ui->binaryEdit->setText(QDir::toNativeSeparators(selectedExecutable.m_BinaryInfo.absoluteFilePath()));
- ui->argumentsEdit->setText(selectedExecutable.m_Arguments);
- ui->workingDirEdit->setText(QDir::toNativeSeparators(selectedExecutable.m_WorkingDirectory));
- ui->removeButton->setEnabled(selectedExecutable.isCustom());
- ui->overwriteAppIDBox->setChecked(!selectedExecutable.m_SteamAppID.isEmpty());
- if (!selectedExecutable.m_SteamAppID.isEmpty()) {
- ui->appIDOverwriteEdit->setText(selectedExecutable.m_SteamAppID);
- } else {
- ui->appIDOverwriteEdit->clear();
- }
- ui->useAppIconCheckBox->setChecked(selectedExecutable.usesOwnIcon());
+void EditExecutablesDialog::on_forceLoadLibraries_toggled(bool checked)
+{
+ if (m_settingUI) {
+ return;
+ }
- int index = -1;
+ ui->configureLibraries->setEnabled(ui->forceLoadLibraries->isChecked());
+ save();
+}
- QString customOverwrite = m_Profile->setting("custom_overwrites", selectedExecutable.m_Title).toString();
- if (!customOverwrite.isEmpty()) {
- index = ui->newFilesModBox->findText(customOverwrite);
- qDebug("find %s -> %d", qUtf8Printable(customOverwrite), index);
- }
+void EditExecutablesDialog::on_browseBinary_clicked()
+{
+ const QString binaryName = FileDialogMemory::getOpenFileName(
+ "editExecutableBinary", this, tr("Select a binary"), ui->binary->text(),
+ tr("Executable (%1)").arg("*.exe *.bat *.jar"));
- ui->newFilesModCheckBox->setChecked(index != -1);
- if (index != -1) {
- ui->newFilesModBox->setCurrentIndex(index);
+ if (binaryName.isNull()) {
+ // canceled
+ return;
+ }
+
+ // setting binary
+ if (binaryName.endsWith(".jar", Qt::CaseInsensitive)) {
+ // special case for jar files, uses the system java installation
+ setJarBinary(binaryName);
+ } else {
+ ui->binary->setText(QDir::toNativeSeparators(binaryName));
+ }
+
+ // setting title if currently empty
+ if (ui->title->text().isEmpty()) {
+ const auto prefix = QFileInfo(binaryName).baseName();
+ const auto newTitle = m_executablesList.makeNonConflictingTitle(prefix);
+
+ if (newTitle) {
+ ui->title->setText(*newTitle);
}
+ }
+
+ save();
+}
+
+void EditExecutablesDialog::on_browseWorkingDirectory_clicked()
+{
+ QString dirName = FileDialogMemory::getExistingDirectory(
+ "editExecutableDirectory", this, tr("Select a directory"),
+ ui->workingDirectory->text());
+
+ if (dirName.isNull()) {
+ // canceled
+ return;
+ }
+
+ ui->workingDirectory->setText(dirName);
+}
+
+void EditExecutablesDialog::on_configureLibraries_clicked()
+{
+ auto* e = selectedExe();
+ if (!e) {
+ qWarning("trying to configure libraries but nothing is selected");
+ return;
+ }
+
+ ForcedLoadDialog dialog(m_organizerCore.managedGame(), this);
+
+ if (auto libraryList=m_forcedLibraries.find(e->title())) {
+ dialog.setValues(libraryList->value);
+ }
- m_ForcedLibraries = m_Profile->determineForcedLibraries(ui->titleEdit->text());
- bool forcedLibraries = m_Profile->forcedLibrariesEnabled(ui->titleEdit->text());
- ui->forceLoadButton->setEnabled(forcedLibraries);
- ui->forceLoadCheckBox->setChecked(forcedLibraries);
+ if (dialog.exec() == QDialog::Accepted) {
+ m_forcedLibraries.setValue(e->title(), dialog.values());
+ save();
+ }
+}
+
+void EditExecutablesDialog::on_buttons_clicked(QAbstractButton* b)
+{
+ if (b == ui->buttons->button(QDialogButtonBox::Ok)) {
+ commitChanges();
+ accept();
+ } else if (b == ui->buttons->button(QDialogButtonBox::Apply)) {
+ commitChanges();
+ } else {
+ reject();
}
}
-void EditExecutablesDialog::on_newFilesModCheckBox_toggled(bool checked)
+void EditExecutablesDialog::setJarBinary(const QString& binaryName)
{
- ui->newFilesModBox->setEnabled(checked);
+ auto java = OrganizerCore::findJavaInstallation(binaryName);
+
+ if (java.isEmpty()) {
+ QMessageBox::information(
+ this, tr("Java (32-bit) required"),
+ tr("MO requires 32-bit java to run this application. If you already "
+ "have it installed, select javaw.exe from that installation as "
+ "the binary."));
+ }
+
+ // only save once
+
+ m_settingUI = true;
+ ui->binary->setText(java);
+ ui->workingDirectory->setText(QDir::toNativeSeparators(QFileInfo(binaryName).absolutePath()));
+ ui->arguments->setText("-jar \"" + QDir::toNativeSeparators(binaryName) + "\"");
+ m_settingUI = false;
+
+ save();
}