summaryrefslogtreecommitdiff
path: root/src/editexecutablesdialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/editexecutablesdialog.cpp')
-rw-r--r--src/editexecutablesdialog.cpp256
1 files changed, 191 insertions, 65 deletions
diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp
index 8929d207..1c804a7c 100644
--- a/src/editexecutablesdialog.cpp
+++ b/src/editexecutablesdialog.cpp
@@ -24,6 +24,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "modlist.h"
#include "forcedloaddialog.h"
#include "organizercore.h"
+#include "spawn.h"
#include <QMessageBox>
#include <Shellapi.h>
@@ -33,7 +34,29 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
using namespace MOBase;
using namespace MOShared;
-EditExecutablesDialog::EditExecutablesDialog(OrganizerCore& oc, QWidget* parent)
+class IgnoreChanges
+{
+public:
+ IgnoreChanges(EditExecutablesDialog* d)
+ : m_dialog(d)
+ {
+ m_dialog->m_settingUI = true;
+ }
+
+ ~IgnoreChanges()
+ {
+ m_dialog->m_settingUI = false;
+ }
+
+ IgnoreChanges(const IgnoreChanges&) = delete;
+ IgnoreChanges& operator=(const IgnoreChanges&) = delete;
+
+private:
+ EditExecutablesDialog* m_dialog;
+};
+
+
+EditExecutablesDialog::EditExecutablesDialog(OrganizerCore& oc, int sel, QWidget* parent)
: TutorableDialog("EditExecutables", parent)
, ui(new Ui::EditExecutablesDialog)
, m_organizerCore(oc)
@@ -49,10 +72,25 @@ EditExecutablesDialog::EditExecutablesDialog(OrganizerCore& oc, QWidget* parent)
loadCustomOverwrites();
loadForcedLibraries();
- ui->mods->addItems(m_organizerCore.modList()->allMods());
+ for (auto&& m : m_organizerCore.modList()->allMods()) {
+ if (ModInfo::isRegularName(m)) {
+ ui->mods->addItem(m);
+ }
+ }
+
fillList();
setDirty(false);
+ if (sel >= 0 && sel < ui->list->count()) {
+ selectIndex(sel);
+ }
+
+ auto* m = new QMenu;
+ m->addAction(tr("Add from file..."), [&]{ addFromFile(); });
+ m->addAction(tr("Add empty"), [&]{ addEmpty(); });
+ m->addAction(tr("Clone selected"), [&]{ clone(); });
+ ui->add->setMenu(m);
+
// 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(); });
@@ -60,11 +98,17 @@ EditExecutablesDialog::EditExecutablesDialog(OrganizerCore& oc, QWidget* parent)
connect(ui->steamAppID, &QLineEdit::textChanged, [&]{ save(); });
connect(ui->mods, &QComboBox::currentTextChanged, [&]{ save(); });
connect(ui->useApplicationIcon, &QCheckBox::toggled, [&]{ save(); });
+ connect(ui->hide, &QCheckBox::toggled, [&]{ save(); });
connect(ui->list->model(), &QAbstractItemModel::rowsMoved, [&]{ saveOrder(); });
}
EditExecutablesDialog::~EditExecutablesDialog() = default;
+int EditExecutablesDialog::exec()
+{
+ GeometrySaver gs(Settings::instance(), this);
+ return QDialog::exec();
+}
void EditExecutablesDialog::loadCustomOverwrites()
{
@@ -101,9 +145,7 @@ ExecutablesList EditExecutablesDialog::getExecutablesList() const
auto itor = m_executablesList.find(title);
if (itor == m_executablesList.end()) {
- qWarning().nospace()
- << "getExecutablesList(): executable '" << title << "' not found";
-
+ log::warn("getExecutablesList(): executable '{}' not found", title);
continue;
}
@@ -165,6 +207,14 @@ void EditExecutablesDialog::setDirty(bool b)
}
}
+void EditExecutablesDialog::selectIndex(int i)
+{
+ if (i >= 0 && i < ui->list->count()) {
+ ui->list->selectionModel()->setCurrentIndex(
+ ui->list->model()->index(i, 0), QItemSelectionModel::ClearAndSelect);
+ }
+}
+
QListWidgetItem* EditExecutablesDialog::selectedItem()
{
const auto selection = ui->list->selectedItems();
@@ -203,7 +253,7 @@ void EditExecutablesDialog::fillList()
// select the first one in the list, if any
if (ui->list->count() > 0) {
- ui->list->item(0)->setSelected(true);
+ selectIndex(0);
} else {
updateUI(nullptr, nullptr);
}
@@ -218,7 +268,7 @@ void EditExecutablesDialog::updateUI(
const QListWidgetItem* item, const Executable* e)
{
// the ui is currently being set, ignore changes
- m_settingUI = true;
+ IgnoreChanges c(this);
if (e) {
setEdits(*e);
@@ -227,9 +277,6 @@ void EditExecutablesDialog::updateUI(
}
setButtons(item, e);
-
- // any changes from now on are from the user
- m_settingUI = false;
}
void EditExecutablesDialog::setButtons(
@@ -271,18 +318,25 @@ void EditExecutablesDialog::clearEdits()
ui->configureLibraries->setEnabled(false);
ui->useApplicationIcon->setEnabled(false);
ui->useApplicationIcon->setChecked(false);
+ ui->hide->setEnabled(false);
+ ui->hide->setChecked(false);
+
+ m_lastGoodTitle = "";
}
void EditExecutablesDialog::setEdits(const Executable& e)
{
ui->title->setText(e.title());
- ui->binary->setText(QDir::toNativeSeparators(e.binaryInfo().absoluteFilePath()));
+ ui->binary->setText(QDir::toNativeSeparators(e.binaryInfo().filePath()));
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());
+ ui->hide->setChecked(e.hide());
+
+ m_lastGoodTitle = e.title();
{
int modIndex = -1;
@@ -293,9 +347,10 @@ void EditExecutablesDialog::setEdits(const Executable& e)
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";
+ log::warn(
+ "executable '{}' uses mod '{}' as a custom overwrite, but that mod "
+ "doesn't exist",
+ e.title(), modName->value);
}
}
@@ -325,6 +380,7 @@ void EditExecutablesDialog::setEdits(const Executable& e)
ui->useApplicationIcon->setEnabled(true);
ui->createFilesInMod->setEnabled(true);
ui->forceLoadLibraries->setEnabled(true);
+ ui->hide->setEnabled(true);
}
void EditExecutablesDialog::save()
@@ -335,7 +391,7 @@ void EditExecutablesDialog::save()
auto* e = selectedExe();
if (!e) {
- qWarning("trying to save but nothing is selected");
+ log::warn("trying to save but nothing is selected");
return;
}
@@ -353,7 +409,7 @@ void EditExecutablesDialog::save()
// get the new title, but ignore it if it's conflicting with an already
// existing executable
- QString newTitle = ui->title->text();
+ QString newTitle = ui->title->text().trimmed();
if (isTitleConflicting(newTitle)) {
newTitle = e->title();
}
@@ -384,6 +440,12 @@ void EditExecutablesDialog::save()
e->flags(e->flags() & (~Executable::UseApplicationIcon));
}
+ if (ui->hide->isChecked()) {
+ e->flags(e->flags() | Executable::Hide);
+ } else {
+ e->flags(e->flags() & (~Executable::Hide));
+ }
+
setDirty(true);
}
@@ -417,13 +479,14 @@ void EditExecutablesDialog::move(QListWidgetItem* item, int direction)
return;
}
- const auto row = ui->list->row(item);
+ const auto oldRow = ui->list->row(item);
+ const auto newRow = oldRow + (direction > 0 ? 1 : -1);
// removing item
- ui->list->takeItem(row);
- ui->list->insertItem(row + (direction > 0 ? 1 : -1), item);
- item->setSelected(true);
+ ui->list->takeItem(oldRow);
+ ui->list->insertItem(newRow, item);
+ selectIndex(newRow);
setDirty(true);
}
@@ -455,33 +518,20 @@ void EditExecutablesDialog::on_reset_clicked()
void EditExecutablesDialog::on_add_clicked()
{
- auto title = m_executablesList.makeNonConflictingTitle(tr("New Executable"));
- if (!title) {
- return;
- }
-
- const Executable e(*title);
-
- m_executablesList.setExecutable(e);
-
- auto* item = createListItem(e);
- ui->list->addItem(item);
- item->setSelected(true);
-
- setDirty(true);
+ addFromFile();
}
void EditExecutablesDialog::on_remove_clicked()
{
auto* item = selectedItem();
if (!item) {
- qWarning("trying to remove entry but nothing is selected");
+ log::warn("trying to remove entry but nothing is selected");
return;
}
auto* exe = selectedExe();
if (!exe) {
- qWarning("trying to remove entry but nothing is selected");
+ log::warn("trying to remove entry but nothing is selected");
return;
}
@@ -501,10 +551,10 @@ void EditExecutablesDialog::on_remove_clicked()
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);
+ selectIndex(ui->list->count() - 1);
}
} else {
- ui->list->item(currentRow)->setSelected(true);
+ selectIndex(currentRow);
}
setDirty(true);
@@ -544,17 +594,26 @@ bool EditExecutablesDialog::isTitleConflicting(const QString& s)
return false;
}
-void EditExecutablesDialog::on_title_textChanged(const QString& s)
+void EditExecutablesDialog::on_title_textChanged(const QString& original)
{
if (m_settingUI) {
return;
}
- // don't allow changing the title to something that already exists
+ auto s = original.trimmed();
+
+ // disallow empty names
+ if (s.isEmpty()) {
+ return;
+ }
+
+ // disallow changing the title to something that already exists
if (isTitleConflicting(s)) {
return;
}
+ m_lastGoodTitle = s;
+
// 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();
@@ -566,6 +625,11 @@ void EditExecutablesDialog::on_title_textChanged(const QString& s)
}
}
+void EditExecutablesDialog::on_title_editingFinished()
+{
+ ui->title->setText(m_lastGoodTitle);
+}
+
void EditExecutablesDialog::on_overwriteSteamAppID_toggled(bool checked)
{
if (m_settingUI) {
@@ -598,34 +662,78 @@ void EditExecutablesDialog::on_forceLoadLibraries_toggled(bool checked)
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"));
+ const auto binaryName = browseBinary(ui->binary->text());
+ if (binaryName.fileName().isEmpty()) {
+ return;
+ }
+
+ setBinary(binaryName);
+ save();
+}
- if (binaryName.isNull()) {
- // canceled
+void EditExecutablesDialog::addFromFile()
+{
+ const auto binary = browseBinary(ui->binary->text());
+ if (binary.fileName().isEmpty()) {
return;
}
+ addNew(Executable(binary.completeBaseName()));
+ setBinary(binary);
+}
+
+void EditExecutablesDialog::addEmpty()
+{
+ addNew(Executable(tr("New Executable")));
+}
+
+void EditExecutablesDialog::clone()
+{
+ auto* e = selectedExe();
+ if (!e) {
+ return;
+ }
+
+ addNew(*e);
+}
+
+void EditExecutablesDialog::addNew(Executable e)
+{
+ const auto fixedTitle = m_executablesList.makeNonConflictingTitle(e.title());
+ if (!fixedTitle) {
+ return;
+ }
+
+ e.title(*fixedTitle);
+
+ m_executablesList.setExecutable(e);
+
+ auto* item = createListItem(e);
+ ui->list->addItem(item);
+
+ selectIndex(ui->list->count() - 1);
+ setDirty(true);
+}
+
+void EditExecutablesDialog::setBinary(const QFileInfo& binary)
+{
// setting binary
- if (binaryName.endsWith(".jar", Qt::CaseInsensitive)) {
+ if (binary.suffix().compare("jar", Qt::CaseInsensitive) == 0) {
// special case for jar files, uses the system java installation
- setJarBinary(binaryName);
+ setJarBinary(binary);
} else {
- ui->binary->setText(QDir::toNativeSeparators(binaryName));
+ ui->binary->setText(QDir::toNativeSeparators(binary.absoluteFilePath()));
}
- // setting title if currently empty
- if (ui->title->text().isEmpty()) {
- const auto prefix = QFileInfo(binaryName).baseName();
+ // setting title if some variation of "New Executable"
+ if (ui->title->text().startsWith(tr("New Executable"), Qt::CaseInsensitive)) {
+ const auto prefix = binary.completeBaseName();
const auto newTitle = m_executablesList.makeNonConflictingTitle(prefix);
if (newTitle) {
ui->title->setText(*newTitle);
}
}
-
- save();
}
void EditExecutablesDialog::on_browseWorkingDirectory_clicked()
@@ -635,7 +743,7 @@ void EditExecutablesDialog::on_browseWorkingDirectory_clicked()
ui->workingDirectory->text());
if (dirName.isNull()) {
- // canceled
+ // cancelled
return;
}
@@ -646,7 +754,7 @@ void EditExecutablesDialog::on_configureLibraries_clicked()
{
auto* e = selectedExe();
if (!e) {
- qWarning("trying to configure libraries but nothing is selected");
+ log::warn("trying to configure libraries but nothing is selected");
return;
}
@@ -674,25 +782,43 @@ void EditExecutablesDialog::on_buttons_clicked(QAbstractButton* b)
}
}
-void EditExecutablesDialog::setJarBinary(const QString& binaryName)
+QFileInfo EditExecutablesDialog::browseBinary(const QString& initial)
{
- auto java = OrganizerCore::findJavaInstallation(binaryName);
+ const QString Filters =
+ tr("Executables (*.exe *.bat *.jar)") + ";;" +
+ tr("All Files (*.*)");
+
+ const auto f = FileDialogMemory::getOpenFileName(
+ "editExecutableBinary", this, tr("Select an executable"),
+ initial, Filters);
+
+ if (f.isNull()) {
+ return {};
+ }
+
+ return QFileInfo(f);
+}
+
+void EditExecutablesDialog::setJarBinary(const QFileInfo& binary)
+{
+ auto java = spawn::findJavaInstallation(binary.absoluteFilePath());
if (java.isEmpty()) {
QMessageBox::information(
- this, tr("Java (32-bit) required"),
- tr("MO requires 32-bit java to run this application. If you already "
+ this, tr("Java required"),
+ tr("MO requires Java to run this application. If you already "
"have it installed, select javaw.exe from that installation as "
"the binary."));
}
- // only save once
+ {
+ // only save once
+ IgnoreChanges c(this);
- 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;
+ ui->binary->setText(java);
+ ui->workingDirectory->setText(QDir::toNativeSeparators(binary.absolutePath()));
+ ui->arguments->setText("-jar \"" + QDir::toNativeSeparators(binary.absoluteFilePath()) + "\"");
+ }
save();
}