/*
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 .
*/
#ifndef EDITEXECUTABLESDIALOG_H
#define EDITEXECUTABLESDIALOG_H
#include "executableslist.h"
#include "iplugingame.h"
#include "profile.h"
#include "tutorabledialog.h"
#include
#include
#include
#include
namespace Ui
{
class EditExecutablesDialog;
}
class ModList;
class OrganizerCore;
/** helper class to manage custom overwrites within the edit executables
* dialog, stores a T and a bool in map indexed by a QString
**/
template
class ToggableMap
{
public:
struct Value
{
bool enabled;
T value;
Value(bool b, T&& v) : enabled(b), value(std::forward(v)) {}
};
/**
* returns the Value associated with the given title, or empty
**/
std::optional find(const QString& title) const
{
auto itor = m_map.find(title);
if (itor == m_map.end()) {
return {};
}
return itor->second;
}
/**
* sets the given value, adds it if not found
**/
void set(QString title, bool b, T value)
{
m_map.insert_or_assign(std::move(title), Value(b, std::move(value)));
}
/**
* sets whether the given value is enabled, inserts it if not found
**/
void setEnabled(const QString& title, bool b)
{
auto itor = m_map.find(title);
if (itor == m_map.end()) {
m_map.emplace(title, Value(b, {}));
} else {
itor->second.enabled = b;
}
}
/**
* sets the given value, inserts it enabled if not found
**/
void setValue(const QString& title, T value)
{
auto itor = m_map.find(title);
if (itor == m_map.end()) {
m_map.emplace(title, Value(true, std::move(value)));
} else {
itor->second.value = std::move(value);
}
}
/**
* renames the given value, ignored if not found
**/
void rename(const QString& oldTitle, QString newTitle)
{
auto itor = m_map.find(oldTitle);
if (itor == m_map.end()) {
return;
}
// move to new title, erase old
m_map.emplace(std::move(newTitle), std::move(itor->second));
m_map.erase(itor);
}
/**
* removes the given value, ignored if not found
**/
void remove(const QString& title)
{
auto itor = m_map.find(title);
if (itor == m_map.end()) {
return;
}
m_map.erase(itor);
}
private:
std::map m_map;
};
/**
* @brief Dialog to manage the list of executables
**/
class EditExecutablesDialog : public MOBase::TutorableDialog
{
Q_OBJECT;
friend class IgnoreChanges;
public:
using CustomOverwrites = ToggableMap;
using ForcedLibraries = ToggableMap>;
explicit EditExecutablesDialog(OrganizerCore& oc, int selection = -1,
QWidget* parent = nullptr);
~EditExecutablesDialog();
// also saves and restores geometry
//
int exec() override;
ExecutablesList getExecutablesList() const;
const CustomOverwrites& getCustomOverwrites() const;
const ForcedLibraries& getForcedLibraries() const;
private slots:
void on_list_itemSelectionChanged();
void on_reset_clicked();
void on_add_clicked();
void on_remove_clicked();
void on_up_clicked();
void on_down_clicked();
void on_title_textChanged(const QString& s);
void on_title_editingFinished();
void on_overwriteSteamAppID_toggled(bool checked);
void on_createFilesInMod_toggled(bool checked);
void on_forceLoadLibraries_toggled(bool checked);
void on_browseBinary_clicked();
void on_browseWorkingDirectory_clicked();
void on_configureLibraries_clicked();
void on_buttons_clicked(QAbstractButton* b);
private:
std::unique_ptr ui;
OrganizerCore& m_organizerCore;
// copy of the original executables, used to clear the current settings when
// committing changes
const ExecutablesList m_originalExecutables;
// current executable list
ExecutablesList m_executablesList;
// custom overwrites set in the dialog
CustomOverwrites m_customOverwrites;
// forced libraries set in the dialog
ForcedLibraries m_forcedLibraries;
// remembers the last executable title that made sense, reverts to this when
// the widget loses focus if it's empty
QString m_lastGoodTitle;
// true when the change events being triggered are in response to loading
// the executable's data into the UI, not from a user change
bool m_settingUI;
void loadCustomOverwrites();
void loadForcedLibraries();
QListWidgetItem* selectedItem();
Executable* selectedExe();
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);
bool isTitleConflicting(const QString& s);
bool commitChanges();
void setDirty(bool b);
void selectIndex(int i);
bool checkOutputMods(const ExecutablesList& exes);
void addFromFile();
void addEmpty();
void clone();
void addNew(Executable e);
QFileInfo browseBinary(const QString& initial);
void setBinary(const QFileInfo& binary);
void setJarBinary(const QFileInfo& binary);
};
#endif // EDITEXECUTABLESDIALOG_H