/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see .
*/
#include "editexecutablesdialog.h"
#include "ui_editexecutablesdialog.h"
#include "filedialogmemory.h"
#include "stackdata.h"
#include
#include
#include
using namespace MOBase;
using namespace MOShared;
EditExecutablesDialog::EditExecutablesDialog(const ExecutablesList &executablesList, QWidget *parent)
: TutorableDialog("EditExecutables", parent),
ui(new Ui::EditExecutablesDialog), m_CurrentItem(nullptr), m_ExecutablesList(executablesList)
{
ui->setupUi(this);
refreshExecutablesWidget();
}
EditExecutablesDialog::~EditExecutablesDialog()
{
delete ui;
}
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()));
}
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->m_Title);
newItem->setTextColor((current->m_Flags & Executable::CustomExecutable) ? QColor(Qt::black)
: QColor(Qt::darkGray));
ui->executablesListBox->addItem(newItem);
}
ui->addButton->setEnabled(false);
ui->removeButton->setEnabled(false);
}
void EditExecutablesDialog::on_binaryEdit_textChanged(const QString &arg1)
{
QFileInfo fileInfo(arg1);
ui->addButton->setEnabled(fileInfo.exists() && fileInfo.isFile());
}
void EditExecutablesDialog::resetInput()
{
ui->binaryEdit->setText("");
ui->titleEdit->setText("");
ui->workingDirEdit->clear();
ui->argumentsEdit->setText("");
ui->appIDOverwriteEdit->clear();
ui->overwriteAppIDBox->setChecked(false);
ui->closeCheckBox->setChecked(false);
ui->useAppIconCheckBox->setChecked(false);
m_CurrentItem = nullptr;
}
void EditExecutablesDialog::saveExecutable()
{
m_ExecutablesList.addExecutable(ui->titleEdit->text(),
QDir::fromNativeSeparators(ui->binaryEdit->text()),
ui->argumentsEdit->text(),
QDir::fromNativeSeparators(ui->workingDirEdit->text()),
(ui->closeCheckBox->checkState() == Qt::Checked) ?
ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE
: ExecutableInfo::CloseMOStyle::DEFAULT_STAY,
ui->overwriteAppIDBox->isChecked() ?
ui->appIDOverwriteEdit->text() : "",
ui->useAppIconCheckBox->isChecked() ?
Executable::UseApplicationIcon : Executable::Flags());
}
void EditExecutablesDialog::delayedRefresh()
{
int index = ui->executablesListBox->currentIndex().row();
resetInput();
refreshExecutablesWidget();
ui->executablesListBox->setCurrentRow(index);
}
void EditExecutablesDialog::on_addButton_clicked()
{
saveExecutable();
resetInput();
refreshExecutablesWidget();
}
void EditExecutablesDialog::on_browseButton_clicked()
{
QString binaryName = FileDialogMemory::getOpenFileName("editExecutableBinary", this,
tr("Select a binary"), QString(), tr("Executable (%1)").arg("*.exe *.bat *.jar"));
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) > (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");
}
}
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) + "\"");
} else {
ui->binaryEdit->setText(QDir::toNativeSeparators(binaryName));
}
}
void EditExecutablesDialog::on_browseDirButton_clicked()
{
QString dirName = FileDialogMemory::getExistingDirectory("editExecutableDirectory", this,
tr("Select a directory"));
ui->workingDirEdit->setText(dirName);
}
void EditExecutablesDialog::on_removeButton_clicked()
{
if (QMessageBox::question(this, tr("Confirm"), tr("Really remove \"%1\" from executables?").arg(ui->titleEdit->text()),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
m_ExecutablesList.remove(ui->titleEdit->text());
}
resetInput();
refreshExecutablesWidget();
}
void EditExecutablesDialog::on_titleEdit_textChanged(const QString &arg1)
{
QPushButton *addButton = findChild("addButton");
QPushButton *removeButton = findChild("removeButton");
QListWidget *executablesWidget = findChild("executablesListBox");
QList existingItems = executablesWidget->findItems(arg1, Qt::MatchFixedString);
addButton->setEnabled(arg1.length() != 0);
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);
}
}
bool EditExecutablesDialog::executableChanged()
{
if (m_CurrentItem != nullptr) {
Executable const &selectedExecutable(m_ExecutablesList.find(m_CurrentItem->text()));
return selectedExecutable.m_Arguments != ui->argumentsEdit->text()
|| selectedExecutable.m_SteamAppID != ui->appIDOverwriteEdit->text()
|| selectedExecutable.m_WorkingDirectory != QDir::fromNativeSeparators(ui->workingDirEdit->text())
|| selectedExecutable.m_BinaryInfo.absoluteFilePath() != QDir::fromNativeSeparators(ui->binaryEdit->text())
|| (selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE) != ui->closeCheckBox->isChecked()
|| selectedExecutable.usesOwnIcon() != ui->useAppIconCheckBox->isChecked();
} else {
return false;
}
}
void EditExecutablesDialog::on_executablesListBox_itemSelectionChanged()
{
if (ui->executablesListBox->selectedItems().size() == 0) {
// deselected
resetInput();
}
}
void EditExecutablesDialog::on_overwriteAppIDBox_toggled(bool checked)
{
ui->appIDOverwriteEdit->setEnabled(checked);
}
void EditExecutablesDialog::on_closeButton_clicked()
{
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();
}
}
this->accept();
}
void EditExecutablesDialog::on_executablesListBox_clicked(const QModelIndex ¤t)
{
if (current.isValid()) {
ui->executablesListBox->selectionModel()->clearSelection();
ui->executablesListBox->selectionModel()->select(current, QItemSelectionModel::SelectCurrent);
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) {
// this invalidates the item passed as a a parameter
saveExecutable();
QTimer::singleShot(50, this, SLOT(delayedRefresh()));
return;
}
}
m_CurrentItem = ui->executablesListBox->item(current.row());
Executable const &selectedExecutable(m_ExecutablesList.find(m_CurrentItem->text()));
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->closeCheckBox->setChecked(selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE);
if (selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::NEVER_CLOSE) {
ui->closeCheckBox->setEnabled(false);
ui->closeCheckBox->setToolTip(tr("MO must be kept running or this application will not work correctly."));
} else {
ui->closeCheckBox->setEnabled(true);
ui->closeCheckBox->setToolTip(tr("If checked, MO will be closed once the specified executable is run."));
}
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());
}
}