From 60b59ddf097fffa846a4d28e0d9256630da5149c Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Thu, 23 Jul 2020 07:32:06 -0400
Subject: started create instance dialog allow for multiple instances of
Settings fill in information in instance manager
---
src/createinstancedialog.ui | 655 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 655 insertions(+)
create mode 100644 src/createinstancedialog.ui
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
new file mode 100644
index 00000000..bcfddb20
--- /dev/null
+++ b/src/createinstancedialog.ui
@@ -0,0 +1,655 @@
+
+
+ CreateInstanceDialog
+
+
+
+ 0
+ 0
+ 493
+ 423
+
+
+
+ Creating an instance
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ <h2>Creating a new instance</h2>
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 20
+ 10
+
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
+
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ <h3>Select the type of instance to create.</h3>
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Create a global instance
+
+
+ true
+
+
+ Global instances are stored in %1, but some paths can be changed to be on a different drive if necessary. A single installation of Mod Organizer can manage multiple global instances.
+
+
+
+ -
+
+
+ Create a portable instance
+
+
+ true
+
+
+ A portable instance stores everything in Mod Organizer's installation folder, currently %1. There can only be one portable instance per installation of Mod Organizer.
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ <h3>Select the game to manage.</h3>
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Show all supported games
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ <h3>Pick a name for this instance.</h3>
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
-
+
+
+ Instance name
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ <h3>Select a folder where the data should be stored.</h3>
+
+
+
+ -
+
+
+ This includes downloads, mods, profiles and overwrite. If there is enough space on this drive, you should use the default folder.
+
+
+ true
+
+
+
+
+
+
+ -
+
+
+
-
+
+
+ 1
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ ...
+
+
+
+ -
+
+
+ Location
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Overwrite
+
+
+
+ -
+
+
+ Mods
+
+
+
+ -
+
+
+ Base directory
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Profiles
+
+
+
+ -
+
+
+ -
+
+
+ Downloads
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ Use <code>%BASE_DIR%</code> to refer to the Base Directory.
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ ...
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 292
+ 20
+
+
+
+
+ -
+
+
+ Show advanced options
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ < Back
+
+
+
+ -
+
+
+ Next >
+
+
+ true
+
+
+
+ -
+
+
+ Cancel
+
+
+
+
+
+
+
+
+
+
+
--
cgit v1.3.1
From 717be0c0483839ef4da22b366ed5bf8f07e379e2 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Thu, 23 Jul 2020 09:17:43 -0400
Subject: game page
---
src/createinstancedialog.cpp | 280 +++++++++++++++++++++++++++++++++++++++---
src/createinstancedialog.h | 7 +-
src/createinstancedialog.ui | 55 ++++++++-
src/instancemanagerdialog.cpp | 2 +-
4 files changed, 324 insertions(+), 20 deletions(-)
(limited to 'src/createinstancedialog.ui')
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
+#include
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> 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()) {
+ m_games.push_back(std::make_unique(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()) {
+ 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 "
+ "%2 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 "
+ "%2, "
+ "not "
+ "%3.")
+ .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()) {
- // 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;
+ const PluginContainer& m_pc;
std::vector> 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 @@
0
-
-
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 455
+ 287
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Qt::Vertical
+
+
+ QDialogButtonBox::NoButton
+
+
+
+
+
+
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();
}
--
cgit v1.3.1
From b10bcf4cb72bf3db06735a6b893c93319cead965 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Thu, 23 Jul 2020 10:27:58 -0400
Subject: instance name page
---
src/createinstancedialog.cpp | 215 ++++++++++++++++++++++++++++++++++++++-----
src/createinstancedialog.h | 16 +++-
src/createinstancedialog.ui | 23 ++++-
src/instancemanager.cpp | 21 +++++
src/instancemanager.h | 5 +-
5 files changed, 252 insertions(+), 28 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp
index 79eaa79a..908c20d6 100644
--- a/src/createinstancedialog.cpp
+++ b/src/createinstancedialog.cpp
@@ -21,11 +21,40 @@ public:
return true;
}
+ virtual bool skip() const
+ {
+ // no-op
+ return false;
+ }
+
+ virtual void activated()
+ {
+ // no-op
+ }
+
+ void updateNavigation()
+ {
+ m_dlg.updateNavigation();
+ }
+
void next()
{
m_dlg.next();
}
+
+ virtual CreateInstanceDialog::Types selectedType() const
+ {
+ // no-op
+ return CreateInstanceDialog::NoType;
+ }
+
+ virtual MOBase::IPluginGame* selectedGame() const
+ {
+ // no-op
+ return nullptr;
+ }
+
protected:
Ui::CreateInstanceDialog* ui;
CreateInstanceDialog& m_dlg;
@@ -40,7 +69,7 @@ class TypePage : public Page
{
public:
TypePage(CreateInstanceDialog& dlg, std::size_t i)
- : Page(dlg, i)
+ : Page(dlg, i), m_type(CreateInstanceDialog::NoType)
{
ui->createGlobal->setDescription(
ui->createGlobal->description()
@@ -59,12 +88,17 @@ public:
bool ready() const override
{
- return m_global.has_value();
+ return (m_type != CreateInstanceDialog::NoType);
+ }
+
+ CreateInstanceDialog::Types selectedType() const
+ {
+ return m_type;
}
void global()
{
- m_global = true;
+ m_type = CreateInstanceDialog::Global;
ui->createGlobal->setChecked(true);
ui->createPortable->setChecked(false);
@@ -74,7 +108,7 @@ public:
void portable()
{
- m_global = false;
+ m_type = CreateInstanceDialog::Portable;
ui->createGlobal->setChecked(false);
ui->createPortable->setChecked(true);
@@ -83,7 +117,7 @@ public:
}
private:
- std::optional m_global;
+ CreateInstanceDialog::Types m_type;
};
@@ -99,26 +133,40 @@ public:
QObject::connect(ui->showAllGames, &QCheckBox::clicked, [&]{ fillList(); });
}
+ bool ready() const override
+ {
+ return (m_selection != nullptr);
+ }
+
+ MOBase::IPluginGame* selectedGame() const override
+ {
+ if (!m_selection) {
+ return nullptr;
+ }
+
+ return m_selection->game;
+ }
+
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 (checked) {
+ 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);
+ if (path.isEmpty()) {
+ checked = nullptr;
+ } else {
+ checked = checkInstallation(path, checked);
+ }
}
}
m_selection = checked;
selectButton(checked);
+ updateNavigation();
}
void selectCustom()
@@ -430,8 +478,90 @@ class NamePage : public Page
{
public:
NamePage(CreateInstanceDialog& dlg, std::size_t i)
- : Page(dlg, i)
+ : Page(dlg, i), m_modified(false), m_okay(false)
+ {
+ m_originalLabel = ui->instanceNameLabel->text();
+
+ QObject::connect(
+ ui->instanceName, &QLineEdit::textEdited, [&]{ onChanged(); });
+ }
+
+ bool ready() const override
+ {
+ return m_okay;
+ }
+
+ bool skip() const override
{
+ return (m_dlg.selectedType() == CreateInstanceDialog::Portable);
+ }
+
+ void activated() override
+ {
+ auto* g = m_dlg.selectedGame();
+ if (!g) {
+ // shouldn't happen, next should be disabled
+ return;
+ }
+
+ ui->instanceNameLabel->setText(m_originalLabel.arg(g->gameName()));
+
+ if (!m_modified || ui->instanceName->text().isEmpty()) {
+ const auto n = InstanceManager::instance().makeUniqueName(g->gameName());
+ ui->instanceName->setText(n);
+ m_modified = false;
+ }
+
+ updateWarnings();
+ }
+
+private:
+ QString m_originalLabel;
+ bool m_modified;
+ bool m_okay;
+
+ void onChanged()
+ {
+ m_modified = true;
+ updateWarnings();
+ }
+
+ void updateWarnings()
+ {
+ bool exists = false;
+ bool invalid = false;
+ bool empty = false;
+
+ auto& m = InstanceManager::instance();
+
+ const auto name = ui->instanceName->text().trimmed();
+
+ if (name.isEmpty()) {
+ empty = true;
+ } else {
+ const auto sanitized = m.sanitizeInstanceName(name);
+ if (name != sanitized) {
+ invalid = true;
+ } else {
+ exists = m.instanceExists(name);
+ }
+ }
+
+ if (exists) {
+ m_okay = false;
+ ui->instanceNameExists->setVisible(true);
+ ui->instanceNameInvalid->setVisible(false);
+ } else if (invalid) {
+ m_okay = false;
+ ui->instanceNameExists->setVisible(false);
+ ui->instanceNameInvalid->setVisible(true);
+ } else {
+ m_okay = !empty;
+ ui->instanceNameExists->setVisible(false);
+ ui->instanceNameInvalid->setVisible(false);
+ }
+
+ updateNavigation();
}
};
@@ -463,7 +593,7 @@ CreateInstanceDialog::CreateInstanceDialog(
ui->pages->setCurrentIndex(0);
- updateNavigationButtons();
+ updateNavigation();
connect(ui->next, &QPushButton::clicked, [&]{ next(); });
connect(ui->back, &QPushButton::clicked, [&]{ back(); });
@@ -483,17 +613,35 @@ const PluginContainer& CreateInstanceDialog::pluginContainer()
void CreateInstanceDialog::next()
{
- ui->pages->setCurrentIndex(ui->pages->currentIndex() + 1);
- updateNavigationButtons();
+ selectPage(ui->pages->currentIndex() + 1);
}
void CreateInstanceDialog::back()
{
- ui->pages->setCurrentIndex(ui->pages->currentIndex() - 1);
- updateNavigationButtons();
+ selectPage(ui->pages->currentIndex() - 1);
}
-void CreateInstanceDialog::updateNavigationButtons()
+void CreateInstanceDialog::selectPage(std::size_t i)
+{
+ while (i < m_pages.size()) {
+ if (!m_pages[i]->skip()) {
+ break;
+ }
+
+ ++i;
+ }
+
+ if (i >= m_pages.size()) {
+ return;
+ }
+
+ ui->pages->setCurrentIndex(static_cast(i));
+ m_pages[i]->activated();
+
+ updateNavigation();
+}
+
+void CreateInstanceDialog::updateNavigation()
{
const auto i = ui->pages->currentIndex();
const auto last = (i == (ui->pages->count() - 1));
@@ -501,3 +649,26 @@ void CreateInstanceDialog::updateNavigationButtons()
ui->next->setEnabled(m_pages[i]->ready() && !last);
ui->back->setEnabled(i > 0);
}
+
+CreateInstanceDialog::Types CreateInstanceDialog::selectedType() const
+{
+ for (auto&& p : m_pages) {
+ const auto t = p->selectedType();
+ if (t != NoType) {
+ return t;
+ }
+ }
+
+ return NoType;
+}
+
+MOBase::IPluginGame* CreateInstanceDialog::selectedGame() const
+{
+ for (auto&& p : m_pages) {
+ if (auto* g=p->selectedGame()) {
+ return g;
+ }
+ }
+
+ return nullptr;
+}
diff --git a/src/createinstancedialog.h b/src/createinstancedialog.h
index df056f85..3fd19d55 100644
--- a/src/createinstancedialog.h
+++ b/src/createinstancedialog.h
@@ -3,6 +3,7 @@
#include
+namespace MOBase { class IPluginGame; }
namespace Ui { class CreateInstanceDialog; };
namespace cid { class Page; }
@@ -13,6 +14,13 @@ class CreateInstanceDialog : public QDialog
Q_OBJECT
public:
+ enum Types
+ {
+ NoType = 0,
+ Global,
+ Portable
+ };
+
explicit CreateInstanceDialog(
const PluginContainer& pc, QWidget *parent = nullptr);
@@ -23,13 +31,17 @@ public:
void next();
void back();
+ void selectPage(std::size_t i);
+
+ void updateNavigation();
+
+ Types selectedType() const;
+ MOBase::IPluginGame* selectedGame() const;
private:
std::unique_ptr ui;
const PluginContainer& m_pc;
std::vector> m_pages;
-
- void updateNavigationButtons();
};
#endif // MODORGANIZER_CREATEINSTANCEDIALOG_INCLUDED
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index 8cad959d..6f215539 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -305,9 +305,12 @@
0
-
-
+
- <h3>Pick a name for this instance.</h3>
+ <h3>Customize the name for this <span style="white-space: nowrap;">%1</span> instance.</h3>
+
+
+ true
@@ -318,7 +321,7 @@
- 0
+ 9
-
@@ -327,6 +330,20 @@
+ -
+
+
+ There is already an instance with this name.
+
+
+
+ -
+
+
+ The name contains invalid characters. It must be a valid folder name.
+
+
+
-
diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp
index 98edba47..b135cac1 100644
--- a/src/instancemanager.cpp
+++ b/src/instancemanager.cpp
@@ -650,6 +650,27 @@ MOBase::IPluginGame* InstanceManager::determineCurrentGame(
return nullptr;
}
+QString InstanceManager::makeUniqueName(const QString& instanceName) const
+{
+ const QString sanitized = sanitizeInstanceName(instanceName);
+
+ QString name = sanitized;
+ for (int i=2; i<100; ++i) {
+ if (!instanceExists(name)) {
+ return name;
+ }
+
+ name = QString("%1 (%2)").arg(sanitized).arg(i);
+ }
+
+ return {};
+}
+
+bool InstanceManager::instanceExists(const QString& instanceName) const
+{
+ const QDir root = instancesPath();
+ return root.exists(instanceName);
+}
QString InstanceManager::sanitizeInstanceName(const QString &name) const
{
diff --git a/src/instancemanager.h b/src/instancemanager.h
index d53f4391..0cd5ef4c 100644
--- a/src/instancemanager.h
+++ b/src/instancemanager.h
@@ -53,6 +53,10 @@ public:
QStringList instanceNames() const;
std::vector instancePaths() const;
+ QString sanitizeInstanceName(const QString &name) const;
+ QString makeUniqueName(const QString& instanceName) const;
+ bool instanceExists(const QString& instanceName) const;
+
private:
InstanceManager();
@@ -63,7 +67,6 @@ private:
QString manageInstances(const QStringList &instanceList) const;
- QString sanitizeInstanceName(const QString &name) const;
void setCurrentInstance(const QString &name);
QString queryInstanceName(const QStringList &instanceList) const;
--
cgit v1.3.1
From 46d81056d1eda2fd74dac200cd7b8c36d9cbc4eb Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Thu, 23 Jul 2020 10:50:31 -0400
Subject: editions page
---
src/createinstancedialog.cpp | 174 +++++++++++++++++++++++++++++++++++++------
src/createinstancedialog.h | 1 +
src/createinstancedialog.ui | 106 +++++++++++++++++++++++++-
3 files changed, 258 insertions(+), 23 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp
index 908c20d6..262deb20 100644
--- a/src/createinstancedialog.cpp
+++ b/src/createinstancedialog.cpp
@@ -11,8 +11,8 @@ namespace cid
class Page
{
public:
- Page(CreateInstanceDialog& dlg, std::size_t i)
- : ui(dlg.getUI()), m_dlg(dlg), m_pc(dlg.pluginContainer()), m_index(i)
+ Page(CreateInstanceDialog& dlg)
+ : ui(dlg.getUI()), m_dlg(dlg), m_pc(dlg.pluginContainer())
{
}
@@ -55,21 +55,24 @@ public:
return nullptr;
}
+ virtual QString instanceName() const
+ {
+ // no-op
+ return {};
+ }
+
protected:
Ui::CreateInstanceDialog* ui;
CreateInstanceDialog& m_dlg;
const PluginContainer& m_pc;
-
-private:
- std::size_t m_index;
};
class TypePage : public Page
{
public:
- TypePage(CreateInstanceDialog& dlg, std::size_t i)
- : Page(dlg, i), m_type(CreateInstanceDialog::NoType)
+ TypePage(CreateInstanceDialog& dlg)
+ : Page(dlg), m_type(CreateInstanceDialog::NoType)
{
ui->createGlobal->setDescription(
ui->createGlobal->description()
@@ -124,8 +127,8 @@ private:
class GamePage : public Page
{
public:
- GamePage(CreateInstanceDialog& dlg, std::size_t i)
- : Page(dlg, i), m_selection(nullptr)
+ GamePage(CreateInstanceDialog& dlg)
+ : Page(dlg), m_selection(nullptr)
{
createGames();
fillList();
@@ -474,11 +477,93 @@ private:
};
+class EditionsPage : public Page
+{
+public:
+ EditionsPage(CreateInstanceDialog& dlg)
+ : Page(dlg), m_previousGame(nullptr)
+ {
+ }
+
+ bool ready() const override
+ {
+ return !m_selection.isEmpty();
+ }
+
+ bool skip() const override
+ {
+ auto* g = m_dlg.selectedGame();
+ if (!g) {
+ // shouldn't happen
+ return true;
+ }
+
+ const auto variants = g->gameVariants();
+ return (variants.size() < 2);
+ }
+
+ void activated() override
+ {
+ auto* g = m_dlg.selectedGame();
+
+ if (m_previousGame != g) {
+ m_previousGame = g;
+ m_selection = "";
+ fillList();
+ }
+ }
+
+ void select(const QString& variant)
+ {
+ for (auto* b : m_buttons) {
+ if (b->text() == variant) {
+ m_selection = variant;
+ b->setChecked(true);
+ } else {
+ b->setChecked(false);
+ }
+ }
+
+ updateNavigation();
+ }
+
+private:
+ MOBase::IPluginGame* m_previousGame;
+ std::vector m_buttons;
+ QString m_selection;
+
+ void fillList()
+ {
+ ui->editions->clear();
+ m_buttons.clear();
+
+ auto* g = m_dlg.selectedGame();
+ if (!g) {
+ // shouldn't happen
+ return;
+ }
+
+ const auto variants = g->gameVariants();
+ for (auto& v : variants) {
+ auto* b = new QCommandLinkButton(v);
+ b->setCheckable(true);
+
+ QObject::connect(b, &QAbstractButton::clicked, [v, this] {
+ select(v);
+ });
+
+ ui->editions->addButton(b, QDialogButtonBox::AcceptRole);
+ m_buttons.push_back(b);
+ }
+ }
+};
+
+
class NamePage : public Page
{
public:
- NamePage(CreateInstanceDialog& dlg, std::size_t i)
- : Page(dlg, i), m_modified(false), m_okay(false)
+ NamePage(CreateInstanceDialog& dlg)
+ : Page(dlg), m_modified(false), m_okay(false)
{
m_originalLabel = ui->instanceNameLabel->text();
@@ -515,6 +600,16 @@ public:
updateWarnings();
}
+ QString instanceName() const override
+ {
+ if (!m_okay) {
+ return {};
+ }
+
+ const auto text = ui->instanceName->text().trimmed();
+ return InstanceManager::instance().sanitizeInstanceName(text);
+ }
+
private:
QString m_originalLabel;
bool m_modified;
@@ -534,16 +629,16 @@ private:
auto& m = InstanceManager::instance();
- const auto name = ui->instanceName->text().trimmed();
+ const auto text = ui->instanceName->text().trimmed();
- if (name.isEmpty()) {
+ if (text.isEmpty()) {
empty = true;
} else {
- const auto sanitized = m.sanitizeInstanceName(name);
- if (name != sanitized) {
+ const auto sanitized = m.sanitizeInstanceName(text);
+ if (text != sanitized) {
invalid = true;
} else {
- exists = m.instanceExists(name);
+ exists = m.instanceExists(text);
}
}
@@ -569,9 +664,31 @@ private:
class PathsPage : public Page
{
public:
- PathsPage(CreateInstanceDialog& dlg, std::size_t i)
- : Page(dlg, i)
+ PathsPage(CreateInstanceDialog& dlg)
+ : Page(dlg)
{
+ QObject::connect(
+ ui->advancedPathOptions, &QCheckBox::clicked, [&]{ onAdvanced(); });
+
+ ui->pathPages->setCurrentIndex(0);
+ }
+
+ void activated() override
+ {
+ const auto root = InstanceManager::instance().instancesPath();
+ const auto path = QDir::toNativeSeparators(root + "/" + m_dlg.instanceName());
+
+ ui->location->setText(path);
+ }
+
+private:
+ void onAdvanced()
+ {
+ if (ui->advancedPathOptions->isChecked()) {
+ ui->pathPages->setCurrentIndex(1);
+ } else {
+ ui->pathPages->setCurrentIndex(0);
+ }
}
};
@@ -586,10 +703,11 @@ CreateInstanceDialog::CreateInstanceDialog(
ui->setupUi(this);
- m_pages.push_back(std::make_unique(*this, 0));
- m_pages.push_back(std::make_unique(*this, 1));
- m_pages.push_back(std::make_unique(*this, 2));
- m_pages.push_back(std::make_unique(*this, 3));
+ m_pages.push_back(std::make_unique(*this));
+ m_pages.push_back(std::make_unique(*this));
+ m_pages.push_back(std::make_unique(*this));
+ m_pages.push_back(std::make_unique(*this));
+ m_pages.push_back(std::make_unique(*this));
ui->pages->setCurrentIndex(0);
@@ -672,3 +790,15 @@ MOBase::IPluginGame* CreateInstanceDialog::selectedGame() const
return nullptr;
}
+
+QString CreateInstanceDialog::instanceName() const
+{
+ for (auto&& p : m_pages) {
+ const auto s = p->instanceName();
+ if (!s.isEmpty()) {
+ return s;
+ }
+ }
+
+ return {};
+}
diff --git a/src/createinstancedialog.h b/src/createinstancedialog.h
index 3fd19d55..14ed9f8e 100644
--- a/src/createinstancedialog.h
+++ b/src/createinstancedialog.h
@@ -37,6 +37,7 @@ public:
Types selectedType() const;
MOBase::IPluginGame* selectedGame() const;
+ QString instanceName() const;
private:
std::unique_ptr ui;
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index 6f215539..751c5427 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -287,6 +287,110 @@
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ <h3>Select the game edition.</h3>
+
+
+
+ -
+
+
+ This game has multiple variants. The correct one must be selected or Mod Organizer will not be able to launch the game properly.
+
+
+ true
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 455
+ 257
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Qt::Vertical
+
+
+ QDialogButtonBox::NoButton
+
+
+
+
+
+
+
+
+
+
+
+
-
@@ -405,7 +509,7 @@
-
- 1
+ 0
--
cgit v1.3.1
From ebbc8ed60c606b1b76fcea36eb2bd5db6373f7f0 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Thu, 23 Jul 2020 12:20:55 -0400
Subject: paths page
---
src/createinstancedialog.cpp | 337 +++++++++++++++++++++++++++++++++++++------
src/createinstancedialog.h | 3 +
src/createinstancedialog.ui | 148 +++++++++++++------
3 files changed, 395 insertions(+), 93 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp
index 262deb20..4308969e 100644
--- a/src/createinstancedialog.cpp
+++ b/src/createinstancedialog.cpp
@@ -2,12 +2,158 @@
#include "ui_createinstancedialog.h"
#include "instancemanager.h"
#include "plugincontainer.h"
+#include "shared/appconfig.h"
#include
#include
namespace cid
{
+class PathChecker
+{
+public:
+ PathChecker(QLabel* existsLabel, QLabel* invalidLabel)
+ : m_exists(existsLabel), m_invalid(invalidLabel)
+ {
+ m_existsOriginal = m_exists->text();
+ m_invalidOriginal = m_invalid->text();
+ }
+
+ QString sanitizeFileName(const QString& name) const
+ {
+ QString new_name = name;
+
+ // Restrict the allowed characters
+ new_name = new_name.remove(QRegExp("[^A-Za-z0-9 _=+;!@#$%^'\\-\\.\\[\\]\\{\\}\\(\\)]"));
+
+ // Don't end in spaces and periods
+ new_name = new_name.remove(QRegExp("\\.*$"));
+ new_name = new_name.remove(QRegExp(" *$"));
+
+ // Recurse until stuff stops changing
+ if (new_name != name) {
+ return sanitizeFileName(new_name);
+ }
+
+ return new_name;
+ }
+
+ // same thing as above, but allows path separators and colons
+ //
+ QString sanitizePath(const QString& path) const
+ {
+ QString new_name = path;
+
+ // Restrict the allowed characters
+ new_name = new_name.remove(QRegExp("[^\\\\\\/A-Za-z0-9 _=+;!@#$%^:'\\-\\.\\[\\]\\{\\}\\(\\)]"));
+
+ // Don't end in spaces and periods
+ new_name = new_name.remove(QRegExp("\\.*$"));
+ new_name = new_name.remove(QRegExp(" *$"));
+
+ // Recurse until stuff stops changing
+ if (new_name != path) {
+ return sanitizeFileName(new_name);
+ }
+
+ return new_name;
+ }
+
+ bool checkName(QString parentDir, QString name) const
+ {
+ bool exists = false;
+ bool invalid = false;
+ bool empty = false;
+
+ name = name.trimmed();
+
+ if (name.isEmpty()) {
+ empty = true;
+ } else {
+ const QString sanitized = sanitizeFileName(name);
+
+ if (name != sanitized) {
+ invalid = true;
+ } else {
+ exists = QDir(parentDir).exists(name);
+ }
+ }
+
+ bool okay = false;
+
+ if (exists) {
+ m_exists->setVisible(true);
+ setPossiblePlaceholder(m_exists, m_existsOriginal, QDir(parentDir).filePath(name));
+ m_invalid->setVisible(false);
+ } else if (invalid) {
+ m_exists->setVisible(false);
+ m_invalid->setVisible(true);
+ setPossiblePlaceholder(m_invalid, m_invalidOriginal, name);
+ } else {
+ okay = !empty;
+ m_exists->setVisible(false);
+ m_invalid->setVisible(false);
+ }
+
+ return okay;
+ }
+
+ bool checkPath(QString path) const
+ {
+ bool exists = false;
+ bool invalid = false;
+ bool empty = false;
+
+ path = path.trimmed();
+
+ if (path.isEmpty()) {
+ empty = true;
+ } else {
+ const QString sanitized = sanitizePath(path);
+
+ if (path != sanitized) {
+ invalid = true;
+ } else {
+ exists = QDir(path).exists();
+ }
+ }
+
+ bool okay = false;
+
+ if (exists) {
+ m_exists->setVisible(true);
+ setPossiblePlaceholder(m_exists, m_existsOriginal, path);
+ m_invalid->setVisible(false);
+ } else if (invalid) {
+ m_exists->setVisible(false);
+ m_invalid->setVisible(true);
+ setPossiblePlaceholder(m_invalid, m_invalidOriginal, path);
+ } else {
+ okay = !empty;
+ m_exists->setVisible(false);
+ m_invalid->setVisible(false);
+ }
+
+ return okay;
+ }
+
+private:
+ QLabel* m_exists;
+ QString m_existsOriginal;
+
+ QLabel* m_invalid;
+ QString m_invalidOriginal;
+
+ void setPossiblePlaceholder(
+ QLabel* label, const QString& s, const QString& arg) const
+ {
+ if (label->text().contains("%1")) {
+ label->setText(s.arg(arg));
+ }
+ }
+};
+
+
class Page
{
public:
@@ -562,8 +708,9 @@ private:
class NamePage : public Page
{
public:
- NamePage(CreateInstanceDialog& dlg)
- : Page(dlg), m_modified(false), m_okay(false)
+ NamePage(CreateInstanceDialog& dlg) :
+ Page(dlg), m_modified(false), m_okay(false),
+ m_checker(ui->instanceNameExists, ui->instanceNameInvalid)
{
m_originalLabel = ui->instanceNameLabel->text();
@@ -607,10 +754,11 @@ public:
}
const auto text = ui->instanceName->text().trimmed();
- return InstanceManager::instance().sanitizeInstanceName(text);
+ return m_checker.sanitizeFileName(text);
}
private:
+ PathChecker m_checker;
QString m_originalLabel;
bool m_modified;
bool m_okay;
@@ -623,39 +771,9 @@ private:
void updateWarnings()
{
- bool exists = false;
- bool invalid = false;
- bool empty = false;
-
- auto& m = InstanceManager::instance();
-
- const auto text = ui->instanceName->text().trimmed();
-
- if (text.isEmpty()) {
- empty = true;
- } else {
- const auto sanitized = m.sanitizeInstanceName(text);
- if (text != sanitized) {
- invalid = true;
- } else {
- exists = m.instanceExists(text);
- }
- }
-
- if (exists) {
- m_okay = false;
- ui->instanceNameExists->setVisible(true);
- ui->instanceNameInvalid->setVisible(false);
- } else if (invalid) {
- m_okay = false;
- ui->instanceNameExists->setVisible(false);
- ui->instanceNameInvalid->setVisible(true);
- } else {
- m_okay = !empty;
- ui->instanceNameExists->setVisible(false);
- ui->instanceNameInvalid->setVisible(false);
- }
+ const auto root = InstanceManager::instance().instancesPath();
+ m_okay = m_checker.checkName(root, ui->instanceName->text());
updateNavigation();
}
};
@@ -664,31 +782,109 @@ private:
class PathsPage : public Page
{
public:
- PathsPage(CreateInstanceDialog& dlg)
- : Page(dlg)
+ PathsPage(CreateInstanceDialog& dlg) :
+ Page(dlg),
+ m_checker(ui->locationExists, ui->locationInvalid),
+ m_advancedChecker(ui->advancedDirExists, ui->advancedDirInvalid)
{
+ QObject::connect(ui->location, &QLineEdit::textEdited, [&]{ onChanged(); });
+ QObject::connect(ui->base, &QLineEdit::textEdited, [&]{ onChanged(); });
+ QObject::connect(ui->downloads, &QLineEdit::textEdited, [&]{ onChanged(); });
+ QObject::connect(ui->mods, &QLineEdit::textEdited, [&]{ onChanged(); });
+ QObject::connect(ui->profiles, &QLineEdit::textEdited, [&]{ onChanged(); });
+ QObject::connect(ui->overwrite, &QLineEdit::textEdited, [&]{ onChanged(); });
+
QObject::connect(
ui->advancedPathOptions, &QCheckBox::clicked, [&]{ onAdvanced(); });
ui->pathPages->setCurrentIndex(0);
}
+ bool ready() const override
+ {
+ return checkPaths();
+ }
+
void activated() override
{
- const auto root = InstanceManager::instance().instancesPath();
- const auto path = QDir::toNativeSeparators(root + "/" + m_dlg.instanceName());
+ const auto name = m_dlg.instanceName();
+
+ setPaths(name, (m_lastInstanceName != name));
+ checkPaths();
+ updateNavigation();
- ui->location->setText(path);
+ m_lastInstanceName = name;
}
private:
+ PathChecker m_checker, m_advancedChecker;
+ QString m_lastInstanceName;
+
+ void onChanged()
+ {
+ checkPaths();
+ updateNavigation();
+ }
+
+ bool checkPaths() const
+ {
+ if (ui->advancedPathOptions->isChecked()) {
+ return
+ checkAdvancedPath(ui->base->text()) &&
+ checkVarPath(ui->downloads->text());
+ } else {
+ return m_checker.checkPath(ui->location->text());
+ }
+ }
+
+ bool checkAdvancedPath(const QString& path) const
+ {
+ return m_advancedChecker.checkPath(path);
+ }
+
+ bool checkVarPath(QString path) const
+ {
+ path.replace("%BASE_DIR%", ui->base->text());
+ return checkAdvancedPath(path);
+ }
+
void onAdvanced()
{
if (ui->advancedPathOptions->isChecked()) {
+ ui->base->setText(ui->location->text());
ui->pathPages->setCurrentIndex(1);
} else {
+ ui->location->setText(ui->base->text());
ui->pathPages->setCurrentIndex(0);
}
+
+ checkPaths();
+ }
+
+ void setPaths(const QString& name, bool force)
+ {
+ const auto root = InstanceManager::instance().instancesPath();
+ const auto path = QDir::toNativeSeparators(root + "/" + name);
+
+ setIfEmpty(ui->location, path, force);
+
+ setIfEmpty(ui->base, path, force);
+ setIfEmpty(ui->downloads, makeDefaultPath(AppConfig::downloadPath()), force);
+ setIfEmpty(ui->mods, makeDefaultPath(AppConfig::modsPath()), force);
+ setIfEmpty(ui->profiles, makeDefaultPath(AppConfig::profilesPath()), force);
+ setIfEmpty(ui->overwrite, makeDefaultPath(AppConfig::overwritePath()), force);
+ }
+
+ void setIfEmpty(QLineEdit* e, const QString& path, bool force)
+ {
+ if (e->text().isEmpty() || force) {
+ e->setText(path);
+ }
+ }
+
+ QString makeDefaultPath(const std::wstring& dir)
+ {
+ return "%BASE_DIR%\\" + QString::fromStdWString(dir);
}
};
@@ -702,6 +898,7 @@ CreateInstanceDialog::CreateInstanceDialog(
using namespace cid;
ui->setupUi(this);
+ m_originalNext = ui->next->text();
m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
@@ -731,24 +928,62 @@ const PluginContainer& CreateInstanceDialog::pluginContainer()
void CreateInstanceDialog::next()
{
- selectPage(ui->pages->currentIndex() + 1);
+ const auto i = ui->pages->currentIndex();
+ const auto last = (i == (ui->pages->count() - 1));
+
+ if (last) {
+ finish();
+ } else {
+ changePage(+1);
+ }
}
void CreateInstanceDialog::back()
{
- selectPage(ui->pages->currentIndex() - 1);
+ changePage(-1);
}
-void CreateInstanceDialog::selectPage(std::size_t i)
+void CreateInstanceDialog::changePage(int d)
{
- while (i < m_pages.size()) {
- if (!m_pages[i]->skip()) {
- break;
+ std::size_t i = static_cast(ui->pages->currentIndex());
+
+ if (d > 0) {
+ for (;;) {
+ ++i;
+
+ if (i >= m_pages.size()) {
+ break;
+ }
+
+ if (!m_pages[i]->skip()) {
+ break;
+ }
}
+ } else {
+ for (;;) {
+ if (i == 0) {
+ break;
+ }
+
+ --i;
- ++i;
+ if (!m_pages[i]->skip()) {
+ break;
+ }
+ }
}
+ if (i < m_pages.size()) {
+ selectPage(i);
+ }
+}
+
+void CreateInstanceDialog::finish()
+{
+}
+
+void CreateInstanceDialog::selectPage(std::size_t i)
+{
if (i >= m_pages.size()) {
return;
}
@@ -764,8 +999,14 @@ void CreateInstanceDialog::updateNavigation()
const auto i = ui->pages->currentIndex();
const auto last = (i == (ui->pages->count() - 1));
- ui->next->setEnabled(m_pages[i]->ready() && !last);
+ ui->next->setEnabled(m_pages[i]->ready());
ui->back->setEnabled(i > 0);
+
+ if (last) {
+ ui->next->setText(tr("Finish"));
+ } else {
+ ui->next->setText(m_originalNext);
+ }
}
CreateInstanceDialog::Types CreateInstanceDialog::selectedType() const
diff --git a/src/createinstancedialog.h b/src/createinstancedialog.h
index 14ed9f8e..ac1c30b6 100644
--- a/src/createinstancedialog.h
+++ b/src/createinstancedialog.h
@@ -32,6 +32,8 @@ public:
void next();
void back();
void selectPage(std::size_t i);
+ void changePage(int d);
+ void finish();
void updateNavigation();
@@ -43,6 +45,7 @@ private:
std::unique_ptr ui;
const PluginContainer& m_pc;
std::vector> m_pages;
+ QString m_originalNext;
};
#endif // MODORGANIZER_CREATEINSTANCEDIALOG_INCLUDED
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index 751c5427..98cbe96e 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -554,7 +554,7 @@
- -
+
-
Qt::Vertical
@@ -567,8 +567,26 @@
+ -
+
+
+ This folder already exists.
+
+
+
-
-
+
+
+ Folder
+
+
+
+ -
+
+
+ The folder contains invalid characters.
+
+
@@ -604,10 +622,17 @@
0
- -
-
+
-
+
- Overwrite
+ ...
+
+
+
+ -
+
+
+ ...
@@ -618,6 +643,27 @@
+ -
+
+
+ Folder
+
+
+
+ -
+
+
+ Folder
+
+
+
+ -
+
+
+ Overwrite
+
+
+
-
@@ -625,29 +671,30 @@
- -
-
-
- Qt::Vertical
+
-
+
+
+ ...
-
-
- 20
- 40
-
+
+
+ -
+
+
+ Folder
-
+
- -
-
+
-
+
- Profiles
+ The folder %1 already exists.
+
+
+ true
- -
-
-
-
@@ -656,40 +703,35 @@
-
-
-
- -
-
-
- -
-
+
+
+ Folder
+
+
-
-
-
- -
-
-
- Use <code>%BASE_DIR%</code> to refer to the Base Directory.
+
+
+ Folder
- -
-
+
-
+
- ...
+ Profiles
- -
-
+
-
+
- ...
+ Use <code>%BASE_DIR%</code> to refer to the Base Directory.
- -
-
+
-
+
...
@@ -702,10 +744,26 @@
- -
-
+
-
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
- ...
+ The folder %1 contains invalid characters.
+
+
+ true
--
cgit v1.3.1
From 2cb5c21b8e15b02a09144ff6c1ab11e87879a420 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Fri, 24 Jul 2020 09:25:02 -0400
Subject: fixed settings doing weird stuff with multiple instances sort games
by name added intro and confirmation pages
---
src/createinstancedialog.cpp | 55 ++++++++++++++++++++++++++----
src/createinstancedialog.h | 1 +
src/createinstancedialog.ui | 79 +++++++++++++++++++++++++++++++++++++++++++
src/instancemanagerdialog.cpp | 6 ++++
src/main.cpp | 10 +++---
src/mainwindow.cpp | 26 ++++++++------
src/settings.cpp | 40 +++++++++++-----------
src/settings.h | 5 ++-
8 files changed, 178 insertions(+), 44 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp
index 4308969e..5db6d685 100644
--- a/src/createinstancedialog.cpp
+++ b/src/createinstancedialog.cpp
@@ -214,6 +214,16 @@ protected:
};
+class InfoPage : public Page
+{
+public:
+ InfoPage(CreateInstanceDialog& dlg)
+ : Page(dlg)
+ {
+ }
+};
+
+
class TypePage : public Page
{
public:
@@ -345,7 +355,7 @@ public:
void warnUnrecognized(const QString& path)
{
QString supportedGames;
- for (auto* game : m_pc.plugins()) {
+ for (auto* game : sortedGamePlugins()) {
supportedGames += "" + game->gameName() + "";
}
@@ -381,6 +391,21 @@ private:
Game* m_selection;
+ std::vector sortedGamePlugins() const
+ {
+ std::vector v;
+
+ for (auto* game : m_pc.plugins()) {
+ v.push_back(game);
+ }
+
+ std::sort(v.begin(), v.end(), [](auto* a, auto* b) {
+ return (a->gameName() < b->gameName());
+ });
+
+ return v;
+ }
+
Game* findGame(MOBase::IPluginGame* game)
{
for (auto& g : m_games) {
@@ -396,7 +421,7 @@ private:
{
m_games.clear();
- for (auto* game : m_pc.plugins()) {
+ for (auto* game : sortedGamePlugins()) {
m_games.push_back(std::make_unique(game));
}
}
@@ -563,9 +588,9 @@ private:
.title(QObject::tr("Unrecognized game"))
.main(QObject::tr("Unrecognized game"))
.content(QObject::tr(
- "The folder %1 does not seem to contain installation for "
+ "The folder %1 does not seem to contain an installation for "
"%2 or "
- "any other game Mod Organizer can manage.")
+ "for any other game Mod Organizer can manage.")
.arg(path)
.arg(game->gameName()))
.button({
@@ -800,6 +825,11 @@ public:
ui->pathPages->setCurrentIndex(0);
}
+ bool skip() const override
+ {
+ return (m_dlg.selectedType() == CreateInstanceDialog::Portable);
+ }
+
bool ready() const override
{
return checkPaths();
@@ -900,11 +930,13 @@ CreateInstanceDialog::CreateInstanceDialog(
ui->setupUi(this);
m_originalNext = ui->next->text();
+ m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
+ m_pages.push_back(std::make_unique(*this));
ui->pages->setCurrentIndex(0);
@@ -926,10 +958,21 @@ const PluginContainer& CreateInstanceDialog::pluginContainer()
return m_pc;
}
+bool CreateInstanceDialog::isOnLastPage() const
+{
+ for (int i=ui->pages->currentIndex() + 1; i < ui->pages->count(); ++i) {
+ if (!m_pages[i]->skip()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
void CreateInstanceDialog::next()
{
const auto i = ui->pages->currentIndex();
- const auto last = (i == (ui->pages->count() - 1));
+ const auto last = isOnLastPage();
if (last) {
finish();
@@ -997,7 +1040,7 @@ void CreateInstanceDialog::selectPage(std::size_t i)
void CreateInstanceDialog::updateNavigation()
{
const auto i = ui->pages->currentIndex();
- const auto last = (i == (ui->pages->count() - 1));
+ const auto last = isOnLastPage();
ui->next->setEnabled(m_pages[i]->ready());
ui->back->setEnabled(i > 0);
diff --git a/src/createinstancedialog.h b/src/createinstancedialog.h
index ac1c30b6..02608c8d 100644
--- a/src/createinstancedialog.h
+++ b/src/createinstancedialog.h
@@ -36,6 +36,7 @@ public:
void finish();
void updateNavigation();
+ bool isOnLastPage() const;
Types selectedType() const;
MOBase::IPluginGame* selectedGame() const;
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index 98cbe96e..72d73020 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -60,6 +60,24 @@
0
+
+
+ -
+
+
+ <h3>What is an instance?</h3>
+<p>An instance is a full set of mods, downloads, profiles and configuration for a game. Each game must be managed in its own instance. Mod Organizer can freely switch between instances.</p>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ true
+
+
+
+
+
-
@@ -823,6 +841,67 @@
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ <h3>Confirmation</h3>
+
+
+
+ -
+
+
+ The instance is about to be created. Review the information below and press 'Finish'.
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
+
+
+
+
+
+
+
+
-
diff --git a/src/instancemanagerdialog.cpp b/src/instancemanagerdialog.cpp
index 566f1aad..26e8eae1 100644
--- a/src/instancemanagerdialog.cpp
+++ b/src/instancemanagerdialog.cpp
@@ -8,6 +8,12 @@
#include "shared/appconfig.h"
#include
+void openInstanceManager(PluginContainer& pc, QWidget* parent)
+{
+ InstanceManagerDialog dlg(pc, parent);
+ dlg.exec();
+}
+
class InstanceInfo
{
public:
diff --git a/src/main.cpp b/src/main.cpp
index 71fb0bbd..58e22466 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -270,6 +270,8 @@ std::optional handleCommandLine(
return {};
}
+void openInstanceManager(PluginContainer& pc, QWidget* parent);
+
int runApplication(
MOApplication &application, const cl::CommandLine& cl,
SingleInstance &instance, const QString &dataPath)
@@ -298,8 +300,9 @@ int runApplication(
try
{
- Settings settings(dataPath + "/" + QString::fromStdWString(AppConfig::iniFileName()));
- settings.setGlobalInstance();
+ Settings settings(
+ dataPath + "/" + QString::fromStdWString(AppConfig::iniFileName()),
+ true);
log::getDefault().setLevel(settings.diagnostics().logLevel());
@@ -434,8 +437,7 @@ int runApplication(
QTimer::singleShot(std::chrono::milliseconds(1), [&]
{
- InstanceManagerDialog dlg(*pluginContainer, &mainWindow);
- dlg.exec();
+ openInstanceManager(*pluginContainer, &mainWindow);
});
res = application.exec();
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 65c1d65c..c2d83e36 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -5952,20 +5952,24 @@ void MainWindow::on_actionNotifications_triggered()
scheduleCheckForProblems();
}
+void openInstanceManager(PluginContainer& pc, QWidget* parent);
+
void MainWindow::on_actionChange_Game_triggered()
{
- if (m_OrganizerCore.settings().interface().showChangeGameConfirmation()) {
- const auto r = QMessageBox::question(
- this, tr("Are you sure?"), tr("This will restart MO, continue?"),
- QMessageBox::Yes | QMessageBox::Cancel);
+ openInstanceManager(m_PluginContainer, this);
- if (r != QMessageBox::Yes) {
- return;
- }
- }
-
- InstanceManager::instance().clearCurrentInstance();
- ExitModOrganizer(Exit::Restart);
+ //if (m_OrganizerCore.settings().interface().showChangeGameConfirmation()) {
+ // const auto r = QMessageBox::question(
+ // this, tr("Are you sure?"), tr("This will restart MO, continue?"),
+ // QMessageBox::Yes | QMessageBox::Cancel);
+ //
+ // if (r != QMessageBox::Yes) {
+ // return;
+ // }
+ //}
+ //
+ //InstanceManager::instance().clearCurrentInstance();
+ //ExitModOrganizer(Exit::Restart);
}
void MainWindow::setCategoryListVisible(bool visible)
diff --git a/src/settings.cpp b/src/settings.cpp
index 43e7a4fa..8db9c623 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -61,33 +61,31 @@ QString toString(EndorsementState s)
Settings *Settings::s_Instance = nullptr;
-Settings::Settings(const QString& path) :
+Settings::Settings(const QString& path, bool globalInstance) :
m_Settings(path, QSettings::IniFormat),
- m_Game(m_Settings), m_Geometry(m_Settings), m_Widgets(m_Settings),
- m_Colors(m_Settings), m_Plugins(m_Settings), m_Paths(m_Settings),
- m_Network(m_Settings), m_Nexus(*this, m_Settings), m_Steam(*this, m_Settings),
+ m_Game(m_Settings), m_Geometry(m_Settings),
+ m_Widgets(m_Settings, globalInstance), m_Colors(m_Settings),
+ m_Plugins(m_Settings), m_Paths(m_Settings), m_Network(m_Settings),
+ m_Nexus(*this, m_Settings), m_Steam(*this, m_Settings),
m_Interface(m_Settings), m_Diagnostics(m_Settings)
{
+ if (globalInstance) {
+ if (s_Instance != nullptr) {
+ throw std::runtime_error("second instance of \"Settings\" created");
+ } else {
+ s_Instance = this;
+ }
+ }
}
Settings::~Settings()
{
- MOBase::QuestionBoxMemory::setCallbacks({}, {}, {});
-
if (s_Instance == this) {
+ MOBase::QuestionBoxMemory::setCallbacks({}, {}, {});
s_Instance = nullptr;
}
}
-void Settings::setGlobalInstance()
-{
- if (s_Instance != nullptr) {
- throw std::runtime_error("second instance of \"Settings\" created");
- } else {
- s_Instance = this;
- }
-}
-
Settings &Settings::instance()
{
if (s_Instance == nullptr) {
@@ -1011,13 +1009,15 @@ void GeometrySettings::restoreDocks(QMainWindow* mw) const
}
-WidgetSettings::WidgetSettings(QSettings& s)
+WidgetSettings::WidgetSettings(QSettings& s, bool globalInstance)
: m_Settings(s)
{
- MOBase::QuestionBoxMemory::setCallbacks(
- [this](auto&& w, auto&& f){ return questionButton(w, f); },
- [this](auto&& w, auto&& b){ setQuestionWindowButton(w, b); },
- [this](auto&& w, auto&& f, auto&& b){ setQuestionFileButton(w, f, b); });
+ if (globalInstance) {
+ MOBase::QuestionBoxMemory::setCallbacks(
+ [this](auto&& w, auto&& f){ return questionButton(w, f); },
+ [this](auto&& w, auto&& b){ setQuestionWindowButton(w, b); },
+ [this](auto&& w, auto&& f, auto&& b){ setQuestionFileButton(w, f, b); });
+ }
}
std::optional WidgetSettings::index(const QComboBox* cb) const
diff --git a/src/settings.h b/src/settings.h
index 84102c72..a8c527d6 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -195,7 +195,7 @@ private:
class WidgetSettings
{
public:
- WidgetSettings(QSettings& s);
+ WidgetSettings(QSettings& s, bool globalInstance);
// selected index for a combobox
//
@@ -677,11 +677,10 @@ class Settings : public QObject
Q_OBJECT;
public:
- Settings(const QString& path);
+ Settings(const QString& path, bool globalInstance=false);
~Settings();
static Settings &instance();
- void setGlobalInstance();
// name of the ini file
//
--
cgit v1.3.1
From 7b02c77a3961d859aae270922db26bbc999677cb Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Fri, 24 Jul 2020 10:10:19 -0400
Subject: review page
---
src/createinstancedialog.cpp | 197 +++++++++++++++++++++++++++++++++++--------
src/createinstancedialog.h | 31 ++++++-
src/createinstancedialog.ui | 6 +-
3 files changed, 194 insertions(+), 40 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp
index 5db6d685..8c6605ed 100644
--- a/src/createinstancedialog.cpp
+++ b/src/createinstancedialog.cpp
@@ -189,7 +189,7 @@ public:
}
- virtual CreateInstanceDialog::Types selectedType() const
+ virtual CreateInstanceDialog::Types selectedInstanceType() const
{
// no-op
return CreateInstanceDialog::NoType;
@@ -201,7 +201,25 @@ public:
return nullptr;
}
- virtual QString instanceName() const
+ virtual QString selectedGameLocation() const
+ {
+ // no-op
+ return {};
+ }
+
+ virtual QString selectedGameEdition() const
+ {
+ // no-op
+ return {};
+ }
+
+ virtual QString selectedInstanceName() const
+ {
+ // no-op
+ return {};
+ }
+
+ virtual CreateInstanceDialog::Paths selectedPaths() const
{
// no-op
return {};
@@ -250,7 +268,7 @@ public:
return (m_type != CreateInstanceDialog::NoType);
}
- CreateInstanceDialog::Types selectedType() const
+ CreateInstanceDialog::Types selectedInstanceType() const override
{
return m_type;
}
@@ -306,6 +324,15 @@ public:
return m_selection->game;
}
+ QString selectedGameLocation() const override
+ {
+ if (!m_selection) {
+ return {};
+ }
+
+ return m_selection->dir;
+ }
+
void select(MOBase::IPluginGame* game)
{
Game* checked = findGame(game);
@@ -663,7 +690,7 @@ public:
bool skip() const override
{
- auto* g = m_dlg.selectedGame();
+ auto* g = m_dlg.game();
if (!g) {
// shouldn't happen
return true;
@@ -675,7 +702,7 @@ public:
void activated() override
{
- auto* g = m_dlg.selectedGame();
+ auto* g = m_dlg.game();
if (m_previousGame != g) {
m_previousGame = g;
@@ -698,6 +725,22 @@ public:
updateNavigation();
}
+ QString selectedGameEdition() const override
+ {
+ auto* g = m_dlg.game();
+ if (!g) {
+ // shouldn't happen
+ return {};
+ }
+
+ const auto variants = g->gameVariants();
+ if (variants.size() < 2) {
+ return {};
+ } else {
+ return m_selection;
+ }
+ }
+
private:
MOBase::IPluginGame* m_previousGame;
std::vector m_buttons;
@@ -708,7 +751,7 @@ private:
ui->editions->clear();
m_buttons.clear();
- auto* g = m_dlg.selectedGame();
+ auto* g = m_dlg.game();
if (!g) {
// shouldn't happen
return;
@@ -750,12 +793,12 @@ public:
bool skip() const override
{
- return (m_dlg.selectedType() == CreateInstanceDialog::Portable);
+ return (m_dlg.instanceType() == CreateInstanceDialog::Portable);
}
void activated() override
{
- auto* g = m_dlg.selectedGame();
+ auto* g = m_dlg.game();
if (!g) {
// shouldn't happen, next should be disabled
return;
@@ -772,7 +815,7 @@ public:
updateWarnings();
}
- QString instanceName() const override
+ QString selectedInstanceName() const override
{
if (!m_okay) {
return {};
@@ -827,7 +870,7 @@ public:
bool skip() const override
{
- return (m_dlg.selectedType() == CreateInstanceDialog::Portable);
+ return (m_dlg.instanceType() == CreateInstanceDialog::Portable);
}
bool ready() const override
@@ -846,6 +889,23 @@ public:
m_lastInstanceName = name;
}
+ CreateInstanceDialog::Paths selectedPaths() const override
+ {
+ CreateInstanceDialog::Paths p;
+
+ if (ui->advancedPathOptions->isChecked()) {
+ p.base = ui->base->text();
+ p.downloads = ui->downloads->text();
+ p.mods = ui->mods->text();
+ p.profiles = ui->profiles->text();
+ p.overwrite = ui->overwrite->text();
+ } else {
+ p.base = ui->location->text();
+ }
+
+ return p;
+ }
+
private:
PathChecker m_checker, m_advancedChecker;
QString m_lastInstanceName;
@@ -918,6 +978,82 @@ private:
}
};
+
+class ConfirmationPage : public Page
+{
+public:
+ ConfirmationPage(CreateInstanceDialog& dlg)
+ : Page(dlg)
+ {
+ }
+
+ void activated() override
+ {
+ ui->review->setPlainText(makeReview());
+ }
+
+ QString makeReview() const
+ {
+ QStringList lines;
+
+ const auto paths = m_dlg.paths();
+
+ // type
+ switch (m_dlg.instanceType())
+ {
+ case CreateInstanceDialog::Global:
+ {
+ lines.push_back(QObject::tr("Instance type: %1").arg(QObject::tr("Global")));
+ lines.push_back(QObject::tr("Instance name: %1").arg(m_dlg.instanceName()));
+
+ if (paths.downloads.isEmpty()) {
+ // simple settings
+ lines.push_back(QObject::tr("Instance location: %1").arg(paths.base));
+ } else {
+ // advanced settings
+ lines.push_back(QObject::tr("Instance base folder: %1").arg(paths.base));
+ lines.push_back(dirLine(QObject::tr("Downloads"), paths.downloads));
+ lines.push_back(dirLine(QObject::tr("Mods"), paths.mods));
+ lines.push_back(dirLine(QObject::tr("Profiles"), paths.profiles));
+ lines.push_back(dirLine(QObject::tr("Overwrite"), paths.overwrite));
+ }
+
+ break;
+ }
+
+ case CreateInstanceDialog::Portable:
+ {
+ lines.push_back(QObject::tr("Instance type: %1").arg(QObject::tr("Portable")));
+ lines.push_back(QObject::tr("Instance location: %1").arg(qApp->applicationDirPath()));
+ break;
+ }
+
+ default:
+ {
+ lines.push_back(QObject::tr("Instance type: %1").arg(QObject::tr("?")));
+ }
+ }
+
+ // game
+ MOBase::IPluginGame* game = m_dlg.game();
+
+ QString name = game->gameName();
+ if (!m_dlg.gameEdition().isEmpty()) {
+ name += " (" + m_dlg.gameEdition() + ")";
+ }
+
+ lines.push_back(QObject::tr("Game: %1").arg(name));
+ lines.push_back(QObject::tr("Game location: %1").arg(m_dlg.gameLocation()));
+
+ return lines.join("\n");
+ }
+
+ QString dirLine(const QString& caption, const QString& path) const
+ {
+ return QString(" - %1: %2").arg(caption).arg(path);
+ }
+};
+
} // namespace
@@ -936,7 +1072,7 @@ CreateInstanceDialog::CreateInstanceDialog(
m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
- m_pages.push_back(std::make_unique(*this));
+ m_pages.push_back(std::make_unique(*this));
ui->pages->setCurrentIndex(0);
@@ -1052,37 +1188,32 @@ void CreateInstanceDialog::updateNavigation()
}
}
-CreateInstanceDialog::Types CreateInstanceDialog::selectedType() const
+CreateInstanceDialog::Types CreateInstanceDialog::instanceType() const
{
- for (auto&& p : m_pages) {
- const auto t = p->selectedType();
- if (t != NoType) {
- return t;
- }
- }
+ return getSelected(&cid::Page::selectedInstanceType);
+}
- return NoType;
+MOBase::IPluginGame* CreateInstanceDialog::game() const
+{
+ return getSelected(&cid::Page::selectedGame);
}
-MOBase::IPluginGame* CreateInstanceDialog::selectedGame() const
+QString CreateInstanceDialog::gameLocation() const
{
- for (auto&& p : m_pages) {
- if (auto* g=p->selectedGame()) {
- return g;
- }
- }
+ return getSelected(&cid::Page::selectedGameLocation);
+}
- return nullptr;
+QString CreateInstanceDialog::gameEdition() const
+{
+ return getSelected(&cid::Page::selectedGameEdition);
}
QString CreateInstanceDialog::instanceName() const
{
- for (auto&& p : m_pages) {
- const auto s = p->instanceName();
- if (!s.isEmpty()) {
- return s;
- }
- }
+ return getSelected(&cid::Page::selectedInstanceName);
+}
- return {};
+CreateInstanceDialog::Paths CreateInstanceDialog::paths() const
+{
+ return getSelected(&cid::Page::selectedPaths);
}
diff --git a/src/createinstancedialog.h b/src/createinstancedialog.h
index 02608c8d..d9c392ca 100644
--- a/src/createinstancedialog.h
+++ b/src/createinstancedialog.h
@@ -21,6 +21,17 @@ public:
Portable
};
+ struct Paths
+ {
+ QString base;
+ QString downloads;
+ QString mods;
+ QString profiles;
+ QString overwrite;
+
+ auto operator<=>(const Paths&) const = default;
+ };
+
explicit CreateInstanceDialog(
const PluginContainer& pc, QWidget *parent = nullptr);
@@ -38,15 +49,31 @@ public:
void updateNavigation();
bool isOnLastPage() const;
- Types selectedType() const;
- MOBase::IPluginGame* selectedGame() const;
+ Types instanceType() const;
+ MOBase::IPluginGame* game() const;
+ QString gameLocation() const;
+ QString gameEdition() const;
QString instanceName() const;
+ Paths paths() const;
private:
std::unique_ptr ui;
const PluginContainer& m_pc;
std::vector> m_pages;
QString m_originalNext;
+
+ template
+ T getSelected(T (cid::Page::*mf)() const) const
+ {
+ for (auto&& p : m_pages) {
+ const auto t = (p.get()->*mf)();
+ if (t != T()) {
+ return t;
+ }
+ }
+
+ return T();
+ }
};
#endif // MODORGANIZER_CREATEINSTANCEDIALOG_INCLUDED
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index 72d73020..c899a5b7 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -891,11 +891,7 @@
0
-
-
-
- Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
-
-
+
--
cgit v1.3.1
From 4ac8ab98563e223075c1c93852d4112ab6e4579c Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Fri, 24 Jul 2020 15:29:28 -0400
Subject: don't skip paths for portable instance, what am I doing implemented
actual creation removed mentions of %BASE_DIR% everywhere, use constant and
functions from PathSettings
---
modorganizer.natvis | 97 +++++++++++
src/createinstancedialog.cpp | 379 ++++++++++++++++++++++++++++++++++++-------
src/createinstancedialog.h | 20 +++
src/createinstancedialog.ui | 16 +-
src/instancemanager.h | 3 +-
src/settings.cpp | 18 +-
src/settings.h | 12 ++
src/settingsdialog.cpp | 2 +-
src/settingsdialogpaths.cpp | 12 +-
9 files changed, 484 insertions(+), 75 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/modorganizer.natvis b/modorganizer.natvis
index fe4a7ce2..6e21e099 100644
--- a/modorganizer.natvis
+++ b/modorganizer.natvis
@@ -8,5 +8,102 @@ file={m_wsFile}
loaded={m_loaded}
expanded={m_expanded}
}}
+
+ <null>
+ {fileEntry}
+ fileEntry
+
+ - *((Qt5Core.dll!QSharedData *) this)
+ - fileEntry
+
+
+
+
+
+ {*((Qt5Core.dll!QFileInfoPrivate *) d_ptr.d)}
+ *((Qt5Core.dll!QFileInfoPrivate *) d_ptr.d)
+
+ - *((Qt5Core.dll!QFileInfoPrivate *) d_ptr.d)
+
+
+
+
+
+ <null>
+ {m_filePath}
+ m_filePath
+
+
+
+
+
+ <null>
+ {dirEntry}
+ dirEntry
+
+ - *((Qt5Core.dll!QSharedData *) this)
+ - dirEntry
+ - nameFilters
+ - absoluteDirEntry
+
+
+
+
+
+
+ {*((Qt5Core.dll!QDirPrivate *) d_ptr.d)}
+ *((Qt5Core.dll!QDirPrivate *) d_ptr.d)
+
+ - *((Qt5Core.dll!QDirPrivate *) d_ptr.d)
+
+
+
+
+
+ <null>
+ {fileName}
+ fileName
+
+ - *((Qt5Core.dll!QFileDevice *) this)
+ - fileName
+
+
+
+
+
+ {*((Qt5Core.dll!QFilePrivate *) d_ptr.d)}
+ *((Qt5Core.dll!QFilePrivate *) d_ptr.d)
+
+ - *((Qt5Core.dll!QFilePrivate *) d_ptr.d)
+
+
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp
index 8c6605ed..5c85aa68 100644
--- a/src/createinstancedialog.cpp
+++ b/src/createinstancedialog.cpp
@@ -2,13 +2,19 @@
#include "ui_createinstancedialog.h"
#include "instancemanager.h"
#include "plugincontainer.h"
+#include "settings.h"
#include "shared/appconfig.h"
#include
#include
+#include
+
+using namespace MOBase;
namespace cid
{
+using MOBase::TaskDialog;
+
class PathChecker
{
public:
@@ -153,6 +159,12 @@ private:
}
};
+QString makeDefaultPath(const std::wstring& dir)
+{
+ return QDir::toNativeSeparators(
+ PathSettings::makeDefaultPath(QString::fromStdWString(dir)));
+}
+
class Page
{
@@ -195,7 +207,7 @@ public:
return CreateInstanceDialog::NoType;
}
- virtual MOBase::IPluginGame* selectedGame() const
+ virtual IPluginGame* selectedGame() const
{
// no-op
return nullptr;
@@ -315,7 +327,7 @@ public:
return (m_selection != nullptr);
}
- MOBase::IPluginGame* selectedGame() const override
+ IPluginGame* selectedGame() const override
{
if (!m_selection) {
return nullptr;
@@ -330,10 +342,10 @@ public:
return {};
}
- return m_selection->dir;
+ return QDir::toNativeSeparators(m_selection->dir);
}
- void select(MOBase::IPluginGame* game)
+ void select(IPluginGame* game)
{
Game* checked = findGame(game);
@@ -397,12 +409,12 @@ public:
private:
struct Game
{
- MOBase::IPluginGame* game = nullptr;
+ IPluginGame* game = nullptr;
QCommandLinkButton* button = nullptr;
QString dir;
bool installed = false;
- Game(MOBase::IPluginGame* g)
+ Game(IPluginGame* g)
: game(g), installed(g->isInstalled())
{
if (installed) {
@@ -418,11 +430,11 @@ private:
Game* m_selection;
- std::vector sortedGamePlugins() const
+ std::vector sortedGamePlugins() const
{
- std::vector v;
+ std::vector v;
- for (auto* game : m_pc.plugins()) {
+ for (auto* game : m_pc.plugins()) {
v.push_back(game);
}
@@ -433,7 +445,7 @@ private:
return v;
}
- Game* findGame(MOBase::IPluginGame* game)
+ Game* findGame(IPluginGame* game)
{
for (auto& g : m_games) {
if (g->game == game) {
@@ -598,9 +610,9 @@ private:
return g;
}
- MOBase::IPluginGame* findAnotherGame(const QString& path)
+ IPluginGame* findAnotherGame(const QString& path)
{
- for (auto* otherGame : m_pc.plugins()) {
+ for (auto* otherGame : m_pc.plugins()) {
if (otherGame->looksValid(path)) {
return otherGame;
}
@@ -609,9 +621,9 @@ private:
return nullptr;
}
- bool confirmUnknown(const QString& path, MOBase::IPluginGame* game)
+ bool confirmUnknown(const QString& path, IPluginGame* game)
{
- const auto r = MOBase::TaskDialog(&m_dlg)
+ const auto r = TaskDialog(&m_dlg)
.title(QObject::tr("Unrecognized game"))
.main(QObject::tr("Unrecognized game"))
.content(QObject::tr(
@@ -632,11 +644,11 @@ private:
return (r == QMessageBox::Ignore);
}
- MOBase::IPluginGame* confirmOtherGame(
+ IPluginGame* confirmOtherGame(
const QString& path,
- MOBase::IPluginGame* selectedGame, MOBase::IPluginGame* guessedGame)
+ IPluginGame* selectedGame, IPluginGame* guessedGame)
{
- const auto r = MOBase::TaskDialog(&m_dlg)
+ const auto r = TaskDialog(&m_dlg)
.title(QObject::tr("Incorrect game"))
.main(QObject::tr("Incorrect game"))
.content(QObject::tr(
@@ -742,7 +754,7 @@ public:
}
private:
- MOBase::IPluginGame* m_previousGame;
+ IPluginGame* m_previousGame;
std::vector m_buttons;
QString m_selection;
@@ -868,10 +880,6 @@ public:
ui->pathPages->setCurrentIndex(0);
}
- bool skip() const override
- {
- return (m_dlg.instanceType() == CreateInstanceDialog::Portable);
- }
bool ready() const override
{
@@ -934,7 +942,7 @@ private:
bool checkVarPath(QString path) const
{
- path.replace("%BASE_DIR%", ui->base->text());
+ path = PathSettings::resolve(path, ui->base->text());
return checkAdvancedPath(path);
}
@@ -971,11 +979,6 @@ private:
e->setText(path);
}
}
-
- QString makeDefaultPath(const std::wstring& dir)
- {
- return "%BASE_DIR%\\" + QString::fromStdWString(dir);
- }
};
@@ -990,54 +993,52 @@ public:
void activated() override
{
ui->review->setPlainText(makeReview());
+ ui->creationLog->clear();
}
- QString makeReview() const
+ QString toLocalizedString(CreateInstanceDialog::Types t) const
{
- QStringList lines;
-
- const auto paths = m_dlg.paths();
-
- // type
- switch (m_dlg.instanceType())
+ switch (t)
{
case CreateInstanceDialog::Global:
- {
- lines.push_back(QObject::tr("Instance type: %1").arg(QObject::tr("Global")));
- lines.push_back(QObject::tr("Instance name: %1").arg(m_dlg.instanceName()));
-
- if (paths.downloads.isEmpty()) {
- // simple settings
- lines.push_back(QObject::tr("Instance location: %1").arg(paths.base));
- } else {
- // advanced settings
- lines.push_back(QObject::tr("Instance base folder: %1").arg(paths.base));
- lines.push_back(dirLine(QObject::tr("Downloads"), paths.downloads));
- lines.push_back(dirLine(QObject::tr("Mods"), paths.mods));
- lines.push_back(dirLine(QObject::tr("Profiles"), paths.profiles));
- lines.push_back(dirLine(QObject::tr("Overwrite"), paths.overwrite));
- }
-
- break;
- }
+ return QObject::tr("Global");
case CreateInstanceDialog::Portable:
- {
- lines.push_back(QObject::tr("Instance type: %1").arg(QObject::tr("Portable")));
- lines.push_back(QObject::tr("Instance location: %1").arg(qApp->applicationDirPath()));
- break;
- }
+ return QObject::tr("Portable");
default:
- {
- lines.push_back(QObject::tr("Instance type: %1").arg(QObject::tr("?")));
+ return QObject::tr("Instance type: %1").arg(QObject::tr("?"));
+ }
+ }
+
+ QString makeReview() const
+ {
+ QStringList lines;
+ const auto paths = m_dlg.paths();
+
+ lines.push_back(QObject::tr("Instance type: %1").arg(toLocalizedString(m_dlg.instanceType())));
+ lines.push_back(QObject::tr("Instance location: %1").arg(m_dlg.dataPath()));
+
+ if (m_dlg.instanceType() != CreateInstanceDialog::Portable) {
+ lines.push_back(QObject::tr("Instance name: %1").arg(m_dlg.instanceName()));
+ }
+
+ if (paths.downloads.isEmpty()) {
+ // simple settings
+ if (paths.base != m_dlg.dataPath()) {
+ lines.push_back(QObject::tr("Base directory: %1").arg(paths.base));
}
+ } else {
+ // advanced settings
+ lines.push_back(QObject::tr("Base directory: %1").arg(paths.base));
+ lines.push_back(dirLine(QObject::tr("Downloads"), paths.downloads));
+ lines.push_back(dirLine(QObject::tr("Mods"), paths.mods));
+ lines.push_back(dirLine(QObject::tr("Profiles"), paths.profiles));
+ lines.push_back(dirLine(QObject::tr("Overwrite"), paths.overwrite));
}
// game
- MOBase::IPluginGame* game = m_dlg.game();
-
- QString name = game->gameName();
+ QString name = m_dlg.game()->gameName();
if (!m_dlg.gameEdition().isEmpty()) {
name += " (" + m_dlg.gameEdition() + ")";
}
@@ -1157,8 +1158,195 @@ void CreateInstanceDialog::changePage(int d)
}
}
+
+class Failed {};
+
+class DirectoryCreator
+{
+public:
+ DirectoryCreator(const DirectoryCreator&) = delete;
+ DirectoryCreator& operator=(const DirectoryCreator&) = delete;
+
+ static std::unique_ptr create(
+ const QDir& target, std::function log)
+ {
+ return std::unique_ptr(new DirectoryCreator(target, log));
+ }
+
+ ~DirectoryCreator()
+ {
+ rollback();
+ }
+
+ void commit()
+ {
+ m_created.clear();
+ }
+
+ void rollback() noexcept
+ {
+ try
+ {
+ for (auto itor=m_created.rbegin(); itor!=m_created.rend(); ++itor) {
+ const auto r = shell::DeleteDirectoryRecursive(*itor);
+ if (!r) {
+ m_logger(r.toString());
+ }
+ }
+
+ m_created.clear();
+ }
+ catch(...)
+ {
+ // eat it
+ }
+ }
+
+private:
+ std::function m_logger;
+
+ DirectoryCreator(const QDir& target, std::function log)
+ : m_logger(log)
+ {
+ try
+ {
+ const QString s = QDir::toNativeSeparators(target.absolutePath());
+ const QStringList cs = s.split("\\");
+
+ if (cs.empty()) {
+ return;
+ }
+
+ QDir d(cs[0]);
+
+ for (int i=1; i m_created;
+};
+
void CreateInstanceDialog::finish()
{
+ ui->creationLog->clear();
+ logCreation(tr("Creating instance..."));
+
+ const auto& m = InstanceManager::instance();
+ const auto ci = creationInfo();
+
+ auto logger = [&](QString s) {
+ logCreation(s);
+ };
+
+ auto createDir = [&](QString path) {
+ return DirectoryCreator::create(path, logger);
+ };
+
+
+ try
+ {
+ std::vector> dirs;
+
+ dirs.push_back(createDir(ci.dataPath));
+ dirs.push_back(createDir(ci.paths.base));
+ dirs.push_back(createDir(PathSettings::resolve(ci.paths.downloads, ci.paths.base)));
+ dirs.push_back(createDir(PathSettings::resolve(ci.paths.mods, ci.paths.base)));
+ dirs.push_back(createDir(PathSettings::resolve(ci.paths.profiles, ci.paths.base)));
+ dirs.push_back(createDir(PathSettings::resolve(ci.paths.overwrite, ci.paths.base)));
+
+
+ Settings s(ci.iniPath);
+ s.game().setName(ci.game->gameName());
+ s.game().setDirectory(ci.gameLocation);
+
+ if (!ci.gameEdition.isEmpty()) {
+ s.game().setEdition(ci.gameEdition);
+ }
+
+ if (ci.type == Global) {
+ if (ci.paths.base != ci.dataPath) {
+ s.paths().setBase(ci.paths.base);
+ }
+
+ if (ci.paths.downloads != cid::makeDefaultPath(AppConfig::downloadPath())) {
+ s.paths().setDownloads(ci.paths.downloads);
+ }
+
+ if (ci.paths.mods != cid::makeDefaultPath(AppConfig::modsPath())) {
+ s.paths().setMods(ci.paths.mods);
+ }
+
+ if (ci.paths.profiles != cid::makeDefaultPath(AppConfig::profilesPath())) {
+ s.paths().setProfiles(ci.paths.profiles);
+ }
+
+ if (ci.paths.overwrite != cid::makeDefaultPath(AppConfig::overwritePath())) {
+ s.paths().setOverwrite(ci.paths.overwrite);
+ }
+ }
+
+
+ logCreation(tr("Writing %1...").arg(ci.iniPath));
+
+ const auto r = s.sync();
+ if (r != QSettings::NoError) {
+ switch (r)
+ {
+ case QSettings::AccessError:
+ logCreation(formatSystemMessage(ERROR_ACCESS_DENIED));
+ break;
+
+ case QSettings::FormatError:
+ logCreation(tr("Format error."));
+ break;
+
+ default:
+ logCreation(tr("Error %1.").arg(static_cast(r)));
+ break;
+ }
+
+ throw Failed();
+ }
+
+ for (auto& d : dirs) {
+ d->commit();
+ }
+
+ logCreation(tr("Done."));
+ }
+ catch(Failed&)
+ {
+ }
+}
+
+void CreateInstanceDialog::logCreation(const QString& s)
+{
+ ui->creationLog->insertPlainText(s + "\n");
+}
+
+void CreateInstanceDialog::logCreation(const std::wstring& s)
+{
+ logCreation(QString::fromStdWString(s));
}
void CreateInstanceDialog::selectPage(std::size_t i)
@@ -1213,7 +1401,72 @@ QString CreateInstanceDialog::instanceName() const
return getSelected(&cid::Page::selectedInstanceName);
}
+QString CreateInstanceDialog::dataPath() const
+{
+ QString s;
+
+ if (instanceType() == Portable) {
+ s = QDir(qApp->applicationDirPath()).absolutePath();
+ } else {
+ s = InstanceManager::instance().instancePath(instanceName());
+ }
+
+ return QDir::toNativeSeparators(s);
+}
+
CreateInstanceDialog::Paths CreateInstanceDialog::paths() const
{
return getSelected(&cid::Page::selectedPaths);
}
+
+CreateInstanceDialog::CreationInfo CreateInstanceDialog::creationInfo() const
+{
+ CreationInfo ci;
+
+ ci.type = getSelected(&cid::Page::selectedInstanceType);
+ ci.game = getSelected(&cid::Page::selectedGame);
+ ci.gameLocation = getSelected(&cid::Page::selectedGameLocation);
+ ci.gameEdition = getSelected(&cid::Page::selectedGameEdition);
+ ci.instanceName = getSelected(&cid::Page::selectedInstanceName);
+ ci.paths = getSelected(&cid::Page::selectedPaths);
+ ci.dataPath = dataPath();
+
+ ci.paths.base = QDir(ci.paths.base).absolutePath();
+
+ if (ci.paths.downloads.isEmpty()) {
+ ci.paths.downloads = cid::makeDefaultPath(AppConfig::downloadPath());
+ } else if (!ci.paths.downloads.contains(PathSettings::BaseDirVariable)) {
+ ci.paths.downloads = QDir(ci.paths.downloads).absolutePath();
+ }
+
+ if (ci.paths.mods.isEmpty()) {
+ ci.paths.mods = cid::makeDefaultPath(AppConfig::modsPath());
+ } else if (!ci.paths.mods.contains(PathSettings::BaseDirVariable)) {
+ ci.paths.mods = QDir(ci.paths.mods).absolutePath();
+ }
+
+ if (ci.paths.profiles.isEmpty()) {
+ ci.paths.profiles = cid::makeDefaultPath(AppConfig::profilesPath());
+ } else if (!ci.paths.profiles.contains(PathSettings::BaseDirVariable)) {
+ ci.paths.profiles = QDir(ci.paths.profiles).absolutePath();
+ }
+
+ if (ci.paths.overwrite.isEmpty()) {
+ ci.paths.overwrite = cid::makeDefaultPath(AppConfig::overwritePath());
+ } else if (!ci.paths.overwrite.contains(PathSettings::BaseDirVariable)) {
+ ci.paths.overwrite = QDir(ci.paths.overwrite).absolutePath();
+ }
+
+ ci.iniPath = QFileInfo(
+ ci.dataPath + "/" + QString::fromStdWString(AppConfig::iniFileName()))
+ .absoluteFilePath();
+
+ ci.paths.base = QDir::toNativeSeparators(ci.paths.base);
+ ci.paths.downloads = QDir::toNativeSeparators(ci.paths.downloads);
+ ci.paths.mods = QDir::toNativeSeparators(ci.paths.mods);
+ ci.paths.profiles = QDir::toNativeSeparators(ci.paths.profiles);
+ ci.paths.overwrite = QDir::toNativeSeparators(ci.paths.overwrite);
+ ci.paths.ini = QDir::toNativeSeparators(ci.paths.ini);
+
+ return ci;
+}
diff --git a/src/createinstancedialog.h b/src/createinstancedialog.h
index d9c392ca..2f5774ae 100644
--- a/src/createinstancedialog.h
+++ b/src/createinstancedialog.h
@@ -28,10 +28,24 @@ public:
QString mods;
QString profiles;
QString overwrite;
+ QString ini;
auto operator<=>(const Paths&) const = default;
};
+ struct CreationInfo
+ {
+ Types type;
+ MOBase::IPluginGame* game;
+ QString gameLocation;
+ QString gameEdition;
+ QString instanceName;
+ QString dataPath;
+ QString iniPath;
+ Paths paths;
+ };
+
+
explicit CreateInstanceDialog(
const PluginContainer& pc, QWidget *parent = nullptr);
@@ -54,8 +68,11 @@ public:
QString gameLocation() const;
QString gameEdition() const;
QString instanceName() const;
+ QString dataPath() const;
Paths paths() const;
+ CreationInfo creationInfo() const;
+
private:
std::unique_ptr ui;
const PluginContainer& m_pc;
@@ -74,6 +91,9 @@ private:
return T();
}
+
+ void logCreation(const QString& s);
+ void logCreation(const std::wstring& s);
};
#endif // MODORGANIZER_CREATEINSTANCEDIALOG_INCLUDED
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index c899a5b7..cfb343fa 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -891,7 +891,21 @@
0
-
-
+
+
+ QTextEdit::NoWrap
+
+
+
+ -
+
+
+ QTextEdit::NoWrap
+
+
+ Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
+
+
diff --git a/src/instancemanager.h b/src/instancemanager.h
index 0cd5ef4c..6a6b52ac 100644
--- a/src/instancemanager.h
+++ b/src/instancemanager.h
@@ -56,13 +56,12 @@ public:
QString sanitizeInstanceName(const QString &name) const;
QString makeUniqueName(const QString& instanceName) const;
bool instanceExists(const QString& instanceName) const;
+ QString instancePath(const QString& instanceName) const;
private:
InstanceManager();
- QString instancePath(const QString& instanceName) const;
-
bool deleteLocalInstance(const QString &instanceId) const;
QString manageInstances(const QStringList &instanceList) const;
diff --git a/src/settings.cpp b/src/settings.cpp
index 8db9c623..661cf429 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -1464,6 +1464,8 @@ QSet PluginSettings::readBlacklist() const
}
+const QString PathSettings::BaseDirVariable = "%BASE_DIR%";
+
PathSettings::PathSettings(QSettings& settings)
: m_Settings(settings)
{
@@ -1511,10 +1513,10 @@ QString PathSettings::getConfigurablePath(const QString &key,
bool resolve) const
{
QString result = QDir::fromNativeSeparators(
- get(m_Settings, "Settings", key, QString("%BASE_DIR%/") + def));
+ get(m_Settings, "Settings", key, makeDefaultPath(def)));
if (resolve) {
- result.replace("%BASE_DIR%", base());
+ result = PathSettings::resolve(result, base());
}
return result;
@@ -1529,6 +1531,18 @@ void PathSettings::setConfigurablePath(const QString &key, const QString& path)
}
}
+QString PathSettings::resolve(const QString& path, const QString& baseDir)
+{
+ QString s = path;
+ s.replace(BaseDirVariable, baseDir);
+ return s;
+}
+
+QString PathSettings::makeDefaultPath(const QString dirName)
+{
+ return BaseDirVariable + "/" + dirName;
+}
+
QString PathSettings::base() const
{
return QDir::fromNativeSeparators(get(m_Settings,
diff --git a/src/settings.h b/src/settings.h
index a8c527d6..c723faec 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -391,6 +391,9 @@ private:
class PathSettings
{
public:
+ // %BASE_DIR%
+ static const QString BaseDirVariable;
+
PathSettings(QSettings& settings);
QString base() const;
@@ -418,6 +421,15 @@ public:
std::map recent() const;
void setRecent(const std::map& map);
+
+ // resolves %BASE_DIR%
+ //
+ static QString resolve(const QString& path, const QString& baseDir);
+
+ // returns %BASE_DIR%/dirName
+ //
+ static QString makeDefaultPath(const QString dirName);
+
private:
QSettings& m_Settings;
diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp
index 87c7201d..c4a53fcd 100644
--- a/src/settingsdialog.cpp
+++ b/src/settingsdialog.cpp
@@ -114,7 +114,7 @@ QString SettingsDialog::getColoredButtonStyleSheet() const
void SettingsDialog::accept()
{
QString newModPath = ui->modDirEdit->text();
- newModPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+ newModPath = PathSettings::resolve(newModPath, ui->baseDirEdit->text());
if ((QDir::fromNativeSeparators(newModPath) !=
QDir::fromNativeSeparators(
diff --git a/src/settingsdialogpaths.cpp b/src/settingsdialogpaths.cpp
index 74ba4f25..eb334541 100644
--- a/src/settingsdialogpaths.cpp
+++ b/src/settingsdialogpaths.cpp
@@ -64,7 +64,7 @@ void PathsSettingsTab::update()
std::tie(path, setter, defaultName) = dir;
QString realPath = path;
- realPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+ realPath = PathSettings::resolve(realPath, ui->baseDirEdit->text());
if (!QDir(realPath).exists()) {
if (!QDir().mkpath(realPath)) {
@@ -113,7 +113,7 @@ void PathsSettingsTab::on_browseBaseDirBtn_clicked()
void PathsSettingsTab::on_browseDownloadDirBtn_clicked()
{
QString searchPath = ui->downloadDirEdit->text();
- searchPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+ searchPath = PathSettings::resolve(searchPath, ui->baseDirEdit->text());
QString temp = QFileDialog::getExistingDirectory(&dialog(), QObject::tr("Select download directory"), searchPath);
if (!temp.isEmpty()) {
@@ -124,7 +124,7 @@ void PathsSettingsTab::on_browseDownloadDirBtn_clicked()
void PathsSettingsTab::on_browseModDirBtn_clicked()
{
QString searchPath = ui->modDirEdit->text();
- searchPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+ searchPath = PathSettings::resolve(searchPath, ui->baseDirEdit->text());
QString temp = QFileDialog::getExistingDirectory(&dialog(), QObject::tr("Select mod directory"), searchPath);
if (!temp.isEmpty()) {
@@ -135,7 +135,7 @@ void PathsSettingsTab::on_browseModDirBtn_clicked()
void PathsSettingsTab::on_browseCacheDirBtn_clicked()
{
QString searchPath = ui->cacheDirEdit->text();
- searchPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+ searchPath = PathSettings::resolve(searchPath, ui->baseDirEdit->text());
QString temp = QFileDialog::getExistingDirectory(&dialog(), QObject::tr("Select cache directory"), searchPath);
if (!temp.isEmpty()) {
@@ -146,7 +146,7 @@ void PathsSettingsTab::on_browseCacheDirBtn_clicked()
void PathsSettingsTab::on_browseProfilesDirBtn_clicked()
{
QString searchPath = ui->profilesDirEdit->text();
- searchPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+ searchPath = PathSettings::resolve(searchPath, ui->baseDirEdit->text());
QString temp = QFileDialog::getExistingDirectory(&dialog(), QObject::tr("Select profiles directory"), searchPath);
if (!temp.isEmpty()) {
@@ -157,7 +157,7 @@ void PathsSettingsTab::on_browseProfilesDirBtn_clicked()
void PathsSettingsTab::on_browseOverwriteDirBtn_clicked()
{
QString searchPath = ui->overwriteDirEdit->text();
- searchPath.replace("%BASE_DIR%", ui->baseDirEdit->text());
+ searchPath = PathSettings::resolve(searchPath, ui->baseDirEdit->text());
QString temp = QFileDialog::getExistingDirectory(&dialog(), QObject::tr("Select overwrite directory"), searchPath);
if (!temp.isEmpty()) {
--
cgit v1.3.1
From cfdfa9d40e09d509396f57fbf70b48fa2136c230 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Sat, 25 Jul 2020 21:17:24 -0400
Subject: PathChecker is unnecessary, refactored its guts into NamePage and
PathsPage made existing paths just a warning, don't check for portable
instances
---
src/createinstancedialog.cpp | 72 ++++++-----
src/createinstancedialog.ui | 8 +-
src/createinstancedialogpages.cpp | 250 ++++++++++++++++++++++----------------
src/createinstancedialogpages.h | 39 +++---
src/instancemanager.cpp | 7 +-
src/instancemanager.h | 1 +
6 files changed, 205 insertions(+), 172 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp
index 63be7346..4b9f24ae 100644
--- a/src/createinstancedialog.cpp
+++ b/src/createinstancedialog.cpp
@@ -2,10 +2,8 @@
#include "ui_createinstancedialog.h"
#include "createinstancedialogpages.h"
#include "instancemanager.h"
-//#include "plugincontainer.h"
#include "settings.h"
#include "shared/appconfig.h"
-//#include
#include
#include
@@ -80,6 +78,9 @@ void CreateInstanceDialog::changePage(int d)
{
std::size_t i = static_cast(ui->pages->currentIndex());
+ // goes back or forwards until an unskippable page is reached, or the
+ // first/last page
+
if (d > 0) {
for (;;) {
++i;
@@ -359,7 +360,7 @@ QString CreateInstanceDialog::dataPath() const
QString s;
if (instanceType() == Portable) {
- s = QDir(qApp->applicationDirPath()).absolutePath();
+ s = QDir(InstanceManager::portablePath()).absolutePath();
} else {
s = InstanceManager::instance().instancePath(instanceName());
}
@@ -372,8 +373,31 @@ CreateInstanceDialog::Paths CreateInstanceDialog::paths() const
return getSelected(&cid::Page::selectedPaths);
}
+void fixVarDir(QString& path, const std::wstring& defaultDir)
+{
+ if (path.isEmpty()) {
+ path = cid::makeDefaultPath(defaultDir);
+ } else if (!path.contains(PathSettings::BaseDirVariable)) {
+ path = QDir(path).absolutePath();
+ }
+
+ path = QDir::toNativeSeparators(path);
+}
+
+void fixDirPath(QString& path)
+{
+ path = QDir::toNativeSeparators(QDir(path).absolutePath());
+}
+
+void fixFilePath(QString& path)
+{
+ path = QDir::toNativeSeparators(QFileInfo(path).absolutePath());
+}
+
CreateInstanceDialog::CreationInfo CreateInstanceDialog::creationInfo() const
{
+ const auto iniFilename = QString::fromStdWString(AppConfig::iniFileName());
+
CreationInfo ci;
ci.type = getSelected(&cid::Page::selectedInstanceType);
@@ -383,43 +407,15 @@ CreateInstanceDialog::CreationInfo CreateInstanceDialog::creationInfo() const
ci.instanceName = getSelected(&cid::Page::selectedInstanceName);
ci.paths = getSelected(&cid::Page::selectedPaths);
ci.dataPath = dataPath();
+ ci.iniPath = ci.dataPath + "/" + iniFilename;
- ci.paths.base = QDir(ci.paths.base).absolutePath();
-
- if (ci.paths.downloads.isEmpty()) {
- ci.paths.downloads = cid::makeDefaultPath(AppConfig::downloadPath());
- } else if (!ci.paths.downloads.contains(PathSettings::BaseDirVariable)) {
- ci.paths.downloads = QDir(ci.paths.downloads).absolutePath();
- }
-
- if (ci.paths.mods.isEmpty()) {
- ci.paths.mods = cid::makeDefaultPath(AppConfig::modsPath());
- } else if (!ci.paths.mods.contains(PathSettings::BaseDirVariable)) {
- ci.paths.mods = QDir(ci.paths.mods).absolutePath();
- }
-
- if (ci.paths.profiles.isEmpty()) {
- ci.paths.profiles = cid::makeDefaultPath(AppConfig::profilesPath());
- } else if (!ci.paths.profiles.contains(PathSettings::BaseDirVariable)) {
- ci.paths.profiles = QDir(ci.paths.profiles).absolutePath();
- }
-
- if (ci.paths.overwrite.isEmpty()) {
- ci.paths.overwrite = cid::makeDefaultPath(AppConfig::overwritePath());
- } else if (!ci.paths.overwrite.contains(PathSettings::BaseDirVariable)) {
- ci.paths.overwrite = QDir(ci.paths.overwrite).absolutePath();
- }
-
- ci.iniPath = QFileInfo(
- ci.dataPath + "/" + QString::fromStdWString(AppConfig::iniFileName()))
- .absoluteFilePath();
+ fixDirPath(ci.paths.base);
+ fixFilePath(ci.paths.ini);
- ci.paths.base = QDir::toNativeSeparators(ci.paths.base);
- ci.paths.downloads = QDir::toNativeSeparators(ci.paths.downloads);
- ci.paths.mods = QDir::toNativeSeparators(ci.paths.mods);
- ci.paths.profiles = QDir::toNativeSeparators(ci.paths.profiles);
- ci.paths.overwrite = QDir::toNativeSeparators(ci.paths.overwrite);
- ci.paths.ini = QDir::toNativeSeparators(ci.paths.ini);
+ fixVarDir(ci.paths.downloads, AppConfig::downloadPath());
+ fixVarDir(ci.paths.mods, AppConfig::modsPath());
+ fixVarDir(ci.paths.profiles, AppConfig::profilesPath());
+ fixVarDir(ci.paths.overwrite, AppConfig::overwritePath());
return ci;
}
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index cfb343fa..4d9d8b06 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -588,7 +588,7 @@
-
- This folder already exists.
+ Warning: This folder already exists.
@@ -602,7 +602,7 @@
-
- The folder contains invalid characters.
+ Warning: The folder contains invalid characters.
@@ -706,7 +706,7 @@
-
- The folder %1 already exists.
+ Warning: The folder %1 already exists.
true
@@ -778,7 +778,7 @@
-
- The folder %1 contains invalid characters.
+ Warning: The folder %1 contains invalid characters.
true
diff --git a/src/createinstancedialogpages.cpp b/src/createinstancedialogpages.cpp
index ab020c66..4d2c5b8b 100644
--- a/src/createinstancedialogpages.cpp
+++ b/src/createinstancedialogpages.cpp
@@ -15,19 +15,11 @@ using MOBase::TaskDialog;
QString makeDefaultPath(const std::wstring& dir)
{
- return QDir::toNativeSeparators(
- PathSettings::makeDefaultPath(QString::fromStdWString(dir)));
+ return QDir::toNativeSeparators(PathSettings::makeDefaultPath(
+ QString::fromStdWString(dir)));
}
-
-PathChecker::PathChecker(QLabel* existsLabel, QLabel* invalidLabel)
- : m_exists(existsLabel), m_invalid(invalidLabel)
-{
- m_existsOriginal = m_exists->text();
- m_invalidOriginal = m_invalid->text();
-}
-
-QString PathChecker::sanitizeFileName(const QString& name) const
+QString sanitizeFileName(const QString& name)
{
QString new_name = name;
@@ -48,7 +40,7 @@ QString PathChecker::sanitizeFileName(const QString& name) const
// same thing as above, but allows path separators and colons
//
-QString PathChecker::sanitizePath(const QString& path) const
+QString sanitizePath(const QString& path)
{
QString new_name = path;
@@ -67,93 +59,31 @@ QString PathChecker::sanitizePath(const QString& path) const
return new_name;
}
-bool PathChecker::checkName(QString parentDir, QString name) const
+void setPossiblePlaceholder(
+ QLabel* label, const QString& s, const QString& arg)
{
- bool exists = false;
- bool invalid = false;
- bool empty = false;
-
- name = name.trimmed();
-
- if (name.isEmpty()) {
- empty = true;
- } else {
- const QString sanitized = sanitizeFileName(name);
-
- if (name != sanitized) {
- invalid = true;
- } else {
- exists = QDir(parentDir).exists(name);
- }
- }
+}
- bool okay = false;
- if (exists) {
- m_exists->setVisible(true);
- setPossiblePlaceholder(m_exists, m_existsOriginal, QDir(parentDir).filePath(name));
- m_invalid->setVisible(false);
- } else if (invalid) {
- m_exists->setVisible(false);
- m_invalid->setVisible(true);
- setPossiblePlaceholder(m_invalid, m_invalidOriginal, name);
- } else {
- okay = !empty;
- m_exists->setVisible(false);
- m_invalid->setVisible(false);
- }
-
- return okay;
+PlaceholderLabel::PlaceholderLabel(QLabel* label)
+ : m_label(label), m_original(label->text())
+{
}
-bool PathChecker::checkPath(QString path) const
+void PlaceholderLabel::setText(const QString& arg)
{
- bool exists = false;
- bool invalid = false;
- bool empty = false;
-
- path = path.trimmed();
-
- if (path.isEmpty()) {
- empty = true;
- } else {
- const QString sanitized = sanitizePath(path);
-
- if (path != sanitized) {
- invalid = true;
- } else {
- exists = QDir(path).exists();
- }
- }
-
- bool okay = false;
-
- if (exists) {
- m_exists->setVisible(true);
- setPossiblePlaceholder(m_exists, m_existsOriginal, path);
- m_invalid->setVisible(false);
- } else if (invalid) {
- m_exists->setVisible(false);
- m_invalid->setVisible(true);
- setPossiblePlaceholder(m_invalid, m_invalidOriginal, path);
- } else {
- okay = !empty;
- m_exists->setVisible(false);
- m_invalid->setVisible(false);
+ if (m_original.contains("%1")) {
+ m_label->setText(m_original.arg(arg));
}
-
- return okay;
}
-void PathChecker::setPossiblePlaceholder(
- QLabel* label, const QString& s, const QString& arg) const
+void PlaceholderLabel::setVisible(bool b)
{
- if (label->text().contains("%1")) {
- label->setText(s.arg(arg));
- }
+ m_label->setVisible(b);
}
+
Page::Page(CreateInstanceDialog& dlg)
: ui(dlg.getUI()), m_dlg(dlg), m_pc(dlg.pluginContainer())
{
@@ -238,7 +168,7 @@ TypePage::TypePage(CreateInstanceDialog& dlg)
ui->createPortable->setDescription(
ui->createPortable->description()
- .arg(qApp->applicationDirPath()));
+ .arg(InstanceManager::portablePath()));
QObject::connect(
ui->createGlobal, &QAbstractButton::clicked, [&]{ global(); });
@@ -727,10 +657,9 @@ void EditionsPage::fillList()
NamePage::NamePage(CreateInstanceDialog& dlg) :
Page(dlg), m_modified(false), m_okay(false),
- m_checker(ui->instanceNameExists, ui->instanceNameInvalid)
+ m_label(ui->instanceNameLabel), m_exists(ui->instanceNameExists),
+ m_invalid(ui->instanceNameInvalid)
{
- m_originalLabel = ui->instanceNameLabel->text();
-
QObject::connect(
ui->instanceName, &QLineEdit::textEdited, [&]{ onChanged(); });
}
@@ -753,7 +682,7 @@ void NamePage::activated()
return;
}
- ui->instanceNameLabel->setText(m_originalLabel.arg(g->gameName()));
+ m_label.setText(g->gameName());
if (!m_modified || ui->instanceName->text().isEmpty()) {
const auto n = InstanceManager::instance().makeUniqueName(g->gameName());
@@ -771,7 +700,7 @@ QString NamePage::selectedInstanceName() const
}
const auto text = ui->instanceName->text().trimmed();
- return m_checker.sanitizeFileName(text);
+ return sanitizeFileName(text);
}
void NamePage::onChanged()
@@ -784,15 +713,55 @@ void NamePage::updateWarnings()
{
const auto root = InstanceManager::instance().instancesPath();
- m_okay = m_checker.checkName(root, ui->instanceName->text());
+ m_okay = checkName(root, ui->instanceName->text());
updateNavigation();
}
+bool NamePage::checkName(QString parentDir, QString name)
+{
+ bool exists = false;
+ bool invalid = false;
+ bool empty = false;
+
+ name = name.trimmed();
+
+ if (name.isEmpty()) {
+ empty = true;
+ } else {
+ const QString sanitized = sanitizeFileName(name);
+
+ if (name != sanitized) {
+ invalid = true;
+ } else {
+ exists = QDir(parentDir).exists(name);
+ }
+ }
+
+ bool okay = false;
+
+ if (exists) {
+ m_exists.setVisible(true);
+ m_exists.setText(QDir(parentDir).filePath(name));
+ m_invalid.setVisible(false);
+ } else if (invalid) {
+ m_exists.setVisible(false);
+ m_invalid.setVisible(true);
+ m_invalid.setText(name);
+ } else {
+ okay = !empty;
+ m_exists.setVisible(false);
+ m_invalid.setVisible(false);
+ }
+
+ return okay;
+}
+
PathsPage::PathsPage(CreateInstanceDialog& dlg) :
- Page(dlg),
- m_checker(ui->locationExists, ui->locationInvalid),
- m_advancedChecker(ui->advancedDirExists, ui->advancedDirInvalid)
+ Page(dlg), m_lastType(CreateInstanceDialog::NoType),
+ m_simpleExists(ui->locationExists), m_simpleInvalid(ui->locationInvalid),
+ m_advancedExists(ui->advancedDirExists),
+ m_advancedInvalid(ui->advancedDirInvalid)
{
QObject::connect(ui->location, &QLineEdit::textEdited, [&]{ onChanged(); });
QObject::connect(ui->base, &QLineEdit::textEdited, [&]{ onChanged(); });
@@ -816,12 +785,16 @@ bool PathsPage::ready() const
void PathsPage::activated()
{
const auto name = m_dlg.instanceName();
+ const auto type = m_dlg.instanceType();
- setPaths(name, (m_lastInstanceName != name));
+ const bool changed = (m_lastInstanceName != name) || (m_lastType != type);
+
+ setPaths(name, changed);
checkPaths();
updateNavigation();
m_lastInstanceName = name;
+ m_lastType = type;
}
CreateInstanceDialog::Paths PathsPage::selectedPaths() const
@@ -852,21 +825,23 @@ bool PathsPage::checkPaths() const
if (ui->advancedPathOptions->isChecked()) {
return
checkAdvancedPath(ui->base->text()) &&
- checkVarPath(ui->downloads->text());
+ checkAdvancedPath(resolve(ui->downloads->text())) &&
+ checkAdvancedPath(resolve(ui->mods->text())) &&
+ checkAdvancedPath(resolve(ui->profiles->text())) &&
+ checkAdvancedPath(resolve(ui->overwrite->text()));
} else {
- return m_checker.checkPath(ui->location->text());
+ return checkPath(ui->location->text(), m_simpleExists, m_simpleInvalid);
}
}
bool PathsPage::checkAdvancedPath(const QString& path) const
{
- return m_advancedChecker.checkPath(path);
+ return checkPath(path, m_advancedExists, m_advancedInvalid);
}
-bool PathsPage::checkVarPath(QString path) const
+QString PathsPage::resolve(const QString& path) const
{
- path = PathSettings::resolve(path, ui->base->text());
- return checkAdvancedPath(path);
+ return PathSettings::resolve(path, ui->base->text());
}
void PathsPage::onAdvanced()
@@ -884,12 +859,20 @@ void PathsPage::onAdvanced()
void PathsPage::setPaths(const QString& name, bool force)
{
- const auto root = InstanceManager::instance().instancesPath();
- const auto path = QDir::toNativeSeparators(root + "/" + name);
+ QString path;
- setIfEmpty(ui->location, path, force);
+ if (m_dlg.instanceType() == CreateInstanceDialog::Portable) {
+ path = InstanceManager::portablePath();
+ } else {
+ const auto root = InstanceManager::instance().instancesPath();
+ path = root + "/" + name;
+ }
+ path = QDir::toNativeSeparators(QDir(path).canonicalPath());
+
+ setIfEmpty(ui->location, path, force);
setIfEmpty(ui->base, path, force);
+
setIfEmpty(ui->downloads, makeDefaultPath(AppConfig::downloadPath()), force);
setIfEmpty(ui->mods, makeDefaultPath(AppConfig::modsPath()), force);
setIfEmpty(ui->profiles, makeDefaultPath(AppConfig::profilesPath()), force);
@@ -903,6 +886,61 @@ void PathsPage::setIfEmpty(QLineEdit* e, const QString& path, bool force)
}
}
+bool PathsPage::checkPath(
+ QString path,
+ PlaceholderLabel& existsLabel, PlaceholderLabel& invalidLabel) const
+{
+ bool exists = false;
+ bool invalid = false;
+ bool empty = false;
+
+ path = QDir::toNativeSeparators(path.trimmed());
+
+ if (path.isEmpty()) {
+ empty = true;
+ } else {
+ const QString sanitized = sanitizePath(path);
+
+ if (path != sanitized) {
+ invalid = true;
+ } else {
+ if (m_dlg.instanceType() == CreateInstanceDialog::Portable) {
+ // the default data path for a portable instance is the application
+ // directory, so it's not an error if it exists
+ if (QDir(path) != InstanceManager::instance().portablePath()) {
+ exists = QDir(path).exists();
+ }
+ } else {
+ exists = QDir(path).exists();
+ }
+ }
+ }
+
+ bool okay = true;
+
+ if (invalid) {
+ okay = false;
+ existsLabel.setVisible(false);
+ invalidLabel.setVisible(true);
+ invalidLabel.setText(path);
+ } else if (empty) {
+ okay = false;
+ existsLabel.setVisible(false);
+ invalidLabel.setVisible(false);
+ } else if (exists) {
+ // this is just a warning
+ existsLabel.setVisible(true);
+ existsLabel.setText(path);
+ invalidLabel.setVisible(false);
+ } else {
+ okay = true;
+ existsLabel.setVisible(false);
+ invalidLabel.setVisible(false);
+ }
+
+ return okay;
+}
+
ConfirmationPage::ConfirmationPage(CreateInstanceDialog& dlg)
: Page(dlg)
diff --git a/src/createinstancedialogpages.h b/src/createinstancedialogpages.h
index 0baff666..0d210493 100644
--- a/src/createinstancedialogpages.h
+++ b/src/createinstancedialogpages.h
@@ -13,29 +13,17 @@ namespace cid
QString makeDefaultPath(const std::wstring& dir);
-class PathChecker
+
+class PlaceholderLabel
{
public:
- PathChecker(QLabel* existsLabel, QLabel* invalidLabel);
-
- QString sanitizeFileName(const QString& name) const;
-
- // same thing as above, but allows path separators and colons
- //
- QString sanitizePath(const QString& path) const;
-
- bool checkName(QString parentDir, QString name) const;
- bool checkPath(QString path) const;
+ PlaceholderLabel(QLabel* label);
+ void setText(const QString& arg);
+ void setVisible(bool b);
private:
- QLabel* m_exists;
- QString m_existsOriginal;
-
- QLabel* m_invalid;
- QString m_invalidOriginal;
-
- void setPossiblePlaceholder(
- QLabel* label, const QString& s, const QString& arg) const;
+ QLabel* m_label;
+ QString m_original;
};
@@ -168,13 +156,13 @@ public:
QString selectedInstanceName() const override;
private:
- PathChecker m_checker;
- QString m_originalLabel;
+ mutable PlaceholderLabel m_label, m_exists, m_invalid;
bool m_modified;
bool m_okay;
void onChanged();
void updateWarnings();
+ bool checkName(QString parentDir, QString name);
};
@@ -189,16 +177,21 @@ public:
CreateInstanceDialog::Paths selectedPaths() const override;
private:
- PathChecker m_checker, m_advancedChecker;
QString m_lastInstanceName;
+ CreateInstanceDialog::Types m_lastType;
+ mutable PlaceholderLabel m_simpleExists, m_simpleInvalid;
+ mutable PlaceholderLabel m_advancedExists, m_advancedInvalid;
void onChanged();
bool checkPaths() const;
bool checkAdvancedPath(const QString& path) const;
- bool checkVarPath(QString path) const;
+ QString resolve(const QString& path) const;
void onAdvanced();
void setPaths(const QString& name, bool force);
void setIfEmpty(QLineEdit* e, const QString& path, bool force);
+ bool checkPath(
+ QString path,
+ PlaceholderLabel& existsLabel, PlaceholderLabel& invalidLabel) const;
};
diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp
index b135cac1..849cdb5e 100644
--- a/src/instancemanager.cpp
+++ b/src/instancemanager.cpp
@@ -353,7 +353,12 @@ QStringList InstanceManager::instanceNames() const
bool InstanceManager::isPortablePath(const QString& dataPath)
{
- return (dataPath == qApp->applicationDirPath());
+ return (dataPath == portablePath());
+}
+
+QString InstanceManager::portablePath()
+{
+ return qApp->applicationDirPath();
}
bool InstanceManager::portableInstall() const
diff --git a/src/instancemanager.h b/src/instancemanager.h
index 6a6b52ac..33a751c2 100644
--- a/src/instancemanager.h
+++ b/src/instancemanager.h
@@ -48,6 +48,7 @@ public:
bool allowedToChangeInstance() const;
static bool isPortablePath(const QString& dataPath);
+ static QString portablePath();
QString instancesPath() const;
QStringList instanceNames() const;
--
cgit v1.3.1
From 0389688f3b30b9888bb94a08991bc1de00b89c59 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Sat, 25 Jul 2020 21:52:30 -0400
Subject: move to next page when clicking a game add game name in the label in
the paths page can't use canonicalPath(), path might not exist
---
src/createinstancedialog.ui | 13 ++++++++-----
src/createinstancedialogpages.cpp | 13 ++++++++++---
src/createinstancedialogpages.h | 1 +
3 files changed, 19 insertions(+), 8 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index 4d9d8b06..41703f5e 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -7,7 +7,7 @@
0
0
493
- 423
+ 444
@@ -58,7 +58,7 @@
-
- 0
+ 5
@@ -506,12 +506,15 @@
<h3>Select a folder where the data should be stored.</h3>
+
+ true
+
-
-
+
- This includes downloads, mods, profiles and overwrite. If there is enough space on this drive, you should use the default folder.
+ This includes downloads, mods, profiles and overwrite for your <b>%1</b> instance. If there is enough space on this drive, you should use the default folder.
true
@@ -744,7 +747,7 @@
-
- Use <code>%BASE_DIR%</code> to refer to the Base Directory.
+ Use %BASE_DIR% to refer to the Base Directory.
diff --git a/src/createinstancedialogpages.cpp b/src/createinstancedialogpages.cpp
index 4d2c5b8b..e5213d33 100644
--- a/src/createinstancedialogpages.cpp
+++ b/src/createinstancedialogpages.cpp
@@ -269,6 +269,10 @@ void GamePage::select(IPluginGame* game)
m_selection = checked;
selectButton(checked);
updateNavigation();
+
+ if (checked) {
+ next();
+ }
}
void GamePage::selectCustom()
@@ -277,6 +281,7 @@ void GamePage::selectCustom()
&m_dlg, QObject::tr("Find game installation"));
if (path.isEmpty()) {
+ // reselect the previous button
selectButton(m_selection);
return;
}
@@ -408,7 +413,7 @@ QCommandLinkButton* GamePage::createCustomButton()
QObject::connect(b, &QAbstractButton::clicked, [&] {
selectCustom();
- });
+ });
return b;
}
@@ -422,7 +427,7 @@ void GamePage::createGameButton(Game* g)
QObject::connect(g->button, &QAbstractButton::clicked, [g, this] {
select(g->game);
- });
+ });
}
void GamePage::fillList()
@@ -759,6 +764,7 @@ bool NamePage::checkName(QString parentDir, QString name)
PathsPage::PathsPage(CreateInstanceDialog& dlg) :
Page(dlg), m_lastType(CreateInstanceDialog::NoType),
+ m_label(ui->pathsLabel),
m_simpleExists(ui->locationExists), m_simpleInvalid(ui->locationInvalid),
m_advancedExists(ui->advancedDirExists),
m_advancedInvalid(ui->advancedDirInvalid)
@@ -793,6 +799,7 @@ void PathsPage::activated()
checkPaths();
updateNavigation();
+ m_label.setText(m_dlg.game()->gameName());
m_lastInstanceName = name;
m_lastType = type;
}
@@ -868,7 +875,7 @@ void PathsPage::setPaths(const QString& name, bool force)
path = root + "/" + name;
}
- path = QDir::toNativeSeparators(QDir(path).canonicalPath());
+ path = QDir::toNativeSeparators(QDir::cleanPath(path));
setIfEmpty(ui->location, path, force);
setIfEmpty(ui->base, path, force);
diff --git a/src/createinstancedialogpages.h b/src/createinstancedialogpages.h
index 0d210493..15e63a8f 100644
--- a/src/createinstancedialogpages.h
+++ b/src/createinstancedialogpages.h
@@ -179,6 +179,7 @@ public:
private:
QString m_lastInstanceName;
CreateInstanceDialog::Types m_lastType;
+ PlaceholderLabel m_label;
mutable PlaceholderLabel m_simpleExists, m_simpleInvalid;
mutable PlaceholderLabel m_advancedExists, m_advancedInvalid;
--
cgit v1.3.1
From dfbcf8ec4c6da4d2d098403a01e7ec19b587e836 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Sat, 25 Jul 2020 22:08:43 -0400
Subject: restart when finished, added launch instance checkbox
---
src/createinstancedialog.cpp | 14 ++++++++++++++
src/createinstancedialog.ui | 38 ++++++++++++++++++++++++++++++++++++++
src/instancemanager.h | 3 +--
3 files changed, 53 insertions(+), 2 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp
index 4b9f24ae..63df9cd7 100644
--- a/src/createinstancedialog.cpp
+++ b/src/createinstancedialog.cpp
@@ -3,6 +3,7 @@
#include "createinstancedialogpages.h"
#include "instancemanager.h"
#include "settings.h"
+#include "shared/util.h"
#include "shared/appconfig.h"
#include
#include
@@ -27,6 +28,7 @@ CreateInstanceDialog::CreateInstanceDialog(
m_pages.push_back(std::make_unique(*this));
ui->pages->setCurrentIndex(0);
+ ui->launch->setChecked(true);
updateNavigation();
@@ -287,6 +289,14 @@ void CreateInstanceDialog::finish()
}
logCreation(tr("Done."));
+
+ if (ui->launch->isChecked()) {
+ InstanceManager::instance().setCurrentInstance(ci.instanceName);
+ ExitModOrganizer(Exit::Restart);
+ } else {
+ ui->next->setEnabled(false);
+ ui->cancel->setText(tr("Close"));
+ }
}
catch(Failed&)
{
@@ -328,6 +338,10 @@ void CreateInstanceDialog::updateNavigation()
} else {
ui->next->setText(m_originalNext);
}
+
+ // this may have been changed by finish() if the launch checkbox wasn't
+ // checked
+ ui->cancel->setText(tr("Cancel"));
}
CreateInstanceDialog::Types CreateInstanceDialog::instanceType() const
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index 41703f5e..bcd2eb03 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -910,6 +910,44 @@
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 304
+ 20
+
+
+
+
+ -
+
+
+ Launch the new instance
+
+
+
+
+
+
diff --git a/src/instancemanager.h b/src/instancemanager.h
index 33a751c2..7467e2fa 100644
--- a/src/instancemanager.h
+++ b/src/instancemanager.h
@@ -45,6 +45,7 @@ public:
void clearCurrentInstance();
QString currentInstance() const;
+ void setCurrentInstance(const QString &name);
bool allowedToChangeInstance() const;
static bool isPortablePath(const QString& dataPath);
@@ -67,8 +68,6 @@ private:
QString manageInstances(const QStringList &instanceList) const;
- void setCurrentInstance(const QString &name);
-
QString queryInstanceName(const QStringList &instanceList) const;
QString chooseInstance(const QStringList &instanceList) const;
--
cgit v1.3.1
From 0f0313874aa90c66acaac9082f5ba6fbd29300ef Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Sat, 25 Jul 2020 22:47:34 -0400
Subject: new GlobalSettings class to manage the registry close the create
instance dialog when launch is unchecked
---
src/createinstancedialog.cpp | 7 +------
src/createinstancedialog.ui | 3 +++
src/instancemanager.cpp | 30 +++---------------------------
src/instancemanager.h | 4 ----
src/settings.cpp | 36 ++++++++++++++++++++++++++++++++++++
src/settings.h | 16 ++++++++++++++++
6 files changed, 59 insertions(+), 37 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp
index 63df9cd7..5a38aa50 100644
--- a/src/createinstancedialog.cpp
+++ b/src/createinstancedialog.cpp
@@ -294,8 +294,7 @@ void CreateInstanceDialog::finish()
InstanceManager::instance().setCurrentInstance(ci.instanceName);
ExitModOrganizer(Exit::Restart);
} else {
- ui->next->setEnabled(false);
- ui->cancel->setText(tr("Close"));
+ close();
}
}
catch(Failed&)
@@ -338,10 +337,6 @@ void CreateInstanceDialog::updateNavigation()
} else {
ui->next->setText(m_originalNext);
}
-
- // this may have been changed by finish() if the launch checkbox wasn't
- // checked
- ui->cancel->setText(tr("Cancel"));
}
CreateInstanceDialog::Types CreateInstanceDialog::instanceType() const
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index bcd2eb03..1f9a8ce1 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -943,6 +943,9 @@
Launch the new instance
+
+ true
+
diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp
index 849cdb5e..bd35cb47 100644
--- a/src/instancemanager.cpp
+++ b/src/instancemanager.cpp
@@ -23,7 +23,6 @@ along with Mod Organizer. If not, see .
#include "settings.h"
#include "shared/appconfig.h"
#include "plugincontainer.h"
-#include "env.h"
#include
#include
#include
@@ -38,15 +37,9 @@ along with Mod Organizer. If not, see .
using namespace MOBase;
-const QString Organization = "Mod Organizer Team";
-const QString Application = "Mod Organizer";
-const QString InstanceValue = "CurrentInstance";
-
-
InstanceManager::InstanceManager()
- : m_AppSettings(Organization, Application)
{
- updateRegistryKey();
+ GlobalSettings::updateRegistryKey();
}
InstanceManager &InstanceManager::instance()
@@ -55,23 +48,6 @@ InstanceManager &InstanceManager::instance()
return s_Instance;
}
-void InstanceManager::updateRegistryKey()
-{
- const QString OldOrganization = "Tannin";
- const QString OldApplication = "Mod Organizer";
- const QString OldInstanceValue = "CurrentInstance";
-
- const QString OldRootKey = "Software\\" + OldOrganization;
-
- if (env::registryValueExists(OldRootKey + "\\" + OldApplication, OldInstanceValue)) {
- QSettings old(OldOrganization, OldApplication);
- setCurrentInstance(old.value(OldInstanceValue).toString());
- old.remove(OldInstanceValue);
- }
-
- env::deleteRegistryKeyIfEmpty(OldRootKey);
-}
-
void InstanceManager::overrideInstance(const QString& instanceName)
{
m_overrideInstanceName = instanceName;
@@ -89,7 +65,7 @@ QString InstanceManager::currentInstance() const
if (m_overrideInstance)
return m_overrideInstanceName;
else
- return m_AppSettings.value(InstanceValue, "").toString();
+ return GlobalSettings::currentInstance();
}
void InstanceManager::clearCurrentInstance()
@@ -101,7 +77,7 @@ void InstanceManager::clearCurrentInstance()
void InstanceManager::setCurrentInstance(const QString &name)
{
- m_AppSettings.setValue(InstanceValue, name);
+ GlobalSettings::setCurrentInstance(name);
}
bool InstanceManager::deleteLocalInstance(const QString& instanceId) const
diff --git a/src/instancemanager.h b/src/instancemanager.h
index 7467e2fa..f53543df 100644
--- a/src/instancemanager.h
+++ b/src/instancemanager.h
@@ -75,11 +75,7 @@ private:
bool portableInstall() const;
bool portableInstallIsLocked() const;
- void updateRegistryKey();
-
private:
-
- QSettings m_AppSettings;
bool m_Reset {false};
bool m_overrideInstance{false};
QString m_overrideInstanceName;
diff --git a/src/settings.cpp b/src/settings.cpp
index 661cf429..76378af9 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -2165,3 +2165,39 @@ void DiagnosticsSettings::setSpawnDelay(std::chrono::seconds t)
{
set(m_Settings, "Settings", "spawn_delay", t.count());
}
+
+
+void GlobalSettings::updateRegistryKey()
+{
+ const QString OldOrganization = "Tannin";
+ const QString OldApplication = "Mod Organizer";
+ const QString OldInstanceValue = "CurrentInstance";
+
+ const QString OldRootKey = "Software\\" + OldOrganization;
+
+ if (env::registryValueExists(OldRootKey + "\\" + OldApplication, OldInstanceValue)) {
+ QSettings old(OldOrganization, OldApplication);
+ setCurrentInstance(old.value(OldInstanceValue).toString());
+ old.remove(OldInstanceValue);
+ }
+
+ env::deleteRegistryKeyIfEmpty(OldRootKey);
+}
+
+QString GlobalSettings::currentInstance()
+{
+ return settings().value("CurrentInstance", "").toString();
+}
+
+void GlobalSettings::setCurrentInstance(const QString& s)
+{
+ settings().setValue("CurrentInstance", s);
+}
+
+QSettings GlobalSettings::settings()
+{
+ const QString Organization = "Mod Organizer Team";
+ const QString Application = "Mod Organizer";
+
+ return QSettings(Organization, Application);
+}
diff --git a/src/settings.h b/src/settings.h
index c723faec..54f1bb5b 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -827,6 +827,22 @@ private:
};
+// manages global settings in the registry
+//
+class GlobalSettings
+{
+public:
+ // migrates the old settings from the Tannin key to the new one
+ static void updateRegistryKey();
+
+ static QString currentInstance();
+ static void setCurrentInstance(const QString& s);
+
+private:
+ static QSettings settings();
+};
+
+
// helper class that calls restoreGeometry() in the constructor and
// saveGeometry() in the destructor
//
--
cgit v1.3.1
From 8987693dcf7dc116361869f128fd443716511f0c Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Sat, 25 Jul 2020 23:00:16 -0400
Subject: added hide option for intro page in create instance dialog
---
src/createinstancedialog.cpp | 11 ++++++++++-
src/createinstancedialog.ui | 26 +++++++++++++++++++++++---
src/createinstancedialogpages.cpp | 7 ++++++-
src/createinstancedialogpages.h | 6 ++++--
src/settings.cpp | 15 +++++++++++++++
src/settings.h | 6 ++++++
src/settingsdialoggeneral.cpp | 1 +
7 files changed, 65 insertions(+), 7 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp
index 5a38aa50..2edfee88 100644
--- a/src/createinstancedialog.cpp
+++ b/src/createinstancedialog.cpp
@@ -19,7 +19,7 @@ CreateInstanceDialog::CreateInstanceDialog(
ui->setupUi(this);
m_originalNext = ui->next->text();
- m_pages.push_back(std::make_unique(*this));
+ m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
@@ -30,10 +30,15 @@ CreateInstanceDialog::CreateInstanceDialog(
ui->pages->setCurrentIndex(0);
ui->launch->setChecked(true);
+ if (m_pages[0]->skip()) {
+ next();
+ }
+
updateNavigation();
connect(ui->next, &QPushButton::clicked, [&]{ next(); });
connect(ui->back, &QPushButton::clicked, [&]{ back(); });
+ connect(ui->cancel, &QPushButton::clicked, [&]{ reject(); });
}
CreateInstanceDialog::~CreateInstanceDialog() = default;
@@ -290,6 +295,10 @@ void CreateInstanceDialog::finish()
logCreation(tr("Done."));
+ if (ui->hideIntro->isChecked()) {
+ GlobalSettings::setHideCreateInstanceIntro(true);
+ }
+
if (ui->launch->isChecked()) {
InstanceManager::instance().setCurrentInstance(ci.instanceName);
ExitModOrganizer(Exit::Restart);
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index 1f9a8ce1..cafccb36 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -58,7 +58,7 @@
-
- 5
+ 0
@@ -76,6 +76,26 @@
+ -
+
+
+ Never show this again
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
@@ -258,7 +278,7 @@
0
0
455
- 287
+ 308
@@ -368,7 +388,7 @@
0
0
455
- 257
+ 278
diff --git a/src/createinstancedialogpages.cpp b/src/createinstancedialogpages.cpp
index e5213d33..3f35b4fe 100644
--- a/src/createinstancedialogpages.cpp
+++ b/src/createinstancedialogpages.cpp
@@ -153,11 +153,16 @@ CreateInstanceDialog::Paths Page::selectedPaths() const
}
-InfoPage::InfoPage(CreateInstanceDialog& dlg)
+IntroPage::IntroPage(CreateInstanceDialog& dlg)
: Page(dlg)
{
}
+bool IntroPage::skip() const
+{
+ return GlobalSettings::hideCreateInstanceIntro();
+}
+
TypePage::TypePage(CreateInstanceDialog& dlg)
: Page(dlg), m_type(CreateInstanceDialog::NoType)
diff --git a/src/createinstancedialogpages.h b/src/createinstancedialogpages.h
index 15e63a8f..b8366234 100644
--- a/src/createinstancedialogpages.h
+++ b/src/createinstancedialogpages.h
@@ -53,10 +53,12 @@ protected:
};
-class InfoPage : public Page
+class IntroPage : public Page
{
public:
- InfoPage(CreateInstanceDialog& dlg);
+ IntroPage(CreateInstanceDialog& dlg);
+
+ bool skip() const override;
};
diff --git a/src/settings.cpp b/src/settings.cpp
index 76378af9..4ee4cd81 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -2201,3 +2201,18 @@ QSettings GlobalSettings::settings()
return QSettings(Organization, Application);
}
+
+bool GlobalSettings::hideCreateInstanceIntro()
+{
+ return settings().value("HideCreateInstanceIntro", false).toBool();
+}
+
+void GlobalSettings::setHideCreateInstanceIntro(bool b)
+{
+ settings().setValue("HideCreateInstanceIntro", b);
+}
+
+void GlobalSettings::resetDialogs()
+{
+ setHideCreateInstanceIntro(false);
+}
diff --git a/src/settings.h b/src/settings.h
index 54f1bb5b..dd8abf3f 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -838,6 +838,12 @@ public:
static QString currentInstance();
static void setCurrentInstance(const QString& s);
+ static bool hideCreateInstanceIntro();
+ static void setHideCreateInstanceIntro(bool b);
+
+ // resets anything that the user can disable
+ static void resetDialogs();
+
private:
static QSettings settings();
};
diff --git a/src/settingsdialoggeneral.cpp b/src/settingsdialoggeneral.cpp
index 3d14d521..f29e1d24 100644
--- a/src/settingsdialoggeneral.cpp
+++ b/src/settingsdialoggeneral.cpp
@@ -177,6 +177,7 @@ void GeneralSettingsTab::selectStyle()
void GeneralSettingsTab::resetDialogs()
{
settings().widgets().resetQuestionButtons();
+ GlobalSettings::resetDialogs();
}
void GeneralSettingsTab::onExploreStyles()
--
cgit v1.3.1
From 58479e4b00d399e3025558104e50c75ef609dda0 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Wed, 29 Jul 2020 22:14:43 -0400
Subject: filter for games replaced the button box with a regular widget with
vertical layout it was doing weird things to buttons with focus when removing
and adding buttons on the fly because of filtering
---
src/createinstancedialog.ui | 204 +++++++++++++++++++++-----------------
src/createinstancedialogpages.cpp | 46 ++++++++-
src/createinstancedialogpages.h | 9 +-
3 files changed, 161 insertions(+), 98 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index cafccb36..a8f21c51 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -127,7 +127,7 @@
-
-
+
0
@@ -141,11 +141,8 @@
0
-
-
-
-
- 0
-
+
+
0
@@ -184,22 +181,22 @@
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
@@ -226,32 +223,12 @@
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Show all supported games
-
-
-
-
-
+
0
@@ -265,59 +242,104 @@
0
-
-
-
- Qt::ScrollBarAlwaysOff
-
-
- true
-
-
-
-
- 0
- 0
- 455
- 308
-
+
+
+
+ 0
-
-
- 0
- 0
-
+
+ 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
-
- 0
- 0
-
-
-
- Qt::Vertical
-
-
- QDialogButtonBox::NoButton
+
+ 0
+
+
+ 0
+
+
-
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 98
+ 28
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ PushButton
+
+
+
+
-
-
-
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Show all supported games
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 175
+ 20
+
+
+
+
+ -
+
+
+ Filter
+
+
+
+
@@ -387,8 +409,8 @@
0
0
- 455
- 278
+ 98
+ 28
diff --git a/src/createinstancedialogpages.cpp b/src/createinstancedialogpages.cpp
index 3f35b4fe..2aac93a0 100644
--- a/src/createinstancedialogpages.cpp
+++ b/src/createinstancedialogpages.cpp
@@ -12,6 +12,7 @@ namespace cid
using MOBase::IPluginGame;
using MOBase::TaskDialog;
+using MOBase::FilterWidget;
QString makeDefaultPath(const std::wstring& dir)
{
@@ -228,6 +229,9 @@ GamePage::GamePage(CreateInstanceDialog& dlg)
createGames();
fillList();
+ m_filter.setEdit(ui->gamesFilter);
+
+ QObject::connect(&m_filter, &FilterWidget::changed, [&]{ fillList(); });
QObject::connect(ui->showAllGames, &QCheckBox::clicked, [&]{ fillList(); });
}
@@ -362,6 +366,7 @@ void GamePage::updateButton(Game* g)
}
g->button->setText(g->game->gameName());
+ g->button->setIcon(g->game->gameIcon());
if (g->installed) {
g->button->setDescription(g->dir);
@@ -394,7 +399,7 @@ void GamePage::selectButton(Game* g)
// was not installed; create it and show it
// and it has a button, just check it
createGameButton(gg.get());
- ui->games->addButton(gg->button, QDialogButtonBox::AcceptRole);
+ addButton(gg->button);
}
gg->button->setChecked(true);
@@ -439,9 +444,8 @@ void GamePage::fillList()
{
const bool showAll = ui->showAllGames->isChecked();
- ui->games->clear();
-
- ui->games->addButton(createCustomButton(), QDialogButtonBox::AcceptRole);
+ clearButtons();
+ addButton(createCustomButton());
for (auto& g : m_games) {
g->button = nullptr;
@@ -451,11 +455,43 @@ void GamePage::fillList()
continue;
}
+ if (!m_filter.matches(g->game->gameName())) {
+ continue;
+ }
+
createGameButton(g.get());
- ui->games->addButton(g->button, QDialogButtonBox::AcceptRole);
+ addButton(g->button);
}
}
+void GamePage::clearButtons()
+{
+ auto* ly = static_cast(ui->games->layout());
+
+ ui->games->setUpdatesEnabled(false);
+
+ // delete all children
+ qDeleteAll(ui->games->findChildren("", Qt::FindDirectChildrenOnly));
+
+ // stretch widgets added with addStretch() are not in the parent widget,
+ // they have to be deleted from the layout itself
+ while (auto* child=ly->takeAt(0))
+ delete child;
+
+ // add a stretch, buttons will be added before
+ ly->addStretch();
+
+ ui->games->setUpdatesEnabled(true);
+}
+
+void GamePage::addButton(QAbstractButton* b)
+{
+ auto* ly = static_cast(ui->games->layout());
+
+ // insert before the stretch
+ ly->insertWidget(ly->count() - 1, b);
+}
+
GamePage::Game* GamePage::checkInstallation(const QString& path, Game* g)
{
if (g->game->looksValid(path)) {
diff --git a/src/createinstancedialogpages.h b/src/createinstancedialogpages.h
index b8366234..f2f4216d 100644
--- a/src/createinstancedialogpages.h
+++ b/src/createinstancedialogpages.h
@@ -1,10 +1,12 @@
#ifndef MODORGANIZER_CREATEINSTANCEDIALOGPAGES_INCLUDED
#define MODORGANIZER_CREATEINSTANCEDIALOGPAGES_INCLUDED
+#include "createinstancedialog.h"
+#include
+
#include
#include
#include
-#include "createinstancedialog.h"
namespace MOBase { class IPluginGame; }
@@ -107,16 +109,19 @@ private:
std::vector> m_games;
Game* m_selection;
-
+ MOBase::FilterWidget m_filter;
std::vector sortedGamePlugins() const;
Game* findGame(MOBase::IPluginGame* game);
void createGames();
void updateButton(Game* g);
void selectButton(Game* g);
+ void clearButtons();
+ void addButton(QAbstractButton* b);
QCommandLinkButton* createCustomButton();
void createGameButton(Game* g);
void fillList();
+ void onFilter();
Game* checkInstallation(const QString& path, Game* g);
MOBase::IPluginGame* findAnotherGame(const QString& path);
bool confirmUnknown(const QString& path, MOBase::IPluginGame* game);
--
cgit v1.3.1
From c4df6b8ec98feb34cc9b9785e6d4d0eac6b3f571 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Thu, 30 Jul 2020 00:48:46 -0400
Subject: split nexus connection stuff into NexusConnectionUI so it can be
reused in the instance creation dialog removed the PluginContainer* parameter
from NexusInterface::instance() - it's a singleton, so it only needs to be
given once, not every time - it doesn't even matter because the first time
instance() is called, it creates the singleton, but the plugin container is
always null - and setPluginContainer() is called much later from
OrganizerCore with the correct value added non functional nexus page to
instance creation dialog
---
src/createinstancedialog.cpp | 1 +
src/createinstancedialog.ui | 161 ++++++++++++++--
src/createinstancedialogpages.cpp | 20 ++
src/createinstancedialogpages.h | 14 ++
src/main.cpp | 10 +-
src/mainwindow.cpp | 62 +++----
src/modinfo.cpp | 18 +-
src/modinfo.h | 5 +-
src/modinfodialognexus.cpp | 8 +-
src/nexusinterface.cpp | 15 +-
src/nexusinterface.h | 5 +-
src/organizercore.cpp | 22 +--
src/settingsdialognexus.cpp | 382 +++++++++++++++++++++-----------------
src/settingsdialognexus.h | 55 ++++--
14 files changed, 510 insertions(+), 268 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp
index 75ccc774..935b9ee9 100644
--- a/src/createinstancedialog.cpp
+++ b/src/createinstancedialog.cpp
@@ -25,6 +25,7 @@ CreateInstanceDialog::CreateInstanceDialog(
m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
+ m_pages.push_back(std::make_unique(*this));
m_pages.push_back(std::make_unique(*this));
ui->pages->setCurrentIndex(0);
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index a8f21c51..ebaef84d 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -266,8 +266,8 @@
0
0
- 98
- 28
+ 63
+ 16
@@ -283,13 +283,6 @@
0
- -
-
-
- PushButton
-
-
-
@@ -409,8 +402,8 @@
0
0
- 98
- 28
+ 63
+ 16
@@ -886,6 +879,148 @@
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ <h3>Link Mod Organizer with your Nexus account</h3>
+
+
+
+ -
+
+
+ Linking with Nexus allows you to download mods directly from Mod Organizer and automatically check for updates. This is optional.
+
+
+ true
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 100
+
+
+
+
+ 0
+
+
+ 9
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Connect to Nexus
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Enter API Key Manually
+
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
-
@@ -1057,6 +1192,8 @@
-
+
+
+
diff --git a/src/createinstancedialogpages.cpp b/src/createinstancedialogpages.cpp
index f37853f0..37d50ee1 100644
--- a/src/createinstancedialogpages.cpp
+++ b/src/createinstancedialogpages.cpp
@@ -997,6 +997,26 @@ bool PathsPage::checkPath(
}
+NexusPage::NexusPage(CreateInstanceDialog& dlg)
+ : Page(dlg)
+{
+}
+
+bool NexusPage::ready() const
+{
+ return true;
+}
+
+bool NexusPage::skip() const
+{
+ return Settings::instance().nexus().hasApiKey();
+}
+
+void NexusPage::activated()
+{
+}
+
+
ConfirmationPage::ConfirmationPage(CreateInstanceDialog& dlg)
: Page(dlg)
{
diff --git a/src/createinstancedialogpages.h b/src/createinstancedialogpages.h
index f2f4216d..88e49628 100644
--- a/src/createinstancedialogpages.h
+++ b/src/createinstancedialogpages.h
@@ -203,6 +203,20 @@ private:
};
+class NexusPage : public Page
+{
+public:
+ NexusPage(CreateInstanceDialog& dlg);
+
+ bool ready() const override;
+ bool skip() const override;
+ void activated() override;
+
+private:
+
+};
+
+
class ConfirmationPage : public Page
{
public:
diff --git a/src/main.cpp b/src/main.cpp
index 58e22466..93580931 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -395,7 +395,7 @@ int runApplication(
QString apiKey;
if (settings.nexus().apiKey(apiKey)) {
- NexusInterface::instance(pluginContainer.get())->getAccessManager()->apiCheck(apiKey);
+ NexusInterface::instance().getAccessManager()->apiCheck(apiKey);
}
log::debug("initializing tutorials");
@@ -415,8 +415,8 @@ int runApplication(
// set up main window and its data structures
MainWindow mainWindow(settings, organizer, *pluginContainer);
- NexusInterface::instance(pluginContainer.get())
- ->getAccessManager()->setTopLevelWidget(&mainWindow);
+ NexusInterface::instance()
+ .getAccessManager()->setTopLevelWidget(&mainWindow);
QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), &application,
SLOT(setStyleFile(QString)));
@@ -443,8 +443,8 @@ int runApplication(
res = application.exec();
mainWindow.close();
- NexusInterface::instance(pluginContainer.get())
- ->getAccessManager()->setTopLevelWidget(nullptr);
+ NexusInterface::instance()
+ .getAccessManager()->setTopLevelWidget(nullptr);
}
settings.geometry().resetIfNeeded();
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 60ad77a0..9144210c 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -291,7 +291,7 @@ MainWindow::MainWindow(Settings &settings
ui->statusBar->setup(ui, settings);
{
- auto* ni = NexusInterface::instance(&m_PluginContainer);
+ auto* ni = &NexusInterface::instance();
// there are two ways to get here:
// 1) the user just started MO, and
@@ -439,24 +439,24 @@ MainWindow::MainWindow(Settings &settings
connect(m_OrganizerCore.updater(), SIGNAL(updateAvailable()), this, SLOT(updateAvailable()));
connect(m_OrganizerCore.updater(), SIGNAL(motdAvailable(QString)), this, SLOT(motdReceived(QString)));
- connect(NexusInterface::instance(&pluginContainer), SIGNAL(requestNXMDownload(QString)), &m_OrganizerCore, SLOT(downloadRequestedNXM(QString)));
- connect(NexusInterface::instance(&pluginContainer), SIGNAL(nxmDownloadURLsAvailable(QString,int,int,QVariant,QVariant,int)), this, SLOT(nxmDownloadURLs(QString,int,int,QVariant,QVariant,int)));
- connect(NexusInterface::instance(&pluginContainer), SIGNAL(needLogin()), &m_OrganizerCore, SLOT(nexusApi()));
+ connect(&NexusInterface::instance(), SIGNAL(requestNXMDownload(QString)), &m_OrganizerCore, SLOT(downloadRequestedNXM(QString)));
+ connect(&NexusInterface::instance(), SIGNAL(nxmDownloadURLsAvailable(QString,int,int,QVariant,QVariant,int)), this, SLOT(nxmDownloadURLs(QString,int,int,QVariant,QVariant,int)));
+ connect(&NexusInterface::instance(), SIGNAL(needLogin()), &m_OrganizerCore, SLOT(nexusApi()));
connect(
- NexusInterface::instance(&pluginContainer)->getAccessManager(),
+ NexusInterface::instance().getAccessManager(),
SIGNAL(credentialsReceived(const APIUserAccount&)),
this,
SLOT(updateWindowTitle(const APIUserAccount&)));
connect(
- NexusInterface::instance(&pluginContainer)->getAccessManager(),
+ NexusInterface::instance().getAccessManager(),
SIGNAL(credentialsReceived(const APIUserAccount&)),
- NexusInterface::instance(&m_PluginContainer),
+ &NexusInterface::instance(),
SLOT(setUserAccount(const APIUserAccount&)));
connect(
- NexusInterface::instance(&pluginContainer),
+ &NexusInterface::instance(),
SIGNAL(requestsChanged(const APIStats&, const APIUserAccount&)),
this,
SLOT(onRequestsChanged(const APIStats&, const APIUserAccount&)));
@@ -1911,9 +1911,9 @@ QDir MainWindow::currentSavesDir() const
wchar_t path[MAX_PATH];
if (::GetPrivateProfileStringW(
- L"General", L"SLocalSavePath", L"",
- path, MAX_PATH,
- iniPath.toStdWString().c_str()
+ L"General", L"SLocalSavePath", L"",
+ path, MAX_PATH,
+ iniPath.toStdWString().c_str()
)) {
savesDir.setPath(m_OrganizerCore.managedGame()->documentsDirectory().absoluteFilePath(QString::fromWCharArray(path)));
}
@@ -3288,7 +3288,7 @@ void MainWindow::visitOnNexus_clicked()
int modID = info->nexusId();
gameName = info->gameName();
if (modID > 0) {
- linkClicked(NexusInterface::instance(&m_PluginContainer)->getModURL(modID, gameName));
+ linkClicked(NexusInterface::instance().getModURL(modID, gameName));
} else {
log::error("mod '{}' has no nexus id", info->name());
}
@@ -3298,7 +3298,7 @@ void MainWindow::visitOnNexus_clicked()
int modID = m_OrganizerCore.modList()->data(m_OrganizerCore.modList()->index(m_ContextRow, 0), Qt::UserRole).toInt();
QString gameName = m_OrganizerCore.modList()->data(m_OrganizerCore.modList()->index(m_ContextRow, 0), Qt::UserRole + 4).toString();
if (modID > 0) {
- linkClicked(NexusInterface::instance(&m_PluginContainer)->getModURL(modID, gameName));
+ linkClicked(NexusInterface::instance().getModURL(modID, gameName));
} else {
MessageDialog::showMessage(tr("Nexus ID for this mod is unknown"), this);
}
@@ -3355,7 +3355,7 @@ void MainWindow::visitNexusOrWebPage(const QModelIndex& idx)
const auto url = info->parseCustomURL();
if (modID > 0) {
- linkClicked(NexusInterface::instance(&m_PluginContainer)->getModURL(modID, gameName));
+ linkClicked(NexusInterface::instance().getModURL(modID, gameName));
} else if (url.isValid()) {
linkClicked(url.toString());
} else {
@@ -4220,15 +4220,15 @@ void MainWindow::saveArchiveList()
void MainWindow::checkModsForUpdates()
{
bool checkingModsForUpdate = false;
- if (NexusInterface::instance(&m_PluginContainer)->getAccessManager()->validated()) {
- checkingModsForUpdate = ModInfo::checkAllForUpdate(&m_PluginContainer, this);
- NexusInterface::instance(&m_PluginContainer)->requestEndorsementInfo(this, QVariant(), QString());
- NexusInterface::instance(&m_PluginContainer)->requestTrackingInfo(this, QVariant(), QString());
+ if (NexusInterface::instance().getAccessManager()->validated()) {
+ checkingModsForUpdate = ModInfo::checkAllForUpdate(this);
+ NexusInterface::instance().requestEndorsementInfo(this, QVariant(), QString());
+ NexusInterface::instance().requestTrackingInfo(this, QVariant(), QString());
} else {
QString apiKey;
if (m_OrganizerCore.settings().nexus().apiKey(apiKey)) {
m_OrganizerCore.doAfterLogin([this] () { this->checkModsForUpdates(); });
- NexusInterface::instance(&m_PluginContainer)->getAccessManager()->apiCheck(apiKey);
+ NexusInterface::instance().getAccessManager()->apiCheck(apiKey);
} else {
log::warn("{}", tr("You are not currently authenticated with Nexus. Please do so under Settings -> Nexus."));
}
@@ -4603,7 +4603,7 @@ void MainWindow::exportModListCSV()
if (nexus_ID->isChecked())
builder.setRowField("#Nexus_ID", info->nexusId());
if (mod_Nexus_URL->isChecked())
- builder.setRowField("#Mod_Nexus_URL",(info->nexusId()>0)? NexusInterface::instance(&m_PluginContainer)->getModURL(info->nexusId(), info->gameName()) : "");
+ builder.setRowField("#Mod_Nexus_URL",(info->nexusId()>0)? NexusInterface::instance().getModURL(info->nexusId(), info->gameName()) : "");
if (mod_Version->isChecked())
builder.setRowField("#Mod_Version", info->version().canonicalString());
if (install_Date->isChecked())
@@ -5157,7 +5157,7 @@ void MainWindow::on_actionSettings_triggered()
}
if (settings.paths().cache() != oldCacheDirectory) {
- NexusInterface::instance(&m_PluginContainer)->setCacheDirectory(
+ NexusInterface::instance().setCacheDirectory(
settings.paths().cache());
}
@@ -5191,7 +5191,7 @@ void MainWindow::on_actionNexus_triggered()
QString gameName = game->gameShortName();
if (game->gameNexusName().isEmpty() && game->primarySources().count())
gameName = game->primarySources()[0];
- QDesktopServices::openUrl(QUrl(NexusInterface::instance(&m_PluginContainer)->getGameURL(gameName)));
+ QDesktopServices::openUrl(QUrl(NexusInterface::instance().getGameURL(gameName)));
}
@@ -5350,9 +5350,9 @@ void MainWindow::actionEndorseMO()
if (QMessageBox::question(this, tr("Endorse Mod Organizer"),
tr("Do you want to endorse Mod Organizer on %1 now?").arg(
- NexusInterface::instance(&m_PluginContainer)->getGameURL(game->gameShortName())),
+ NexusInterface::instance().getGameURL(game->gameShortName())),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- NexusInterface::instance(&m_PluginContainer)->requestToggleEndorsement(
+ NexusInterface::instance().requestToggleEndorsement(
game->gameShortName(), game->nexusModOrganizerID(), m_OrganizerCore.getVersion().canonicalString(), true, this, QVariant(), QString());
}
}
@@ -5366,9 +5366,9 @@ void MainWindow::actionWontEndorseMO()
if (QMessageBox::question(this, tr("Abstain from Endorsing Mod Organizer"),
tr("Are you sure you want to abstain from endorsing Mod Organizer 2?\n"
"You will have to visit the mod page on the %1 Nexus site to change your mind.").arg(
- NexusInterface::instance(&m_PluginContainer)->getGameURL(game->gameShortName())),
+ NexusInterface::instance().getGameURL(game->gameShortName())),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- NexusInterface::instance(&m_PluginContainer)->requestToggleEndorsement(
+ NexusInterface::instance().requestToggleEndorsement(
game->gameShortName(), game->nexusModOrganizerID(), m_OrganizerCore.getVersion().canonicalString(), false, this, QVariant(), QString());
}
}
@@ -5430,13 +5430,13 @@ void MainWindow::updateDownloadView()
void MainWindow::modUpdateCheck(std::multimap IDs)
{
- if (NexusInterface::instance(&m_PluginContainer)->getAccessManager()->validated()) {
- ModInfo::manualUpdateCheck(&m_PluginContainer, this, IDs);
+ if (NexusInterface::instance().getAccessManager()->validated()) {
+ ModInfo::manualUpdateCheck(this, IDs);
} else {
QString apiKey;
if (m_OrganizerCore.settings().nexus().apiKey(apiKey)) {
m_OrganizerCore.doAfterLogin([=]() { this->modUpdateCheck(IDs); });
- NexusInterface::instance(&m_PluginContainer)->getAccessManager()->apiCheck(apiKey);
+ NexusInterface::instance().getAccessManager()->apiCheck(apiKey);
} else
log::warn("{}", tr("You are not currently authenticated with Nexus. Please do so under Settings -> Nexus."));
}
@@ -5588,7 +5588,7 @@ void MainWindow::finishUpdateInfo()
log::warn("{}", tr("All of your mods have been checked recently. We restrict update checks to help preserve your available API requests."));
for (auto game : organizedGames)
- NexusInterface::instance(&m_PluginContainer)->requestUpdates(game.second, this, QVariant(), game.first, QString());
+ NexusInterface::instance().requestUpdates(game.second, this, QVariant(), game.first, QString());
disconnect(sender());
delete sender();
@@ -5675,7 +5675,7 @@ void MainWindow::nxmUpdatesAvailable(QString gameName, int modID, QVariant userD
}
if (requiresInfo)
- NexusInterface::instance(&m_PluginContainer)->requestModInfo(gameNameReal, modID, this, QVariant(), QString());
+ NexusInterface::instance().requestModInfo(gameNameReal, modID, this, QVariant(), QString());
}
void MainWindow::nxmModInfoAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID)
diff --git a/src/modinfo.cpp b/src/modinfo.cpp
index bbeefb12..04cb18ce 100644
--- a/src/modinfo.cpp
+++ b/src/modinfo.cpp
@@ -266,7 +266,7 @@ void ModInfo::updateFromDisc(const QString &modDirectory,
createFromOverwrite(pluginContainer, game, directoryStructure);
std::sort(s_Collection.begin(), s_Collection.end(), ModInfo::ByName);
-
+
parallelMap(std::begin(s_Collection), std::end(s_Collection), &ModInfo::prefetch, refreshThreadCount);
updateIndices();
@@ -295,7 +295,7 @@ ModInfo::ModInfo(PluginContainer *pluginContainer)
}
-bool ModInfo::checkAllForUpdate(PluginContainer *pluginContainer, QObject *receiver)
+bool ModInfo::checkAllForUpdate(QObject *receiver)
{
bool updatesAvailable = true;
@@ -348,19 +348,19 @@ bool ModInfo::checkAllForUpdate(PluginContainer *pluginContainer, QObject *recei
}
for (auto game : organizedGames)
- NexusInterface::instance(pluginContainer)->requestUpdates(game.second, receiver, QVariant(), game.first, QString());
+ NexusInterface::instance().requestUpdates(game.second, receiver, QVariant(), game.first, QString());
} else if (earliest < QDateTime::currentDateTimeUtc().addMonths(-1)) {
for (auto gameName : games)
- NexusInterface::instance(pluginContainer)->requestUpdateInfo(gameName, NexusInterface::UpdatePeriod::MONTH, receiver, QVariant(true), QString());
+ NexusInterface::instance().requestUpdateInfo(gameName, NexusInterface::UpdatePeriod::MONTH, receiver, QVariant(true), QString());
} else if (earliest < QDateTime::currentDateTimeUtc().addDays(-7)) {
for (auto gameName : games)
- NexusInterface::instance(pluginContainer)->requestUpdateInfo(gameName, NexusInterface::UpdatePeriod::MONTH, receiver, QVariant(false), QString());
+ NexusInterface::instance().requestUpdateInfo(gameName, NexusInterface::UpdatePeriod::MONTH, receiver, QVariant(false), QString());
} else if (earliest < QDateTime::currentDateTimeUtc().addDays(-1)) {
for (auto gameName : games)
- NexusInterface::instance(pluginContainer)->requestUpdateInfo(gameName, NexusInterface::UpdatePeriod::WEEK, receiver, QVariant(false), QString());
+ NexusInterface::instance().requestUpdateInfo(gameName, NexusInterface::UpdatePeriod::WEEK, receiver, QVariant(false), QString());
} else {
for (auto gameName : games)
- NexusInterface::instance(pluginContainer)->requestUpdateInfo(gameName, NexusInterface::UpdatePeriod::DAY, receiver, QVariant(false), QString());
+ NexusInterface::instance().requestUpdateInfo(gameName, NexusInterface::UpdatePeriod::DAY, receiver, QVariant(false), QString());
}
return updatesAvailable;
@@ -400,7 +400,7 @@ std::set> ModInfo::filteredMods(QString gameName, QVaria
return finalMods;
}
-void ModInfo::manualUpdateCheck(PluginContainer *pluginContainer, QObject *receiver, std::multimap IDs)
+void ModInfo::manualUpdateCheck(QObject *receiver, std::multimap IDs)
{
std::vector> mods;
std::set> organizedGames;
@@ -438,7 +438,7 @@ void ModInfo::manualUpdateCheck(PluginContainer *pluginContainer, QObject *recei
}
for (auto game : organizedGames) {
- NexusInterface::instance(pluginContainer)->requestUpdates(game.second, receiver, QVariant(), game.first, QString());
+ NexusInterface::instance().requestUpdates(game.second, receiver, QVariant(), game.first, QString());
}
} else {
log::info("None of the selected mods can be updated.");
diff --git a/src/modinfo.h b/src/modinfo.h
index 7223cece..480fe013 100644
--- a/src/modinfo.h
+++ b/src/modinfo.h
@@ -190,15 +190,14 @@ public: // Static functions:
* @brief Run a limited batch of mod update checks for "newest version" information.
*
*/
- static void manualUpdateCheck(
- PluginContainer *pluginContainer, QObject *receiver, std::multimap IDs);
+ static void manualUpdateCheck(QObject *receiver, std::multimap IDs);
/**
* @brief Query nexus information for every mod and update the "newest version" information.
*
* @return true if any mods are checked for update.
*/
- static bool checkAllForUpdate(PluginContainer *pluginContainer, QObject *receiver);
+ static bool checkAllForUpdate(QObject *receiver);
/**
*
diff --git a/src/modinfodialognexus.cpp b/src/modinfodialognexus.cpp
index dd95cdaa..b4099a8d 100644
--- a/src/modinfodialognexus.cpp
+++ b/src/modinfodialognexus.cpp
@@ -141,8 +141,8 @@ void NexusTab::updateWebpage()
const int modID = mod().nexusId();
if (isValidModID(modID)) {
- const QString nexusLink = NexusInterface::instance(&plugin())
- ->getModURL(modID, mod().gameName());
+ const QString nexusLink = NexusInterface::instance()
+ .getModURL(modID, mod().gameName());
ui->visitNexus->setToolTip(nexusLink);
refreshData(modID);
@@ -360,8 +360,8 @@ void NexusTab::onVisitNexus()
const int modID = mod().nexusId();
if (isValidModID(modID)) {
- const QString nexusLink = NexusInterface::instance(&plugin())
- ->getModURL(modID, mod().gameName());
+ const QString nexusLink = NexusInterface::instance()
+ .getModURL(modID, mod().gameName());
shell::Open(QUrl(nexusLink));
}
diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp
index 9eb1540a..396cec11 100644
--- a/src/nexusinterface.cpp
+++ b/src/nexusinterface.cpp
@@ -26,6 +26,7 @@ along with Mod Organizer. If not, see .
#include
#include "shared/util.h"
#include
+#include
#include
#include
@@ -50,7 +51,7 @@ void throttledWarning(const APIUserAccount& user)
NexusBridge::NexusBridge(PluginContainer *pluginContainer, const QString &subModule)
- : m_Interface(NexusInterface::instance(pluginContainer))
+ : m_Interface(&NexusInterface::instance())
, m_SubModule(subModule)
{
}
@@ -234,8 +235,8 @@ APILimits NexusInterface::parseLimits(
}
-NexusInterface::NexusInterface(PluginContainer *pluginContainer)
- : m_PluginContainer(pluginContainer)
+NexusInterface::NexusInterface()
+ : m_PluginContainer(nullptr)
{
m_User.limits(defaultAPILimits());
m_MOVersion = createVersionInfo();
@@ -255,10 +256,10 @@ NexusInterface::~NexusInterface()
cleanup();
}
-NexusInterface *NexusInterface::instance(PluginContainer *pluginContainer)
+NexusInterface& NexusInterface::instance()
{
- static NexusInterface s_Instance(pluginContainer);
- return &s_Instance;
+ static NexusInterface ni;
+ return ni;
}
void NexusInterface::setCacheDirectory(const QString &directory)
@@ -284,7 +285,7 @@ void NexusInterface::interpretNexusFileName(const QString &fileName, QString &mo
static const QRegularExpression complex(R"(^([a-zA-Z0-9_'"\-.() ]*?)([-_ ][VvRr]+[0-9]+(?:(?:[\.][0-9]+){0,2}|(?:[_][0-9]+){0,2}|(?:[-.][0-9]+){0,2})?[ab]?)??-([1-9][0-9]+)?-.*?\.(zip|rar|7z))");
//complex regex explanation:
//group 1: modname.
- //group 2: optional version,
+ //group 2: optional version,
// assumed to start with v (empty most of the time).
//group 3: NexusId,
// assumed wrapped in "-", will miss single digit IDs for better accuracy.
diff --git a/src/nexusinterface.h b/src/nexusinterface.h
index 35362bdf..72f30a38 100644
--- a/src/nexusinterface.h
+++ b/src/nexusinterface.h
@@ -154,8 +154,7 @@ public:
static APILimits parseLimits(const QList& headers);
~NexusInterface();
-
- static NexusInterface *instance(PluginContainer *pluginContainer);
+ static NexusInterface& instance();
/**
* @return the access manager object used to connect to nexus
@@ -535,7 +534,7 @@ private:
private:
- NexusInterface(PluginContainer *pluginContainer);
+ NexusInterface();
void nextRequest();
void requestFinished(std::list::iterator iter);
MOBase::IPluginGame *getGame(QString gameName) const;
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index 0849d756..7fd8c33b 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -95,12 +95,12 @@ OrganizerCore::OrganizerCore(Settings &settings)
, m_PluginContainer(nullptr)
, m_CurrentProfile(nullptr)
, m_Settings(settings)
- , m_Updater(NexusInterface::instance(m_PluginContainer))
+ , m_Updater(&NexusInterface::instance())
, m_ModList(m_PluginContainer, this)
, m_PluginList(this)
, m_DirectoryRefresher(new DirectoryRefresher(settings.refreshThreadCount()))
, m_DirectoryStructure(new DirectoryEntry(L"data", nullptr, 0))
- , m_DownloadManager(NexusInterface::instance(m_PluginContainer), this)
+ , m_DownloadManager(&NexusInterface::instance(), this)
, m_DirectoryUpdate(false)
, m_ArchivesInit(false)
, m_PluginListsWriter(std::bind(&OrganizerCore::savePluginList, this))
@@ -108,8 +108,7 @@ OrganizerCore::OrganizerCore(Settings &settings)
env::setHandleCloserThreadCount(settings.refreshThreadCount());
m_DownloadManager.setOutputDirectory(m_Settings.paths().downloads(), false);
- NexusInterface::instance(m_PluginContainer)->setCacheDirectory(
- m_Settings.paths().cache());
+ NexusInterface::instance().setCacheDirectory(m_Settings.paths().cache());
m_InstallationManager.setModsDirectory(m_Settings.paths().mods());
m_InstallationManager.setDownloadDirectory(m_Settings.paths().downloads());
@@ -122,9 +121,9 @@ OrganizerCore::OrganizerCore(Settings &settings)
connect(&m_ModList, SIGNAL(removeOrigin(QString)), this,
SLOT(removeOrigin(QString)));
- connect(NexusInterface::instance(m_PluginContainer)->getAccessManager(),
+ connect(NexusInterface::instance().getAccessManager(),
SIGNAL(validateSuccessful(bool)), this, SLOT(loginSuccessful(bool)));
- connect(NexusInterface::instance(m_PluginContainer)->getAccessManager(),
+ connect(NexusInterface::instance().getAccessManager(),
SIGNAL(validateFailed(QString)), this, SLOT(loginFailed(QString)));
// This seems awfully imperative
@@ -332,8 +331,7 @@ Settings &OrganizerCore::settings()
bool OrganizerCore::nexusApi(bool retry)
{
- NXMAccessManager *accessManager
- = NexusInterface::instance(m_PluginContainer)->getAccessManager();
+ auto* accessManager = NexusInterface::instance().getAccessManager();
if ((accessManager->validateAttempted() || accessManager->validated())
&& !retry) {
@@ -1424,13 +1422,13 @@ void OrganizerCore::updateModsInDirectoryStructure(QMap f)
{
- if (NexusInterface::instance(m_PluginContainer)->getAccessManager()->validated()) {
+ if (NexusInterface::instance().getAccessManager()->validated()) {
f();
} else {
QString apiKey;
if (settings().nexus().apiKey(apiKey)) {
doAfterLogin([f]{ f(); });
- NexusInterface::instance(m_PluginContainer)->getAccessManager()->apiCheck(apiKey);
+ NexusInterface::instance().getAccessManager()->apiCheck(apiKey);
} else {
MessageDialog::showMessage(tr("You need to be logged in with Nexus"), parent);
}
@@ -1704,7 +1702,7 @@ void OrganizerCore::loginSuccessful(bool necessary)
}
m_PostLoginTasks.clear();
- NexusInterface::instance(m_PluginContainer)->loginCompleted();
+ NexusInterface::instance().loginCompleted();
}
void OrganizerCore::loginSuccessfulUpdate(bool necessary)
@@ -1742,7 +1740,7 @@ void OrganizerCore::loginFailed(const QString &message)
qApp->activeWindow());
m_PostLoginTasks.clear();
}
- NexusInterface::instance(m_PluginContainer)->loginCompleted();
+ NexusInterface::instance().loginCompleted();
}
void OrganizerCore::loginFailedUpdate(const QString &message)
diff --git a/src/settingsdialognexus.cpp b/src/settingsdialognexus.cpp
index d49e0a33..a76b9ad7 100644
--- a/src/settingsdialognexus.cpp
+++ b/src/settingsdialognexus.cpp
@@ -71,112 +71,45 @@ private:
};
-NexusSettingsTab::NexusSettingsTab(Settings& s, SettingsDialog& d)
- : SettingsTab(s, d)
+NexusConnectionUI::NexusConnectionUI(Settings& s, QWidget* parent) :
+ m_parent(parent), m_settings(s),
+ m_connect(nullptr), m_disconnect(nullptr), m_manual(nullptr), m_log(nullptr)
{
- ui->offlineBox->setChecked(settings().network().offlineMode());
- ui->proxyBox->setChecked(settings().network().useProxy());
- ui->endorsementBox->setChecked(settings().nexus().endorsementIntegration());
- ui->hideAPICounterBox->setChecked(settings().interface().hideAPICounter());
-
- // display server preferences
- for (const auto& server : s.network().servers()) {
- QString descriptor = server.name();
-
- if (!descriptor.compare("CDN", Qt::CaseInsensitive)) {
- descriptor += QStringLiteral(" (automatic)");
- }
-
- const auto averageSpeed = server.averageSpeed();
- if (averageSpeed > 0) {
- descriptor += QString(" (%1)").arg(MOBase::localizedByteSpeed(averageSpeed));
- }
-
- QListWidgetItem *newItem = new ServerItem(descriptor, Qt::UserRole + 1);
-
- newItem->setData(Qt::UserRole, server.name());
- newItem->setData(Qt::UserRole + 1, server.preferred());
-
- if (server.preferred() > 0) {
- ui->preferredServersList->addItem(newItem);
- } else {
- ui->knownServersList->addItem(newItem);
- }
-
- ui->preferredServersList->sortItems(Qt::DescendingOrder);
- }
-
- QObject::connect(ui->nexusConnect, &QPushButton::clicked, [&]{ on_nexusConnect_clicked(); });
- QObject::connect(ui->nexusManualKey, &QPushButton::clicked, [&]{ on_nexusManualKey_clicked(); });
- QObject::connect(ui->nexusDisconnect, &QPushButton::clicked, [&]{ on_nexusDisconnect_clicked(); });
- QObject::connect(ui->clearCacheButton, &QPushButton::clicked, [&]{ on_clearCacheButton_clicked(); });
- QObject::connect(ui->associateButton, &QPushButton::clicked, [&]{ on_associateButton_clicked(); });
-
- if (settings().nexus().hasApiKey()) {
- addNexusLog(QObject::tr("Connected."));
- } else {
- addNexusLog(QObject::tr("Not connected."));
- }
-
- updateNexusState();
}
-void NexusSettingsTab::update()
+void NexusConnectionUI::set(
+ QAbstractButton* connectButton,
+ QAbstractButton* disconnectButton,
+ QAbstractButton* manualButton,
+ QListWidget* logList)
{
- settings().network().setOfflineMode(ui->offlineBox->isChecked());
- settings().network().setUseProxy(ui->proxyBox->isChecked());
- settings().nexus().setEndorsementIntegration(ui->endorsementBox->isChecked());
- settings().interface().setHideAPICounter(ui->hideAPICounterBox->isChecked());
-
- auto servers = settings().network().servers();
-
- // store server preference
- for (int i = 0; i < ui->knownServersList->count(); ++i) {
- const QString key = ui->knownServersList->item(i)->data(Qt::UserRole).toString();
-
- bool found = false;
-
- for (auto& server : servers) {
- if (server.name() == key) {
- server.setPreferred(0);
- found = true;
- break;
- }
- }
-
- if (!found) {
- log::error("while setting preferred to 0, server '{}' not found", key);
- }
+ m_connect = connectButton;
+ if (m_connect) {
+ QObject::connect(m_connect, &QPushButton::clicked, [&]{ connect(); });
}
- const int count = ui->preferredServersList->count();
-
- for (int i = 0; i < count; ++i) {
- const QString key = ui->preferredServersList->item(i)->data(Qt::UserRole).toString();
- const int newPreferred = count - i;
+ m_disconnect = disconnectButton;
+ if (m_disconnect) {
+ QObject::connect(m_disconnect, &QPushButton::clicked, [&]{ disconnect(); });
+ }
- bool found = false;
+ m_manual = manualButton;
+ if (m_manual) {
+ QObject::connect(manualButton, &QPushButton::clicked, [&]{ manual(); });
+ }
- for (auto& server : servers) {
+ m_log = logList;
- if (server.name() == key) {
- server.setPreferred(newPreferred);
- found = true;
- break;
- }
- }
-
- if (!found) {
- log::error(
- "while setting preference to {}, server '{}' not found",
- newPreferred, key);
- }
+ if (m_settings.nexus().hasApiKey()) {
+ addLog(tr("Connected."));
+ } else {
+ addLog(tr("Not connected."));
}
- settings().network().updateServers(servers);
+ updateState();
}
-void NexusSettingsTab::on_nexusConnect_clicked()
+void NexusConnectionUI::connect()
{
if (m_nexusLogin && m_nexusLogin->isActive()) {
m_nexusLogin->cancel();
@@ -195,19 +128,19 @@ void NexusSettingsTab::on_nexusConnect_clicked()
};
}
- ui->nexusLog->clear();
+ m_log->clear();
m_nexusLogin->start();
- updateNexusState();
+ updateState();
}
-void NexusSettingsTab::on_nexusManualKey_clicked()
+void NexusConnectionUI::manual()
{
if (m_nexusValidator && m_nexusValidator->isActive()) {
m_nexusValidator->cancel();
return;
}
- NexusManualKeyDialog d(&dialog());
+ NexusManualKeyDialog d(m_parent);
if (d.exec() != QDialog::Accepted) {
return;
}
@@ -218,162 +151,273 @@ void NexusSettingsTab::on_nexusManualKey_clicked()
return;
}
- ui->nexusLog->clear();
+ m_log->clear();
validateKey(key);
}
-void NexusSettingsTab::on_nexusDisconnect_clicked()
+void NexusConnectionUI::disconnect()
{
clearKey();
- ui->nexusLog->clear();
- addNexusLog(QObject::tr("Disconnected."));
-}
-
-void NexusSettingsTab::on_clearCacheButton_clicked()
-{
- QDir(Settings::instance().paths().cache()).removeRecursively();
- NexusInterface::instance(dialog().pluginContainer())->clearCache();
-}
-
-void NexusSettingsTab::on_associateButton_clicked()
-{
- Settings::instance().nexus().registerAsNXMHandler(true);
+ m_log->clear();
+ addLog(tr("Disconnected."));
}
-void NexusSettingsTab::validateKey(const QString& key)
+void NexusConnectionUI::validateKey(const QString& key)
{
if (!m_nexusValidator) {
m_nexusValidator.reset(new NexusKeyValidator(
- *NexusInterface::instance(dialog().pluginContainer())->getAccessManager()));
+ *NexusInterface::instance().getAccessManager()));
m_nexusValidator->finished = [&](auto&& r, auto&& m, auto&& u) {
onValidatorFinished(r, m, u);
};
}
- addNexusLog(QObject::tr("Checking API key..."));
+ addLog(tr("Checking API key..."));
m_nexusValidator->start(key, NexusKeyValidator::OneShot);
}
-void NexusSettingsTab::onSSOKeyChanged(const QString& key)
+void NexusConnectionUI::onSSOKeyChanged(const QString& key)
{
if (key.isEmpty()) {
clearKey();
} else {
- addNexusLog(QObject::tr("Received API key."));
+ addLog(tr("Received API key."));
validateKey(key);
}
}
-void NexusSettingsTab::onSSOStateChanged(NexusSSOLogin::States s, const QString& e)
+void NexusConnectionUI::onSSOStateChanged(
+ NexusSSOLogin::States s, const QString& e)
{
if (s != NexusSSOLogin::Finished) {
// finished state is handled in onSSOKeyChanged()
const auto log = NexusSSOLogin::stateToString(s, e);
for (auto&& line : log.split("\n")) {
- addNexusLog(line);
+ addLog(line);
}
}
- updateNexusState();
+ updateState();
}
-void NexusSettingsTab::onValidatorFinished(
+void NexusConnectionUI::onValidatorFinished(
ValidationAttempt::Result r, const QString& message,
std::optional user)
{
if (user) {
- NexusInterface::instance(dialog().pluginContainer())->setUserAccount(*user);
- addNexusLog(QObject::tr("Received user acount information"));
+ NexusInterface::instance().setUserAccount(*user);
+ addLog(tr("Received user account information"));
if (setKey(user->apiKey())) {
- addNexusLog(QObject::tr("Linked with Nexus successfully."));
+ addLog(tr("Linked with Nexus successfully."));
} else {
- addNexusLog(QObject::tr("Failed to set API key"));
+ addLog(tr("Failed to set API key"));
}
} else {
if (message.isEmpty()) {
// shouldn't happen
- addNexusLog("Unknown error");
+ addLog("Unknown error");
} else {
- addNexusLog(message);
+ addLog(message);
}
}
- updateNexusState();
+ updateState();
}
-void NexusSettingsTab::addNexusLog(const QString& s)
+void NexusConnectionUI::addLog(const QString& s)
{
- ui->nexusLog->addItem(s);
- ui->nexusLog->scrollToBottom();
+ m_log->addItem(s);
+ m_log->scrollToBottom();
}
-bool NexusSettingsTab::setKey(const QString& key)
+bool NexusConnectionUI::setKey(const QString& key)
{
- dialog().setExitNeeded(Exit::Restart);
- const bool ret = settings().nexus().setApiKey(key);
- updateNexusState();
+ const bool ret = m_settings.nexus().setApiKey(key);
+ updateState();
+
+ emit keyChanged();
+
return ret;
}
-bool NexusSettingsTab::clearKey()
+bool NexusConnectionUI::clearKey()
{
- dialog().setExitNeeded(Exit::Restart);
- const auto ret = settings().nexus().clearApiKey();
+ const auto ret = m_settings.nexus().clearApiKey();
+
+ NexusInterface::instance().getAccessManager()->clearApiKey();
+ updateState();
- NexusInterface::instance(dialog().pluginContainer())->getAccessManager()->clearApiKey();
- updateNexusState();
+ emit keyChanged();
return ret;
}
-void NexusSettingsTab::updateNexusState()
+void NexusConnectionUI::updateState()
{
- updateNexusButtons();
- updateNexusData();
-}
+ auto setButton = [&](QAbstractButton* b, bool enabled, QString caption={}) {
+ if (b) {
+ b->setEnabled(enabled);
+ if (!caption.isEmpty()) {
+ b->setText(caption);
+ }
+ }
+ };
-void NexusSettingsTab::updateNexusButtons()
-{
if (m_nexusLogin && m_nexusLogin->isActive()) {
// api key is in the process of being retrieved
- ui->nexusConnect->setText(QObject::tr("Cancel"));
- ui->nexusConnect->setEnabled(true);
- ui->nexusDisconnect->setEnabled(false);
- ui->nexusManualKey->setText(QObject::tr("Enter API Key Manually"));
- ui->nexusManualKey->setEnabled(false);
+ setButton(m_connect, true, QObject::tr("Cancel"));
+ setButton(m_disconnect, false);
+ setButton(m_manual, false,QObject::tr("Enter API Key Manually"));
}
else if (m_nexusValidator && m_nexusValidator->isActive()) {
// api key is in the process of being tested
- ui->nexusConnect->setText(QObject::tr("Connect to Nexus"));
- ui->nexusConnect->setEnabled(false);
- ui->nexusDisconnect->setEnabled(false);
- ui->nexusManualKey->setText(QObject::tr("Cancel"));
- ui->nexusManualKey->setEnabled(true);
+ setButton(m_connect, false, QObject::tr("Connect to Nexus"));
+ setButton(m_disconnect, false);
+ setButton(m_manual, true, QObject::tr("Cancel"));
}
- else if (settings().nexus().hasApiKey()) {
+ else if (m_settings.nexus().hasApiKey()) {
// api key is present
- ui->nexusConnect->setText(QObject::tr("Connect to Nexus"));
- ui->nexusConnect->setEnabled(false);
- ui->nexusDisconnect->setEnabled(true);
- ui->nexusManualKey->setText(QObject::tr("Enter API Key Manually"));
- ui->nexusManualKey->setEnabled(false);
+ setButton(m_connect, false, QObject::tr("Connect to Nexus"));
+ setButton(m_disconnect, true);
+ setButton(m_manual, false, QObject::tr("Enter API Key Manually"));
} else {
// api key not present
- ui->nexusConnect->setText(QObject::tr("Connect to Nexus"));
- ui->nexusConnect->setEnabled(true);
- ui->nexusDisconnect->setEnabled(false);
- ui->nexusManualKey->setText(QObject::tr("Enter API Key Manually"));
- ui->nexusManualKey->setEnabled(true);
+ setButton(m_connect, true, QObject::tr("Connect to Nexus"));
+ setButton(m_disconnect, false);
+ setButton(m_manual, true, QObject::tr("Enter API Key Manually"));
+ }
+
+ emit stateChanged();
+}
+
+
+
+NexusSettingsTab::NexusSettingsTab(Settings& s, SettingsDialog& d)
+ : SettingsTab(s, d), m_connectionUI(s, &d)
+{
+ ui->offlineBox->setChecked(settings().network().offlineMode());
+ ui->proxyBox->setChecked(settings().network().useProxy());
+ ui->endorsementBox->setChecked(settings().nexus().endorsementIntegration());
+ ui->hideAPICounterBox->setChecked(settings().interface().hideAPICounter());
+
+ // display server preferences
+ for (const auto& server : s.network().servers()) {
+ QString descriptor = server.name();
+
+ if (!descriptor.compare("CDN", Qt::CaseInsensitive)) {
+ descriptor += QStringLiteral(" (automatic)");
+ }
+
+ const auto averageSpeed = server.averageSpeed();
+ if (averageSpeed > 0) {
+ descriptor += QString(" (%1)").arg(MOBase::localizedByteSpeed(averageSpeed));
+ }
+
+ QListWidgetItem *newItem = new ServerItem(descriptor, Qt::UserRole + 1);
+
+ newItem->setData(Qt::UserRole, server.name());
+ newItem->setData(Qt::UserRole + 1, server.preferred());
+
+ if (server.preferred() > 0) {
+ ui->preferredServersList->addItem(newItem);
+ } else {
+ ui->knownServersList->addItem(newItem);
+ }
+
+ ui->preferredServersList->sortItems(Qt::DescendingOrder);
}
+
+ m_connectionUI.set(
+ ui->nexusConnect,
+ ui->nexusDisconnect,
+ ui->nexusManualKey,
+ ui->nexusLog);
+
+ QObject::connect(
+ &m_connectionUI, &NexusConnectionUI::stateChanged, &d,
+ [&]{ updateNexusData(); }, Qt::QueuedConnection);
+
+ QObject::connect(
+ &m_connectionUI, &NexusConnectionUI::keyChanged, &d,
+ [&]{ dialog().setExitNeeded(Exit::Restart); });
+
+
+ QObject::connect(ui->clearCacheButton, &QPushButton::clicked, [&]{ on_clearCacheButton_clicked(); });
+ QObject::connect(ui->associateButton, &QPushButton::clicked, [&]{ on_associateButton_clicked(); });
+}
+
+void NexusSettingsTab::update()
+{
+ settings().network().setOfflineMode(ui->offlineBox->isChecked());
+ settings().network().setUseProxy(ui->proxyBox->isChecked());
+ settings().nexus().setEndorsementIntegration(ui->endorsementBox->isChecked());
+ settings().interface().setHideAPICounter(ui->hideAPICounterBox->isChecked());
+
+ auto servers = settings().network().servers();
+
+ // store server preference
+ for (int i = 0; i < ui->knownServersList->count(); ++i) {
+ const QString key = ui->knownServersList->item(i)->data(Qt::UserRole).toString();
+
+ bool found = false;
+
+ for (auto& server : servers) {
+ if (server.name() == key) {
+ server.setPreferred(0);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ log::error("while setting preferred to 0, server '{}' not found", key);
+ }
+ }
+
+ const int count = ui->preferredServersList->count();
+
+ for (int i = 0; i < count; ++i) {
+ const QString key = ui->preferredServersList->item(i)->data(Qt::UserRole).toString();
+ const int newPreferred = count - i;
+
+ bool found = false;
+
+ for (auto& server : servers) {
+
+ if (server.name() == key) {
+ server.setPreferred(newPreferred);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ log::error(
+ "while setting preference to {}, server '{}' not found",
+ newPreferred, key);
+ }
+ }
+
+ settings().network().updateServers(servers);
+}
+
+void NexusSettingsTab::on_clearCacheButton_clicked()
+{
+ QDir(Settings::instance().paths().cache()).removeRecursively();
+ NexusInterface::instance().clearCache();
+}
+
+void NexusSettingsTab::on_associateButton_clicked()
+{
+ Settings::instance().nexus().registerAsNXMHandler(true);
}
void NexusSettingsTab::updateNexusData()
{
- const auto user = NexusInterface::instance(dialog().pluginContainer())
- ->getAPIUserAccount();
+ const auto user = NexusInterface::instance().getAPIUserAccount();
if (user.isValid()) {
ui->nexusUserID->setText(user.id());
diff --git a/src/settingsdialognexus.h b/src/settingsdialognexus.h
index 2cb1cc1e..0adf67c7 100644
--- a/src/settingsdialognexus.h
+++ b/src/settingsdialognexus.h
@@ -5,38 +5,67 @@
#include "settingsdialog.h"
#include "nxmaccessmanager.h"
-class NexusSettingsTab : public SettingsTab
+class NexusConnectionUI : public QObject
{
+ Q_OBJECT;
+
public:
- NexusSettingsTab(Settings& settings, SettingsDialog& dialog);
- void update();
+ NexusConnectionUI(Settings& s, QWidget* parent=nullptr);
+
+ void set(
+ QAbstractButton* connectButton,
+ QAbstractButton* disconnectButton,
+ QAbstractButton* manualButton,
+ QListWidget* logList);
+
+ void connect();
+ void manual();
+ void disconnect();
+
+signals:
+ void stateChanged();
+ void keyChanged();
private:
+ QWidget* m_parent;
+ Settings& m_settings;
+ QAbstractButton* m_connect;
+ QAbstractButton* m_disconnect;
+ QAbstractButton* m_manual;
+ QListWidget* m_log;
+
std::unique_ptr m_nexusLogin;
std::unique_ptr m_nexusValidator;
- void on_nexusConnect_clicked();
- void on_nexusManualKey_clicked();
- void on_nexusDisconnect_clicked();
- void on_clearCacheButton_clicked();
- void on_associateButton_clicked();
+ void addLog(const QString& s);
+
+ void updateState();
void validateKey(const QString& key);
bool setKey(const QString& key);
bool clearKey();
- void updateNexusState();
- void updateNexusButtons();
- void updateNexusData();
-
void onSSOKeyChanged(const QString& key);
void onSSOStateChanged(NexusSSOLogin::States s, const QString& e);
void onValidatorFinished(
ValidationAttempt::Result r, const QString& message,
std::optional useR);
+};
+
- void addNexusLog(const QString& s);
+class NexusSettingsTab : public SettingsTab
+{
+public:
+ NexusSettingsTab(Settings& settings, SettingsDialog& dialog);
+ void update();
+
+private:
+ NexusConnectionUI m_connectionUI;
+
+ void on_clearCacheButton_clicked();
+ void on_associateButton_clicked();
+ void updateNexusData();
};
#endif // SETTINGSDIALOGNEXUS_H
--
cgit v1.3.1
From 6f21f3a19fbd82bc43c97dcab877959220ce2f22 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Thu, 30 Jul 2020 01:17:30 -0400
Subject: disable portable instance button if one exists
---
src/createinstancedialog.ui | 18 ++++++++++++++----
src/createinstancedialogpages.cpp | 12 ++++++++++--
src/instancemanager.cpp | 5 ++---
src/instancemanager.h | 2 +-
4 files changed, 27 insertions(+), 10 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index ebaef84d..a3c3db92 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -181,6 +181,16 @@
+ -
+
+
+ A portable instance already exists.
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
-
@@ -266,8 +276,8 @@
0
0
- 63
- 16
+ 455
+ 286
@@ -402,8 +412,8 @@
0
0
- 63
- 16
+ 455
+ 278
diff --git a/src/createinstancedialogpages.cpp b/src/createinstancedialogpages.cpp
index b2e3612f..127243c6 100644
--- a/src/createinstancedialogpages.cpp
+++ b/src/createinstancedialogpages.cpp
@@ -171,11 +171,19 @@ TypePage::TypePage(CreateInstanceDialog& dlg)
{
ui->createGlobal->setDescription(
ui->createGlobal->description()
- .arg(InstanceManager::instance().instancesPath()));
+ .arg(InstanceManager::instance().instancesPath()));
ui->createPortable->setDescription(
ui->createPortable->description()
- .arg(InstanceManager::portablePath()));
+ .arg(InstanceManager::portablePath()));
+
+ if (InstanceManager::instance().portableInstanceExists()) {
+ ui->createPortable->setEnabled(false);
+ ui->portableExistsLabel->setVisible(true);
+ } else {
+ ui->createPortable->setEnabled(true);
+ ui->portableExistsLabel->setVisible(false);
+ }
QObject::connect(
ui->createGlobal, &QAbstractButton::clicked, [&]{ global(); });
diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp
index 2c8d8fb3..b6798fa9 100644
--- a/src/instancemanager.cpp
+++ b/src/instancemanager.cpp
@@ -344,7 +344,7 @@ QString InstanceManager::portablePath()
return qApp->applicationDirPath();
}
-bool InstanceManager::portableInstall() const
+bool InstanceManager::portableInstanceExists() const
{
return QFile::exists(qApp->applicationDirPath() + "/" +
QString::fromStdWString(AppConfig::iniFileName()));
@@ -357,7 +357,6 @@ bool InstanceManager::portableInstallIsLocked() const
QString::fromStdWString(AppConfig::portableLockFileName()));
}
-
bool InstanceManager::allowedToChangeInstance() const
{
return !portableInstallIsLocked();
@@ -388,7 +387,7 @@ QString InstanceManager::determineDataPath()
{
instanceId.clear();
}
- if (instanceId.isEmpty() && !m_Reset && (m_overrideInstance || portableInstall()))
+ if (instanceId.isEmpty() && !m_Reset && (m_overrideInstance || portableInstanceExists()))
{
// startup, apparently using portable mode before
return qApp->applicationDirPath();
diff --git a/src/instancemanager.h b/src/instancemanager.h
index f038678a..9250ffe9 100644
--- a/src/instancemanager.h
+++ b/src/instancemanager.h
@@ -54,6 +54,7 @@ public:
bool allowedToChangeInstance() const;
static bool isPortablePath(const QString& dataPath);
static QString portablePath();
+ bool portableInstanceExists() const;
QString instancesPath() const;
QStringList instanceNames() const;
@@ -76,7 +77,6 @@ private:
QString chooseInstance(const QStringList &instanceList) const;
void createDataPath(const QString &dataPath) const;
- bool portableInstall() const;
bool portableInstallIsLocked() const;
private:
--
cgit v1.3.1
From ea4485857c09fd3ab6879966e7377d3c56951a85 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Thu, 30 Jul 2020 04:36:12 -0400
Subject: filter, explore buttons, instance rename
---
src/createinstancedialog.ui | 21 +++++-
src/createinstancedialogpages.cpp | 62 ++-------------
src/instancemanager.cpp | 9 +++
src/instancemanager.h | 1 +
src/instancemanagerdialog.cpp | 154 ++++++++++++++++++++++++++++++++++++--
src/instancemanagerdialog.h | 12 ++-
src/instancemanagerdialog.ui | 27 ++++++-
7 files changed, 221 insertions(+), 65 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index a3c3db92..b7f4f502 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -77,9 +77,12 @@
-
-
+
- Never show this again
+ <html><head/><body><p><a href="https://github.com/ModOrganizer2/modorganizer/wiki/Instance">More information</a></p></body></html>
+
+
+ true
@@ -96,6 +99,13 @@
+ -
+
+
+ Never show this page again
+
+
+
@@ -1202,6 +1212,13 @@
+
+
+ LinkLabel
+ QLabel
+
+
+
diff --git a/src/createinstancedialogpages.cpp b/src/createinstancedialogpages.cpp
index 127243c6..8d304635 100644
--- a/src/createinstancedialogpages.cpp
+++ b/src/createinstancedialogpages.cpp
@@ -21,50 +21,6 @@ QString makeDefaultPath(const std::wstring& dir)
QString::fromStdWString(dir)));
}
-QString sanitizeFileName(const QString& name)
-{
- QString new_name = name;
-
- // Restrict the allowed characters
- new_name = new_name.remove(QRegExp("[^A-Za-z0-9 _=+;!@#$%^'\\-\\.\\[\\]\\{\\}\\(\\)]"));
-
- // Don't end in spaces and periods
- new_name = new_name.remove(QRegExp("\\.*$"));
- new_name = new_name.remove(QRegExp(" *$"));
-
- // Recurse until stuff stops changing
- if (new_name != name) {
- return sanitizeFileName(new_name);
- }
-
- return new_name;
-}
-
-// same thing as above, but allows path separators and colons
-//
-QString sanitizePath(const QString& path)
-{
- QString new_name = path;
-
- // Restrict the allowed characters
- new_name = new_name.remove(QRegExp("[^\\\\\\/A-Za-z0-9 _=+;!@#$%^:'\\-\\.\\[\\]\\{\\}\\(\\)]"));
-
- // Don't end in spaces and periods
- new_name = new_name.remove(QRegExp("\\.*$"));
- new_name = new_name.remove(QRegExp(" *$"));
-
- // Recurse until stuff stops changing
- if (new_name != path) {
- return sanitizeFileName(new_name);
- }
-
- return new_name;
-}
-
-void setPossiblePlaceholder(
- QLabel* label, const QString& s, const QString& arg)
-{
-}
PlaceholderLabel::PlaceholderLabel(QLabel* label)
@@ -762,7 +718,7 @@ QString NamePage::selectedInstanceName() const
}
const auto text = ui->instanceName->text().trimmed();
- return sanitizeFileName(text);
+ return InstanceManager::instance().sanitizeInstanceName(text);
}
void NamePage::onChanged()
@@ -790,12 +746,10 @@ bool NamePage::checkName(QString parentDir, QString name)
if (name.isEmpty()) {
empty = true;
} else {
- const QString sanitized = sanitizeFileName(name);
-
- if (name != sanitized) {
- invalid = true;
- } else {
+ if (InstanceManager::instance().validInstanceName(name)) {
exists = QDir(parentDir).exists(name);
+ } else {
+ invalid = true;
}
}
@@ -963,11 +917,9 @@ bool PathsPage::checkPath(
if (path.isEmpty()) {
empty = true;
} else {
- const QString sanitized = sanitizePath(path);
+ const QDir d(path);
- if (path != sanitized) {
- invalid = true;
- } else {
+ if (InstanceManager::instance().validInstanceName(d.dirName())) {
if (m_dlg.instanceType() == CreateInstanceDialog::Portable) {
// the default data path for a portable instance is the application
// directory, so it's not an error if it exists
@@ -977,6 +929,8 @@ bool PathsPage::checkPath(
} else {
exists = QDir(path).exists();
}
+ } else {
+ invalid = true;
}
}
diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp
index b6798fa9..111f948b 100644
--- a/src/instancemanager.cpp
+++ b/src/instancemanager.cpp
@@ -676,3 +676,12 @@ QString InstanceManager::sanitizeInstanceName(const QString &name) const
}
return new_name;
}
+
+bool InstanceManager::validInstanceName(const QString& instanceName) const
+{
+ if (instanceName.isEmpty()) {
+ return false;
+ }
+
+ return (instanceName == sanitizeInstanceName(instanceName));
+}
diff --git a/src/instancemanager.h b/src/instancemanager.h
index 9250ffe9..33e115a7 100644
--- a/src/instancemanager.h
+++ b/src/instancemanager.h
@@ -63,6 +63,7 @@ public:
QString sanitizeInstanceName(const QString &name) const;
QString makeUniqueName(const QString& instanceName) const;
bool instanceExists(const QString& instanceName) const;
+ bool validInstanceName(const QString& instanceName) const;
QString instancePath(const QString& instanceName) const;
private:
diff --git a/src/instancemanagerdialog.cpp b/src/instancemanagerdialog.cpp
index a038d3c2..aa6bdb04 100644
--- a/src/instancemanagerdialog.cpp
+++ b/src/instancemanagerdialog.cpp
@@ -8,8 +8,12 @@
#include "shared/appconfig.h"
#include
+namespace shell = MOBase::shell;
+
void openInstanceManager(PluginContainer& pc, QWidget* parent)
{
+ //CreateInstanceDialog dlg(pc, parent);
+ //dlg.exec();
InstanceManagerDialog dlg(pc, parent);
dlg.exec();
}
@@ -77,12 +81,20 @@ InstanceManagerDialog::InstanceManagerDialog(
ui->splitter->setStretchFactor(0, 0);
ui->splitter->setStretchFactor(1, 1);
+ auto* model = new QStandardItemModel;
+ ui->list->setModel(model);
+
+ m_filter.setEdit(ui->filter);
+ m_filter.setList(ui->list);
+ m_filter.setUpdateDelay(false);
+ m_filter.setFilteredBorder(false);
+
auto& m = InstanceManager::instance();
for (auto&& d : m.instancePaths()) {
auto ii = std::make_unique(d);
- ui->list->addItem(ii->name());
+ model->appendRow(new QStandardItem(ii->name()));
m_instances.push_back(std::move(ii));
}
@@ -91,8 +103,12 @@ InstanceManagerDialog::InstanceManagerDialog(
}
connect(ui->createNew, &QPushButton::clicked, [&]{ createNew(); });
- connect(ui->list, &QListWidget::itemSelectionChanged, [&]{ onSelection(); });
+ connect(ui->list->selectionModel(), &QItemSelectionModel::selectionChanged, [&]{ onSelection(); });
//connect(ui->list, &QListWidget::itemActivated, [&]{ openSelectedInstance(); });
+ connect(ui->rename, &QPushButton::clicked, [&]{ rename(); });
+ connect(ui->exploreLocation, &QPushButton::clicked, [&]{ exploreLocation(); });
+ connect(ui->exploreBaseDirectory, &QPushButton::clicked, [&]{ exploreBaseDirectory(); });
+ connect(ui->exploreGame, &QPushButton::clicked, [&]{ exploreGame(); });
}
InstanceManagerDialog::~InstanceManagerDialog() = default;
@@ -105,11 +121,15 @@ void InstanceManagerDialog::select(std::size_t i)
const auto& ii = m_instances[i];
fill(*ii);
+
+ ui->list->selectionModel()->select(
+ m_filter.mapFromSource(m_filter.sourceModel()->index(i, 0)),
+ QItemSelectionModel::ClearAndSelect);
}
void InstanceManagerDialog::openSelectedInstance()
{
- const auto i = singleSelection();
+ const auto i = singleSelectionIndex();
if (i == NoSelection) {
return;
}
@@ -117,9 +137,107 @@ void InstanceManagerDialog::openSelectedInstance()
InstanceManager::instance().switchToInstance(m_instances[i]->name());
}
+void InstanceManagerDialog::rename()
+{
+ auto* i = singleSelection();
+ if (!i) {
+ return;
+ }
+
+ auto& m = InstanceManager::instance();
+ if (m.currentInstance() == i->name()) {
+ QMessageBox::information(this,
+ tr("Rename instance"), tr("The active instance cannot be renamed"));
+ return;
+ }
+
+ QDialog dlg(this);
+ dlg.setWindowTitle(tr("Rename instance"));
+
+ auto* ly = new QVBoxLayout(&dlg);
+
+ auto* bb = new QDialogButtonBox(
+ QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
+
+ auto* text = new QLineEdit(i->name());
+ text->selectAll();
+
+ auto* error = new QLabel;
+
+ ly->addWidget(new QLabel(tr("Instance name")));
+ ly->addWidget(text);
+ ly->addWidget(error);
+ ly->addStretch();
+ ly->addWidget(bb);
+
+ connect(text, &QLineEdit::textChanged, [&] {
+ bool okay = false;
+
+ if (!m.validInstanceName(text->text())) {
+ error->setText(tr("The instance name must be a valid folder name."));
+ } else {
+ const auto name = m.sanitizeInstanceName(text->text());
+
+ if ((name != i->name()) && m.instanceExists(text->text())) {
+ error->setText(tr("An instance with this name already exists."));
+ } else {
+ okay = true;
+ }
+ }
+
+ error->setVisible(!okay);
+ bb->button(QDialogButtonBox::Ok)->setEnabled(okay);
+ });
+
+ connect(bb, &QDialogButtonBox::accepted, [&]{ dlg.accept(); });
+ connect(bb, &QDialogButtonBox::rejected, [&]{ dlg.reject(); });
+
+ dlg.resize({400, 120});
+ if (dlg.exec() != QDialog::Accepted) {
+ return;
+ }
+
+
+ const QString newName = m.sanitizeInstanceName(text->text());
+ const QString src = QDir::toNativeSeparators(i->location());
+ const QString dest = QDir::toNativeSeparators(
+ QFileInfo(i->location()).dir().path() + "/" + newName);
+
+ const auto r = shell::Rename(src, dest, false);
+ if (!r) {
+ QMessageBox::critical(
+ this, tr("Error"),
+ tr("Failed to rename \"%1\" to \"%2\": %3")
+ .arg(src).arg(dest).arg(r.toString()));
+
+ return;
+ }
+}
+
+void InstanceManagerDialog::exploreLocation()
+{
+ if (const auto* i=singleSelection()) {
+ shell::Explore(i->location());
+ }
+}
+
+void InstanceManagerDialog::exploreBaseDirectory()
+{
+ if (const auto* i=singleSelection()) {
+ shell::Explore(i->baseDirectory());
+ }
+}
+
+void InstanceManagerDialog::exploreGame()
+{
+ if (const auto* i=singleSelection()) {
+ shell::Explore(i->gamePath());
+ }
+}
+
void InstanceManagerDialog::onSelection()
{
- const auto i = singleSelection();
+ const auto i = singleSelectionIndex();
if (i == NoSelection) {
return;
}
@@ -133,14 +251,36 @@ void InstanceManagerDialog::createNew()
dlg.exec();
}
-std::size_t InstanceManagerDialog::singleSelection() const
+std::size_t InstanceManagerDialog::singleSelectionIndex() const
{
- const auto sel = ui->list->selectionModel()->selectedIndexes();
+ const auto sel = m_filter.mapSelectionToSource(
+ ui->list->selectionModel()->selection());
+
if (sel.size() != 1) {
return NoSelection;
}
- return static_cast(sel[0].row());
+ return static_cast(sel.indexes()[0].row());
+}
+
+InstanceInfo* InstanceManagerDialog::singleSelection()
+{
+ const auto i = singleSelectionIndex();
+ if (i == NoSelection) {
+ return nullptr;
+ }
+
+ return m_instances[i].get();
+}
+
+const InstanceInfo* InstanceManagerDialog::singleSelection() const
+{
+ const auto i = singleSelectionIndex();
+ if (i == NoSelection) {
+ return nullptr;
+ }
+
+ return m_instances[i].get();
}
void InstanceManagerDialog::fill(const InstanceInfo& ii)
diff --git a/src/instancemanagerdialog.h b/src/instancemanagerdialog.h
index 6dbf015f..529a99b8 100644
--- a/src/instancemanagerdialog.h
+++ b/src/instancemanagerdialog.h
@@ -1,6 +1,7 @@
#ifndef MODORGANIZER_INSTANCEMANAGERDIALOG_INCLUDED
#define MODORGANIZER_INSTANCEMANAGERDIALOG_INCLUDED
+#include
#include
namespace Ui { class InstanceManagerDialog; };
@@ -21,17 +22,26 @@ public:
void select(std::size_t i);
void openSelectedInstance();
+ void rename();
+ void exploreLocation();
+ void exploreBaseDirectory();
+ void exploreGame();
+
private:
static const std::size_t NoSelection = -1;
std::unique_ptr ui;
const PluginContainer& m_pc;
std::vector> m_instances;
+ MOBase::FilterWidget m_filter;
void onSelection();
void createNew();
- std::size_t singleSelection() const;
+ std::size_t singleSelectionIndex() const;
+ InstanceInfo* singleSelection();
+ const InstanceInfo* singleSelection() const;
+
void fill(const InstanceInfo& ii);
};
diff --git a/src/instancemanagerdialog.ui b/src/instancemanagerdialog.ui
index 146b5fb5..08894ec1 100644
--- a/src/instancemanagerdialog.ui
+++ b/src/instancemanagerdialog.ui
@@ -103,7 +103,32 @@
0
-
-
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Filter
+
+
+
+
+
--
cgit v1.3.1
From fb2cddd92a1f09fef22dc66c737aa608408aaa18 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Tue, 3 Nov 2020 11:13:28 -0500
Subject: replace "create instance" title by "setting up instance" fixed bad
game location for custom paths
---
src/createinstancedialog.cpp | 7 ++++++-
src/createinstancedialog.h | 6 +++---
src/createinstancedialog.ui | 11 +++++++++--
src/main.cpp | 10 +++++-----
4 files changed, 23 insertions(+), 11 deletions(-)
(limited to 'src/createinstancedialog.ui')
diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp
index d67e3451..d2846367 100644
--- a/src/createinstancedialog.cpp
+++ b/src/createinstancedialog.cpp
@@ -99,13 +99,18 @@ void CreateInstanceDialog::back()
changePage(-1);
}
-void CreateInstanceDialog::setSinglePageImpl()
+void CreateInstanceDialog::setSinglePageImpl(const QString& instanceName)
{
m_singlePage = true;
if (m_pages[ui->pages->currentIndex()]->skip()) {
next();
}
+
+ // don't show the "create a new instance" title for single pages, this is
+ // when the instance already exists but some info is missing
+ ui->title->setText(tr("Setting up instance %1").arg(instanceName));
+ setWindowTitle(tr("Setting up an instance %1").arg(instanceName));
}
void CreateInstanceDialog::changePage(int d)
diff --git a/src/createinstancedialog.h b/src/createinstancedialog.h
index 6947f2e2..f05495c6 100644
--- a/src/createinstancedialog.h
+++ b/src/createinstancedialog.h
@@ -58,7 +58,7 @@ public:
Settings* settings();
template
- void setSinglePage()
+ void setSinglePage(const QString& instanceName)
{
for (auto&& p : m_pages) {
if (auto* tp=dynamic_cast(p.get())) {
@@ -68,7 +68,7 @@ public:
}
}
- setSinglePageImpl();
+ setSinglePageImpl(instanceName);
}
template
@@ -113,7 +113,7 @@ private:
bool m_singlePage;
- void setSinglePageImpl();
+ void setSinglePageImpl(const QString& instanceName);
template
T getSelected(T (cid::Page::*mf)() const) const
diff --git a/src/createinstancedialog.ui b/src/createinstancedialog.ui
index b7f4f502..b10d74a7 100644
--- a/src/createinstancedialog.ui
+++ b/src/createinstancedialog.ui
@@ -30,9 +30,16 @@
0
-
-
+
+
+
+ 14
+ 75
+ true
+
+
- <h2>Creating a new instance</h2>
+ Creating a new instance
diff --git a/src/main.cpp b/src/main.cpp
index 2a5a3e81..bfc074ec 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -344,7 +344,7 @@ SetupInstanceResults setupInstance(Instance& instance, PluginContainer& pc)
.arg(instance.name()).arg(instance.iniPath()));
CreateInstanceDialog dlg(pc, nullptr);
- dlg.setSinglePage();
+ dlg.setSinglePage(instance.name());
dlg.show();
dlg.activateWindow();
@@ -356,7 +356,7 @@ SetupInstanceResults setupInstance(Instance& instance, PluginContainer& pc)
instance.setGame(
dlg.creationInfo().game->gameName(),
- dlg.creationInfo().game->gameDirectory().absolutePath());
+ dlg.creationInfo().gameLocation);
return SetupInstanceResults::TryAgain;
}
@@ -384,7 +384,7 @@ SetupInstanceResults setupInstance(Instance& instance, PluginContainer& pc)
.arg(instance.gameName()));
CreateInstanceDialog dlg(pc, nullptr);
- dlg.setSinglePage();
+ dlg.setSinglePage(instance.name());
dlg.show();
dlg.activateWindow();
@@ -396,7 +396,7 @@ SetupInstanceResults setupInstance(Instance& instance, PluginContainer& pc)
instance.setGame(
dlg.creationInfo().game->gameName(),
- dlg.creationInfo().game->gameDirectory().absolutePath());
+ dlg.creationInfo().gameLocation);
return SetupInstanceResults::TryAgain;
}
@@ -408,7 +408,7 @@ SetupInstanceResults setupInstance(Instance& instance, PluginContainer& pc)
dlg.getPage()->select(
instance.gamePlugin(), instance.gameDirectory());
- dlg.setSinglePage();
+ dlg.setSinglePage(instance.name());
dlg.show();
dlg.activateWindow();
--
cgit v1.3.1