diff options
| author | isanae <14251494+isanae@users.noreply.github.com> | 2020-07-23 09:17:43 -0400 |
|---|---|---|
| committer | isanae <14251494+isanae@users.noreply.github.com> | 2020-11-03 11:39:04 -0500 |
| commit | 717be0c0483839ef4da22b366ed5bf8f07e379e2 (patch) | |
| tree | bd1cd13c5a00ba4a9181a15baa677778d8a9ea1f /src | |
| parent | 60b59ddf097fffa846a4d28e0d9256630da5149c (diff) | |
game page
Diffstat (limited to 'src')
| -rw-r--r-- | src/createinstancedialog.cpp | 280 | ||||
| -rw-r--r-- | src/createinstancedialog.h | 7 | ||||
| -rw-r--r-- | src/createinstancedialog.ui | 55 | ||||
| -rw-r--r-- | src/instancemanagerdialog.cpp | 2 |
4 files changed, 324 insertions, 20 deletions
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp index d43fba1c..21dcd8ec 100644 --- a/src/createinstancedialog.cpp +++ b/src/createinstancedialog.cpp @@ -1,6 +1,9 @@ #include "createinstancedialog.h" #include "ui_createinstancedialog.h" #include "instancemanager.h" +#include "plugincontainer.h" +#include <report.h> +#include <iplugingame.h> namespace cid { @@ -9,7 +12,7 @@ class Page { public: Page(CreateInstanceDialog& dlg, std::size_t i) - : ui(dlg.getUI()), m_dlg(dlg), m_index(i) + : ui(dlg.getUI()), m_dlg(dlg), m_pc(dlg.pluginContainer()), m_index(i) { } @@ -25,12 +28,14 @@ public: protected: Ui::CreateInstanceDialog* ui; + CreateInstanceDialog& m_dlg; + const PluginContainer& m_pc; private: - CreateInstanceDialog& m_dlg; std::size_t m_index; }; + class TypePage : public Page { public: @@ -88,6 +93,254 @@ public: GamePage(CreateInstanceDialog& dlg, std::size_t i) : Page(dlg, i) { + createGames(); + fillList(); + + QObject::connect(ui->showAllGames, &QCheckBox::clicked, [&]{ fillList(); }); + } + + void select(MOBase::IPluginGame* game) + { + Game* checked = findGame(game); + if (!checked) { + return; + } + + if (!checked->installed) { + const auto path = QFileDialog::getExistingDirectory( + &m_dlg, QObject::tr("Find game installation")); + + if (path.isEmpty()) { + checked = nullptr; + } else { + checked = checkInstallation(path, checked); + } + } + + selectButton(checked); + } + +private: + struct Game + { + MOBase::IPluginGame* game = nullptr; + QCommandLinkButton* button = nullptr; + QString dir; + bool installed = false; + + Game(MOBase::IPluginGame* g) + : game(g), installed(g->isInstalled()) + { + if (installed) { + dir = game->gameDirectory().path(); + } + } + + Game(const Game&) = delete; + Game& operator=(const Game&) = delete; + }; + + std::vector<std::unique_ptr<Game>> m_games; + + + Game* findGame(MOBase::IPluginGame* game) + { + for (auto& g : m_games) { + if (g->game == game) { + return g.get(); + } + } + + return nullptr; + } + + void createGames() + { + m_games.clear(); + + for (auto* game : m_pc.plugins<MOBase::IPluginGame>()) { + m_games.push_back(std::make_unique<Game>(game)); + } + } + + void createButton(Game* g) + { + g->button = new QCommandLinkButton; + g->button->setCheckable(true); + + updateButton(g); + + QObject::connect(g->button, &QAbstractButton::clicked, [g, this] { + select(g->game); + }); + } + + void updateButton(Game* g) + { + if (!g->button) { + return; + } + + g->button->setText(g->game->gameName()); + + if (g->installed) { + g->button->setDescription(g->dir); + } else { + g->button->setDescription(QObject::tr("No installation found")); + } + } + + void selectButton(Game* g) + { + for (const auto& gg : m_games) { + if (!gg->button) { + continue; + } + + if (g) { + gg->button->setChecked(gg->game == g->game); + } else { + gg->button->setChecked(false); + } + } + } + + void fillList() + { + const bool showAll = ui->showAllGames->isChecked(); + + ui->games->clear(); + + for (auto& g : m_games) { + g->button = nullptr; + + if (!showAll && !g->installed) { + // not installed + continue; + } + + createButton(g.get()); + ui->games->addButton(g->button, QDialogButtonBox::AcceptRole); + } + } + + Game* checkInstallation(const QString& path, Game* g) + { + if (g->game->looksValid(path)) { + // okay + return g; + } + + // the selected game can't use that folder, find another one + auto* otherGame = findAnotherGame(path); + if (otherGame == g->game) { + // shouldn't happen, but okay + return g; + } + + if (otherGame) { + auto* confirmedGame = confirmOtherGame(path, g->game, otherGame); + + if (!confirmedGame) { + // cancelled + return nullptr; + } + + // make it look like the user clicked that button instead + g = findGame(confirmedGame); + if (!g) { + return nullptr; + } + } else { + // nothing can manage this, but the user can override + if (!confirmUnknown(path, g->game)) { + // cancelled + return nullptr; + } + } + + // remember this path + g->dir = path; + g->installed = true; + + updateButton(g); + + return g; + } + + MOBase::IPluginGame* findAnotherGame(const QString& path) + { + for (auto* otherGame : m_pc.plugins<MOBase::IPluginGame>()) { + if (otherGame->looksValid(path)) { + return otherGame; + } + } + + return nullptr; + } + + bool confirmUnknown(const QString& path, MOBase::IPluginGame* game) + { + const auto r = MOBase::TaskDialog(&m_dlg) + .title(QObject::tr("Unrecognized game")) + .main(QObject::tr("Unrecognized game")) + .content(QObject::tr( + "The folder %1 does not seem to contain installation for " + "<span style=\"white-space: nowrap; font-weight: bold;\">%2</span> or " + "any other game Mod Organizer can manage.") + .arg(path) + .arg(game->gameName())) + .button({ + QObject::tr("Use this folder for %1").arg(game->gameName()), + QObject::tr("I know what I'm doing"), + QMessageBox::Ignore}) + .button({ + QObject::tr("Cancel"), + QMessageBox::Cancel}) + .exec(); + + return (r == QMessageBox::Ignore); + } + + MOBase::IPluginGame* confirmOtherGame( + const QString& path, + MOBase::IPluginGame* selectedGame, MOBase::IPluginGame* guessedGame) + { + const auto r = MOBase::TaskDialog(&m_dlg) + .title(QObject::tr("Incorrect game")) + .main(QObject::tr("Incorrect game")) + .content(QObject::tr( + "The folder %1 seems to contain an installation for " + "<span style=\"white-space: nowrap; font-weight: bold;\">%2</span>, " + "not " + "<span style=\"white-space: nowrap; font-weight: bold;\">%3</span>.") + .arg(path) + .arg(guessedGame->gameName()) + .arg(selectedGame->gameName())) + .button({ + QObject::tr("Manage %1 instead").arg(guessedGame->gameName()), + QMessageBox::Ok}) + .button({ + QObject::tr("Use this folder for %1").arg(selectedGame->gameName()), + QObject::tr("I know what I'm doing"), + QMessageBox::Ignore}) + .button({ + QObject::tr("Cancel"), + QMessageBox::Cancel}) + .exec(); + + switch (r) + { + case QMessageBox::Ok: + return guessedGame; + + case QMessageBox::Ignore: + return selectedGame; + + case QMessageBox::Cancel: + default: + return nullptr; + } } }; @@ -114,8 +367,9 @@ public: } // namespace -CreateInstanceDialog::CreateInstanceDialog(QWidget *parent) - : QDialog(parent), ui(new Ui::CreateInstanceDialog) +CreateInstanceDialog::CreateInstanceDialog( + const PluginContainer& pc, QWidget *parent) + : QDialog(parent), ui(new Ui::CreateInstanceDialog), m_pc(pc) { using namespace cid; @@ -132,19 +386,6 @@ CreateInstanceDialog::CreateInstanceDialog(QWidget *parent) connect(ui->next, &QPushButton::clicked, [&]{ next(); }); connect(ui->back, &QPushButton::clicked, [&]{ back(); }); - - // - //SelectionDialog games(tr("Select a game to manage.")); - // - //for (auto* game : m_pc.plugins<MOBase::IPluginGame>()) { - // if (game->isInstalled()) { - // games.addChoice(game->gameName(), game->gameDirectory().path(), {}); - // } else { - // games.addChoice(game->gameName(), "", {}); - // } - //} - // - //games.exec(); } CreateInstanceDialog::~CreateInstanceDialog() = default; @@ -154,6 +395,11 @@ Ui::CreateInstanceDialog* CreateInstanceDialog::getUI() return ui.get(); } +const PluginContainer& CreateInstanceDialog::pluginContainer() +{ + return m_pc; +} + void CreateInstanceDialog::next() { ui->pages->setCurrentIndex(ui->pages->currentIndex() + 1); diff --git a/src/createinstancedialog.h b/src/createinstancedialog.h index 03e9de01..df056f85 100644 --- a/src/createinstancedialog.h +++ b/src/createinstancedialog.h @@ -6,22 +6,27 @@ namespace Ui { class CreateInstanceDialog; }; namespace cid { class Page; } +class PluginContainer; + class CreateInstanceDialog : public QDialog { Q_OBJECT public: - explicit CreateInstanceDialog(QWidget *parent = nullptr); + explicit CreateInstanceDialog( + const PluginContainer& pc, QWidget *parent = nullptr); ~CreateInstanceDialog(); Ui::CreateInstanceDialog* getUI(); + const PluginContainer& pluginContainer(); void next(); void back(); private: std::unique_ptr<Ui::CreateInstanceDialog> ui; + const PluginContainer& m_pc; std::vector<std::unique_ptr<cid::Page>> m_pages; void updateNavigationButtons(); diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui index bcfddb20..8cad959d 100644 --- a/src/createinstancedialog.ui +++ b/src/createinstancedialog.ui @@ -227,7 +227,60 @@ <number>0</number> </property> <item> - <widget class="QListWidget" name="games"/> + <widget class="QScrollArea" name="scrollArea"> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="widget_15"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>455</width> + <height>287</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QVBoxLayout" name="verticalLayout_16" stretch="0"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QDialogButtonBox" name="games"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::NoButton</set> + </property> + </widget> + </item> + </layout> + </widget> + </widget> </item> </layout> </widget> diff --git a/src/instancemanagerdialog.cpp b/src/instancemanagerdialog.cpp index c7042aa8..566f1aad 100644 --- a/src/instancemanagerdialog.cpp +++ b/src/instancemanagerdialog.cpp @@ -112,7 +112,7 @@ void InstanceManagerDialog::onSelection() void InstanceManagerDialog::createNew() { - CreateInstanceDialog dlg(this); + CreateInstanceDialog dlg(m_pc, this); dlg.exec(); } |
