diff options
| author | Silarn <jrim@rimpo.org> | 2019-07-22 01:00:42 -0500 |
|---|---|---|
| committer | Silarn <jrim@rimpo.org> | 2019-07-22 01:00:42 -0500 |
| commit | dcd6d624672019727d7effd17aac86f72bff438b (patch) | |
| tree | 1e8d3856f657d898c5992631599cf272d785f973 /src/editexecutablesdialog.cpp | |
| parent | 179a73857125ee604f42b0d5c2d765183c86d2c7 (diff) | |
| parent | e73c309f08eff98f0dbd2590f594a83b67431eac (diff) | |
Merge branch 'Develop'
Diffstat (limited to 'src/editexecutablesdialog.cpp')
| -rw-r--r-- | src/editexecutablesdialog.cpp | 799 |
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 ¤t) +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(); } |
