diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/createinstancedialog.cpp | 9 | ||||
| -rw-r--r-- | src/createinstancedialog.h | 6 | ||||
| -rw-r--r-- | src/createinstancedialogpages.cpp | 5 | ||||
| -rw-r--r-- | src/instancemanagerdialog.cpp | 2 | ||||
| -rw-r--r-- | src/main.cpp | 27 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 4 | ||||
| -rw-r--r-- | src/modlist.cpp | 41 | ||||
| -rw-r--r-- | src/modlist.h | 14 | ||||
| -rw-r--r-- | src/nexusinterface.cpp | 28 | ||||
| -rw-r--r-- | src/nexusinterface.h | 6 | ||||
| -rw-r--r-- | src/nxmaccessmanager.cpp | 37 | ||||
| -rw-r--r-- | src/nxmaccessmanager.h | 11 | ||||
| -rw-r--r-- | src/organizercore.cpp | 4 | ||||
| -rw-r--r-- | src/organizerproxy.cpp | 212 | ||||
| -rw-r--r-- | src/organizerproxy.h | 59 | ||||
| -rw-r--r-- | src/plugincontainer.cpp | 88 | ||||
| -rw-r--r-- | src/pluginlist.cpp | 60 | ||||
| -rw-r--r-- | src/pluginlist.h | 18 | ||||
| -rw-r--r-- | src/settings.cpp | 62 | ||||
| -rw-r--r-- | src/settings.h | 36 | ||||
| -rw-r--r-- | src/settingsdialognexus.cpp | 18 | ||||
| -rw-r--r-- | src/settingsdialognexus.h | 4 |
23 files changed, 623 insertions, 130 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 844f5e19..eec33460 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,6 +33,7 @@ add_filter(NAME src/core GROUPS nexusinterface nxmaccessmanager organizercore + plugincontainer apiuseraccount processrunner qdirfiletree @@ -136,7 +137,6 @@ add_filter(NAME src/modlist GROUPS ) add_filter(NAME src/plugins GROUPS - plugincontainer pluginlist pluginlistsortproxy pluginlistview diff --git a/src/createinstancedialog.cpp b/src/createinstancedialog.cpp index f4140e01..0f62fcf6 100644 --- a/src/createinstancedialog.cpp +++ b/src/createinstancedialog.cpp @@ -11,8 +11,8 @@ using namespace MOBase; CreateInstanceDialog::CreateInstanceDialog( - const PluginContainer& pc, QWidget *parent) : - QDialog(parent), ui(new Ui::CreateInstanceDialog), m_pc(pc), + const PluginContainer& pc, Settings* s, QWidget *parent) : + QDialog(parent), ui(new Ui::CreateInstanceDialog), m_pc(pc), m_settings(s), m_switching(false) { using namespace cid; @@ -55,6 +55,11 @@ const PluginContainer& CreateInstanceDialog::pluginContainer() return m_pc; } +Settings* CreateInstanceDialog::settings() +{ + return m_settings; +} + bool CreateInstanceDialog::isOnLastPage() const { for (int i=ui->pages->currentIndex() + 1; i < ui->pages->count(); ++i) { diff --git a/src/createinstancedialog.h b/src/createinstancedialog.h index 95d4fa68..0841ef29 100644 --- a/src/createinstancedialog.h +++ b/src/createinstancedialog.h @@ -8,6 +8,7 @@ namespace Ui { class CreateInstanceDialog; }; namespace cid { class Page; } class PluginContainer; +class Settings; class CreateInstanceDialog : public QDialog { @@ -47,12 +48,14 @@ public: explicit CreateInstanceDialog( - const PluginContainer& pc, QWidget *parent = nullptr); + const PluginContainer& pc, Settings* s, QWidget *parent = nullptr); ~CreateInstanceDialog(); Ui::CreateInstanceDialog* getUI(); + const PluginContainer& pluginContainer(); + Settings* settings(); void next(); void back(); @@ -77,6 +80,7 @@ public: private: std::unique_ptr<Ui::CreateInstanceDialog> ui; const PluginContainer& m_pc; + Settings* m_settings; std::vector<std::unique_ptr<cid::Page>> m_pages; QString m_originalNext; bool m_switching; diff --git a/src/createinstancedialogpages.cpp b/src/createinstancedialogpages.cpp index 73b265c8..d809079d 100644 --- a/src/createinstancedialogpages.cpp +++ b/src/createinstancedialogpages.cpp @@ -964,7 +964,8 @@ NexusPage::NexusPage(CreateInstanceDialog& dlg) : Page(dlg), m_skip(false) { m_connectionUI.reset(new NexusConnectionUI( - Settings::instance(), &m_dlg, + &m_dlg, + dlg.settings(), ui->nexusConnect, nullptr, ui->nexusManual, @@ -972,7 +973,7 @@ NexusPage::NexusPage(CreateInstanceDialog& dlg) // just check it once, or connecting and then going back and forth would skip // the page, which would be unexpected - m_skip = Settings::instance().nexus().hasApiKey(); + m_skip = GlobalSettings::hasNexusApiKey(); } NexusPage::~NexusPage() = default; diff --git a/src/instancemanagerdialog.cpp b/src/instancemanagerdialog.cpp index 3b9dd344..7b8522ee 100644 --- a/src/instancemanagerdialog.cpp +++ b/src/instancemanagerdialog.cpp @@ -718,7 +718,7 @@ void InstanceManagerDialog::onSelection() void InstanceManagerDialog::createNew() { - CreateInstanceDialog dlg(m_pc, this); + CreateInstanceDialog dlg(m_pc, &Settings::instance(), this); if (dlg.exec() != QDialog::Accepted) { return; } diff --git a/src/main.cpp b/src/main.cpp index 93580931..fd5a47c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,6 +26,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "nxmaccessmanager.h" #include "instancemanager.h" #include "instancemanagerdialog.h" +#include "createinstancedialog.h" #include "organizercore.h" #include "env.h" #include "envmodule.h" @@ -329,6 +330,9 @@ int runApplication( // this must outlive `organizer` std::unique_ptr<PluginContainer> pluginContainer; + log::debug("initializing nexus interface"); + NexusInterface ni(&settings); + log::debug("initializing core"); OrganizerCore organizer(settings); if (!organizer.bootstrap()) { @@ -394,8 +398,8 @@ int runApplication( auto splash = createSplash(settings, dataPath, game); QString apiKey; - if (settings.nexus().apiKey(apiKey)) { - NexusInterface::instance().getAccessManager()->apiCheck(apiKey); + if (GlobalSettings::nexusApiKey(apiKey)) { + ni.getAccessManager()->apiCheck(apiKey); } log::debug("initializing tutorials"); @@ -415,8 +419,7 @@ int runApplication( // set up main window and its data structures MainWindow mainWindow(settings, organizer, *pluginContainer); - NexusInterface::instance() - .getAccessManager()->setTopLevelWidget(&mainWindow); + ni.getAccessManager()->setTopLevelWidget(&mainWindow); QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), &application, SLOT(setStyleFile(QString))); @@ -443,8 +446,7 @@ int runApplication( res = application.exec(); mainWindow.close(); - NexusInterface::instance() - .getAccessManager()->setTopLevelWidget(nullptr); + ni.getAccessManager()->setTopLevelWidget(nullptr); } settings.geometry().resetIfNeeded(); @@ -507,6 +509,7 @@ QString determineDataPath(const cl::CommandLine& cl) } } + int doOneRun( cl::CommandLine& cl, MOApplication& application, SingleInstance& instance) { @@ -515,6 +518,18 @@ int doOneRun( // resets things when MO is "restarted" resetForRestart(cl); + + //{ + // NexusInterface ni(nullptr); + // + // PluginContainer pc(nullptr); + // pc.loadPlugins(); + // + // CreateInstanceDialog dlg(pc, nullptr); + // dlg.exec(); + //} + + const QString dataPath = determineDataPath(cl); if (dataPath.isEmpty()) { return 1; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 3ef34e93..9ad51510 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -4226,7 +4226,7 @@ void MainWindow::checkModsForUpdates() NexusInterface::instance().requestTrackingInfo(this, QVariant(), QString()); } else { QString apiKey; - if (m_OrganizerCore.settings().nexus().apiKey(apiKey)) { + if (GlobalSettings::nexusApiKey(apiKey)) { m_OrganizerCore.doAfterLogin([this] () { this->checkModsForUpdates(); }); NexusInterface::instance().getAccessManager()->apiCheck(apiKey); } else { @@ -5434,7 +5434,7 @@ void MainWindow::modUpdateCheck(std::multimap<QString, int> IDs) ModInfo::manualUpdateCheck(this, IDs); } else { QString apiKey; - if (m_OrganizerCore.settings().nexus().apiKey(apiKey)) { + if (GlobalSettings::nexusApiKey(apiKey)) { m_OrganizerCore.doAfterLogin([=]() { this->modUpdateCheck(IDs); }); NexusInterface::instance().getAccessManager()->apiCheck(apiKey); } else diff --git a/src/modlist.cpp b/src/modlist.cpp index 1f845999..bf9aef83 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -1528,3 +1528,44 @@ void ModList::disableSelected(const QItemSelectionModel *selectionModel) m_Profile->setModsEnabled(QList<unsigned int>(), modsToDisable); } } + + +QString DummyModList::displayName(const QString &internalName) const +{ + return {}; +} + +QStringList DummyModList::allMods() const +{ + return {}; +} + +IModList::ModStates DummyModList::state(const QString &name) const +{ + return 0; +} + +bool DummyModList::setActive(const QString &name, bool active) +{ + return true; +} + +int DummyModList::priority(const QString &name) const +{ + return -1; +} + +bool DummyModList::setPriority(const QString &name, int newPriority) +{ + return true; +} + +bool DummyModList::onModStateChanged(const std::function<void(const QString&, ModStates)> &func) +{ + return true; +} + +bool DummyModList::onModMoved(const std::function<void (const QString &, int, int)> &func) +{ + return true; +} diff --git a/src/modlist.h b/src/modlist.h index 385ca04c..3ab486c9 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -397,5 +397,19 @@ private: };
+
+class DummyModList : public MOBase::IModList
+{
+public:
+ QString displayName(const QString &internalName) const override;
+ QStringList allMods() const override;
+ ModStates state(const QString &name) const override;
+ bool setActive(const QString &name, bool active) override;
+ int priority(const QString &name) const override;
+ bool setPriority(const QString &name, int newPriority) override;
+ bool onModStateChanged(const std::function<void(const QString&, ModStates)> &func) override;
+ bool onModMoved(const std::function<void (const QString &, int, int)> &func) override;
+};
+
#endif // MODLIST_H
diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp index 396cec11..1364d7e1 100644 --- a/src/nexusinterface.cpp +++ b/src/nexusinterface.cpp @@ -23,6 +23,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "nxmaccessmanager.h" #include "selectiondialog.h" #include "bbcode.h" +#include "settings.h" #include <utility.h> #include "shared/util.h" #include <log.h> @@ -235,31 +236,42 @@ APILimits NexusInterface::parseLimits( } -NexusInterface::NexusInterface() +static NexusInterface* g_instance = nullptr; + +NexusInterface::NexusInterface(Settings* s) : m_PluginContainer(nullptr) { + MO_ASSERT(!g_instance); + g_instance = this; + m_User.limits(defaultAPILimits()); m_MOVersion = createVersionInfo(); - m_AccessManager = new NXMAccessManager(this, m_MOVersion.displayString(3)); + m_AccessManager = new NXMAccessManager( + this, s, m_MOVersion.displayString(3)); + m_DiskCache = new QNetworkDiskCache(this); + connect(m_AccessManager, SIGNAL(requestNXMDownload(QString)), this, SLOT(downloadRequestedNXM(QString))); } -NXMAccessManager *NexusInterface::getAccessManager() +NexusInterface::~NexusInterface() { - return m_AccessManager; + cleanup(); + + MO_ASSERT(g_instance == this); + g_instance = nullptr; } -NexusInterface::~NexusInterface() +NXMAccessManager *NexusInterface::getAccessManager() { - cleanup(); + return m_AccessManager; } NexusInterface& NexusInterface::instance() { - static NexusInterface ni; - return ni; + MO_ASSERT(g_instance); + return *g_instance; } void NexusInterface::setCacheDirectory(const QString &directory) diff --git a/src/nexusinterface.h b/src/nexusinterface.h index 72f30a38..cf365b2e 100644 --- a/src/nexusinterface.h +++ b/src/nexusinterface.h @@ -40,7 +40,7 @@ namespace MOBase { class IPluginGame; } class NexusInterface; class NXMAccessManager; - +class Settings; /** * @brief convenience class to make nxm requests easier @@ -153,7 +153,9 @@ public: static APILimits parseLimits(const QNetworkReply* reply); static APILimits parseLimits(const QList<QNetworkReply::RawHeaderPair>& headers); + NexusInterface(Settings* s); ~NexusInterface(); + static NexusInterface& instance(); /** @@ -533,8 +535,6 @@ private: static const int MAX_ACTIVE_DOWNLOADS = 6; private: - - NexusInterface(); void nextRequest(); void requestFinished(std::list<NXMRequestInfo>::iterator iter); MOBase::IPluginGame *getGame(QString gameName) const; diff --git a/src/nxmaccessmanager.cpp b/src/nxmaccessmanager.cpp index 2fe676ba..6c8b9054 100644 --- a/src/nxmaccessmanager.cpp +++ b/src/nxmaccessmanager.cpp @@ -48,8 +48,8 @@ const QString NexusSSO("wss://sso.nexusmods.com"); const QString NexusSSOPage("https://www.nexusmods.com/sso?id=%1&application=modorganizer2"); -ValidationProgressDialog::ValidationProgressDialog(NexusKeyValidator& v) - : m_validator(v), m_updateTimer(nullptr), m_first(true) +ValidationProgressDialog::ValidationProgressDialog(Settings* s, NexusKeyValidator& v) + : m_settings(s), m_validator(v), m_updateTimer(nullptr), m_first(true) { ui.reset(new Ui::ValidationProgressDialog); ui->setupUi(this); @@ -98,7 +98,10 @@ void ValidationProgressDialog::stop() void ValidationProgressDialog::showEvent(QShowEvent* e) { if (m_first) { - Settings::instance().geometry().centerOnMainWindowMonitor(this); + if (m_settings) { + m_settings->geometry().centerOnMainWindowMonitor(this); + } + m_first = false; } } @@ -592,8 +595,8 @@ void ValidationAttempt::cleanup() } -NexusKeyValidator::NexusKeyValidator(NXMAccessManager& am) - : m_manager(am) +NexusKeyValidator::NexusKeyValidator(Settings* s, NXMAccessManager& am) + : m_settings(s), m_manager(am) { } @@ -602,6 +605,15 @@ NexusKeyValidator::~NexusKeyValidator() cancel(); } +std::vector<std::chrono::seconds> NexusKeyValidator::getTimeouts() const +{ + if (m_settings) { + return m_settings->nexus().validationTimeouts(); + } else { + return {10s, 15s, 20s}; + } +} + void NexusKeyValidator::start(const QString& key, Behaviour b) { if (isActive()) { @@ -611,7 +623,7 @@ void NexusKeyValidator::start(const QString& key, Behaviour b) m_key = key; - const auto timeouts = Settings::instance().nexus().validationTimeouts(); + const auto timeouts = getTimeouts(); switch (b) { @@ -755,10 +767,11 @@ void NexusKeyValidator::setFinished( } -NXMAccessManager::NXMAccessManager(QObject *parent, const QString &moVersion) +NXMAccessManager::NXMAccessManager(QObject *parent, Settings* s, const QString &moVersion) : QNetworkAccessManager(parent) + , m_Settings(s) , m_MOVersion(moVersion) - , m_validator(*this) + , m_validator(s, *this) , m_validationState(NotChecked) { m_validator.finished = [&](auto&& r, auto&& m, auto&& u) { @@ -769,8 +782,10 @@ NXMAccessManager::NXMAccessManager(QObject *parent, const QString &moVersion) onValidatorAttemptFinished(a); }; - setCookieJar(new PersistentCookieJar(QDir::fromNativeSeparators( - Settings::instance().paths().cache() + "/nexus_cookies.dat"))); + if (m_Settings) { + setCookieJar(new PersistentCookieJar(QDir::fromNativeSeparators( + m_Settings->paths().cache() + "/nexus_cookies.dat"))); + } if (networkAccessible() == QNetworkAccessManager::UnknownAccessibility) { // why is this necessary all of a sudden? @@ -963,7 +978,7 @@ void NXMAccessManager::clearApiKey() void NXMAccessManager::startProgress() { if (!m_ProgressDialog) { - m_ProgressDialog.reset(new ValidationProgressDialog(m_validator)); + m_ProgressDialog.reset(new ValidationProgressDialog(m_Settings, m_validator)); } m_ProgressDialog->start(); diff --git a/src/nxmaccessmanager.h b/src/nxmaccessmanager.h index 6a45d880..60100467 100644 --- a/src/nxmaccessmanager.h +++ b/src/nxmaccessmanager.h @@ -33,6 +33,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. namespace MOBase { class IPluginGame; } namespace Ui { class ValidationProgressDialog; } class NXMAccessManager; +class Settings; class NexusSSOLogin { @@ -146,7 +147,7 @@ public: std::function<FinishedCallback> finished; std::function<void (const ValidationAttempt&)> attemptFinished; - NexusKeyValidator(NXMAccessManager& am); + NexusKeyValidator(Settings* s, NXMAccessManager& am); ~NexusKeyValidator(); void start(const QString& key, Behaviour b); @@ -157,11 +158,13 @@ public: const ValidationAttempt* currentAttempt() const; private: + Settings* m_settings; NXMAccessManager& m_manager; QString m_key; std::vector<std::unique_ptr<ValidationAttempt>> m_attempts; void createAttempts(const std::vector<std::chrono::seconds>& timeouts); + std::vector<std::chrono::seconds> getTimeouts() const; bool nextTry(); void onAttemptSuccess(const ValidationAttempt& a, const APIUserAccount& u); @@ -178,7 +181,7 @@ class ValidationProgressDialog : public QDialog Q_OBJECT; public: - ValidationProgressDialog(NexusKeyValidator& v); + ValidationProgressDialog(Settings* s, NexusKeyValidator& v); void setParentWidget(QWidget* w); @@ -191,6 +194,7 @@ protected: private: std::unique_ptr<Ui::ValidationProgressDialog> ui; + Settings* m_settings; NexusKeyValidator& m_validator; QTimer* m_updateTimer; bool m_first; @@ -209,7 +213,7 @@ class NXMAccessManager : public QNetworkAccessManager { Q_OBJECT public: - NXMAccessManager(QObject *parent, const QString &moVersion); + NXMAccessManager(QObject *parent, Settings* s, const QString &moVersion); void setTopLevelWidget(QWidget* w); @@ -264,6 +268,7 @@ private: }; QWidget* m_TopLevel; + Settings* m_Settings; mutable std::unique_ptr<ValidationProgressDialog> m_ProgressDialog; QString m_MOVersion; NexusKeyValidator m_validator; diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 7fd8c33b..0d561581 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -339,7 +339,7 @@ bool OrganizerCore::nexusApi(bool retry) return false; } else { QString apiKey; - if (m_Settings.nexus().apiKey(apiKey)) { + if (GlobalSettings::nexusApiKey(apiKey)) { // credentials stored or user entered them manually log::debug("attempt to verify nexus api key"); accessManager->apiCheck(apiKey); @@ -1426,7 +1426,7 @@ void OrganizerCore::loggedInAction(QWidget* parent, std::function<void ()> f) f(); } else { QString apiKey; - if (settings().nexus().apiKey(apiKey)) { + if (GlobalSettings::nexusApiKey(apiKey)) { doAfterLogin([f]{ f(); }); NexusInterface::instance().getAccessManager()->apiCheck(apiKey); } else { diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp index 45efc00c..8cc95a8b 100644 --- a/src/organizerproxy.cpp +++ b/src/organizerproxy.cpp @@ -287,3 +287,215 @@ bool OrganizerProxy::onPluginSettingChanged(std::function<void(QString const&, c // Always call this one, otherwise plugin cannot detect they are being enabled / disabled:
return m_Proxied->onPluginSettingChanged(func);
}
+
+
+
+DummyOrganizerProxy::DummyOrganizerProxy(const QString &pluginName) :
+ m_PluginName(pluginName),
+ m_mods(new DummyModList), m_plugins(new DummyPluginList)
+{
+}
+
+DummyOrganizerProxy::~DummyOrganizerProxy() = default;
+
+IModRepositoryBridge *DummyOrganizerProxy::createNexusBridge() const
+{
+ return nullptr;
+}
+
+QString DummyOrganizerProxy::profileName() const
+{
+ return {};
+}
+
+QString DummyOrganizerProxy::profilePath() const
+{
+ return {};
+}
+
+QString DummyOrganizerProxy::downloadsPath() const
+{
+ return {};
+}
+
+QString DummyOrganizerProxy::overwritePath() const
+{
+ return {};
+}
+
+QString DummyOrganizerProxy::basePath() const
+{
+ return {};
+}
+
+QString DummyOrganizerProxy::modsPath() const
+{
+ return {};
+}
+
+VersionInfo DummyOrganizerProxy::appVersion() const
+{
+ return {};
+}
+
+IModInterface *DummyOrganizerProxy::getMod(const QString &name) const
+{
+ return nullptr;
+}
+
+IPluginGame *DummyOrganizerProxy::getGame(const QString &gameName) const
+{
+ return nullptr;
+}
+
+IModInterface *DummyOrganizerProxy::createMod(MOBase::GuessedValue<QString> &name)
+{
+ return nullptr;
+}
+
+bool DummyOrganizerProxy::removeMod(IModInterface *mod)
+{
+ return true;
+}
+
+void DummyOrganizerProxy::modDataChanged(IModInterface *mod)
+{
+}
+
+QVariant DummyOrganizerProxy::pluginSetting(const QString &pluginName, const QString &key) const
+{
+ if (key == "enabled") {
+ return true;
+ }
+
+ return {};
+}
+
+void DummyOrganizerProxy::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value)
+{
+}
+
+QVariant DummyOrganizerProxy::persistent(const QString &pluginName, const QString &key, const QVariant &def) const
+{
+ return {};
+}
+
+void DummyOrganizerProxy::setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync)
+{
+}
+
+QString DummyOrganizerProxy::pluginDataPath() const
+{
+ return qApp->applicationDirPath() + "/" + ToQString(AppConfig::pluginPath()) + "/data";
+}
+
+HANDLE DummyOrganizerProxy::startApplication(
+ const QString& exe, const QStringList& args, const QString &cwd,
+ const QString& profile, const QString &overwrite, bool ignoreOverwrite)
+{
+ return INVALID_HANDLE_VALUE;
+}
+
+bool DummyOrganizerProxy::waitForApplication(HANDLE handle, LPDWORD exitCode) const
+{
+ return true;
+}
+
+bool DummyOrganizerProxy::onAboutToRun(const std::function<bool (const QString &)> &func)
+{
+ return true;
+}
+
+bool DummyOrganizerProxy::onFinishedRun(const std::function<void (const QString &, unsigned int)> &func)
+{
+ return true;
+}
+
+bool DummyOrganizerProxy::onModInstalled(const std::function<void (const QString &)> &func)
+{
+ return true;
+}
+
+bool DummyOrganizerProxy::onUserInterfaceInitialized(std::function<void(QMainWindow*)> const& func)
+{
+ return true;
+}
+
+bool DummyOrganizerProxy::onProfileChanged(std::function<void(MOBase::IProfile*, MOBase::IProfile*)> const& func)
+{
+ return true;
+}
+
+bool DummyOrganizerProxy::onPluginSettingChanged(std::function<void(QString const&, const QString& key, const QVariant&, const QVariant&)> const& func)
+{
+ return true;
+}
+
+void DummyOrganizerProxy::refreshModList(bool saveChanges)
+{
+}
+
+IModInterface *DummyOrganizerProxy::installMod(const QString &fileName, const QString &nameSuggestion)
+{
+ return nullptr;
+}
+
+QString DummyOrganizerProxy::resolvePath(const QString &fileName) const
+{
+ return {};
+}
+
+QStringList DummyOrganizerProxy::listDirectories(const QString &directoryName) const
+{
+ return {};
+}
+
+QStringList DummyOrganizerProxy::findFiles(const QString &path, const std::function<bool(const QString&)> &filter) const
+{
+ return {};
+}
+
+QStringList DummyOrganizerProxy::findFiles(const QString& path, const QStringList& globFilters) const
+{
+ return {};
+}
+
+QStringList DummyOrganizerProxy::getFileOrigins(const QString &fileName) const
+{
+ return {};
+}
+
+QList<MOBase::IOrganizer::FileInfo> DummyOrganizerProxy::findFileInfos(const QString &path, const std::function<bool (const MOBase::IOrganizer::FileInfo &)> &filter) const
+{
+ return {};
+}
+
+MOBase::IDownloadManager *DummyOrganizerProxy::downloadManager() const
+{
+ return nullptr;
+}
+
+MOBase::IPluginList *DummyOrganizerProxy::pluginList() const
+{
+ return m_plugins.get();
+}
+
+MOBase::IModList *DummyOrganizerProxy::modList() const
+{
+ return m_mods.get();
+}
+
+MOBase::IProfile *DummyOrganizerProxy::profile() const
+{
+ return nullptr;
+}
+
+MOBase::IPluginGame const *DummyOrganizerProxy::managedGame() const
+{
+ return nullptr;
+}
+
+QStringList DummyOrganizerProxy::modsSortedByProfilePriority() const
+{
+ return {};
+}
diff --git a/src/organizerproxy.h b/src/organizerproxy.h index 6690d612..3bd70113 100644 --- a/src/organizerproxy.h +++ b/src/organizerproxy.h @@ -81,4 +81,63 @@ private: };
+
+class DummyOrganizerProxy : public MOBase::IOrganizer
+{
+public:
+ DummyOrganizerProxy(const QString &pluginName);
+ ~DummyOrganizerProxy();
+
+ virtual MOBase::IModRepositoryBridge *createNexusBridge() const;
+ virtual QString profileName() const;
+ virtual QString profilePath() const;
+ virtual QString downloadsPath() const;
+ virtual QString overwritePath() const;
+ virtual QString basePath() const;
+ virtual QString modsPath() const;
+ virtual MOBase::VersionInfo appVersion() const;
+ virtual MOBase::IModInterface *getMod(const QString &name) const;
+ virtual MOBase::IPluginGame *getGame(const QString &gameName) const;
+ virtual MOBase::IModInterface *createMod(MOBase::GuessedValue<QString> &name);
+ virtual bool removeMod(MOBase::IModInterface *mod);
+ virtual void modDataChanged(MOBase::IModInterface *mod);
+ virtual QVariant pluginSetting(const QString &pluginName, const QString &key) const;
+ virtual void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value);
+ virtual QVariant persistent(const QString &pluginName, const QString &key, const QVariant &def = QVariant()) const;
+ virtual void setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync = true);
+ virtual QString pluginDataPath() const;
+ virtual MOBase::IModInterface *installMod(const QString &fileName, const QString &nameSuggestion = QString());
+ virtual QString resolvePath(const QString &fileName) const;
+ virtual QStringList listDirectories(const QString &directoryName) const;
+ virtual QStringList findFiles(const QString &path, const std::function<bool(const QString &)> &filter) const override;
+ virtual QStringList findFiles(const QString &path, const QStringList &globFilters) const override;
+ virtual QStringList getFileOrigins(const QString &fileName) const;
+ virtual QList<FileInfo> findFileInfos(const QString &path, const std::function<bool(const FileInfo&)> &filter) const;
+
+ virtual MOBase::IDownloadManager *downloadManager() const;
+ virtual MOBase::IPluginList *pluginList() const;
+ virtual MOBase::IModList *modList() const;
+ virtual MOBase::IProfile *profile() const override;
+ virtual HANDLE startApplication(const QString &executable, const QStringList &args = QStringList(), const QString &cwd = "",
+ const QString &profile = "", const QString &forcedCustomOverwrite = "", bool ignoreCustomOverwrite = false);
+ virtual bool waitForApplication(HANDLE handle, LPDWORD exitCode = nullptr) const;
+ virtual void refreshModList(bool saveChanges);
+
+ virtual bool onAboutToRun(const std::function<bool(const QString&)> &func);
+ virtual bool onFinishedRun(const std::function<void (const QString&, unsigned int)> &func);
+ virtual bool onModInstalled(const std::function<void (const QString&)> &func);
+ virtual bool onUserInterfaceInitialized(std::function<void(QMainWindow*)> const& func);
+ virtual bool onProfileChanged(std::function<void(MOBase::IProfile*, MOBase::IProfile*)> const& func);
+ virtual bool onPluginSettingChanged(std::function<void(QString const&, const QString& key, const QVariant&, const QVariant&)> const& func);
+
+ virtual MOBase::IPluginGame const *managedGame() const;
+
+ virtual QStringList modsSortedByProfilePriority() const;
+
+private:
+ const QString &m_PluginName;
+ std::unique_ptr<MOBase::IPluginList> m_plugins;
+ std::unique_ptr<MOBase::IModList> m_mods;
+};
+
#endif // ORGANIZERPROXY_H
diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp index 4771359d..6f2670dd 100644 --- a/src/plugincontainer.cpp +++ b/src/plugincontainer.cpp @@ -173,10 +173,21 @@ bool PluginContainer::verifyPlugin(IPlugin *plugin) {
if (plugin == nullptr) {
return false;
- } else if (!plugin->init(new OrganizerProxy(m_Organizer, this, plugin))) {
+ }
+
+ IOrganizer* proxy = nullptr;
+
+ if (m_Organizer) {
+ proxy = new OrganizerProxy(m_Organizer, this, plugin);
+ } else {
+ proxy = new DummyOrganizerProxy(plugin);
+ }
+
+ if (!plugin->init(proxy)) {
log::warn("plugin failed to initialize");
return false;
}
+
return true;
}
@@ -200,7 +211,9 @@ bool PluginContainer::registerPlugin(QObject *plugin, const QString &fileName) return false;
}
plugin->setProperty("filename", fileName);
- m_Organizer->settings().plugins().registerPlugin(pluginObj);
+ if (m_Organizer) {
+ m_Organizer->settings().plugins().registerPlugin(pluginObj);
+ }
}
{ // diagnosis plugin
@@ -244,7 +257,9 @@ bool PluginContainer::registerPlugin(QObject *plugin, const QString &fileName) IPluginInstaller *installer = qobject_cast<IPluginInstaller*>(plugin);
if (verifyPlugin(installer)) {
bf::at_key<IPluginInstaller>(m_Plugins).push_back(installer);
- m_Organizer->installationManager()->registerInstaller(installer);
+ if (m_Organizer) {
+ m_Organizer->installationManager()->registerInstaller(installer);
+ }
return true;
}
}
@@ -317,7 +332,7 @@ void PluginContainer::unloadPlugins() }
// disconnect all slots before unloading plugins so plugins don't have to take care of that
- if (m_Organizer != nullptr) {
+ if (m_Organizer) {
m_Organizer->disconnectPlugins();
}
@@ -363,24 +378,28 @@ void PluginContainer::loadPlugins() registerPlugin(plugin, "");
}
- QFile loadCheck(qApp->property("dataPath").toString() + "/plugin_loadcheck.tmp");
- if (loadCheck.exists() && loadCheck.open(QIODevice::ReadOnly)) {
- // oh, there was a failed plugin load last time. Find out which plugin was loaded last
- QString fileName;
- while (!loadCheck.atEnd()) {
- fileName = QString::fromUtf8(loadCheck.readLine().constData()).trimmed();
- }
- if (QMessageBox::question(nullptr, QObject::tr("Plugin error"),
- QObject::tr("It appears the plugin \"%1\" failed to load last startup and caused MO to crash. Do you want to disable it?\n"
- "(Please note: If this is the first time you see this message for this plugin you may want to give it another try. "
- "The plugin may be able to recover from the problem)").arg(fileName),
- QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) {
- m_Organizer->settings().plugins().addBlacklist(fileName);
+ QFile loadCheck;
+
+ if (m_Organizer) {
+ loadCheck.setFileName(qApp->property("dataPath").toString() + "/plugin_loadcheck.tmp");
+ if (loadCheck.exists() && loadCheck.open(QIODevice::ReadOnly)) {
+ // oh, there was a failed plugin load last time. Find out which plugin was loaded last
+ QString fileName;
+ while (!loadCheck.atEnd()) {
+ fileName = QString::fromUtf8(loadCheck.readLine().constData()).trimmed();
+ }
+ if (QMessageBox::question(nullptr, QObject::tr("Plugin error"),
+ QObject::tr("It appears the plugin \"%1\" failed to load last startup and caused MO to crash. Do you want to disable it?\n"
+ "(Please note: If this is the first time you see this message for this plugin you may want to give it another try. "
+ "The plugin may be able to recover from the problem)").arg(fileName),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) {
+ m_Organizer->settings().plugins().addBlacklist(fileName);
+ }
+ loadCheck.close();
}
- loadCheck.close();
- }
- loadCheck.open(QIODevice::WriteOnly);
+ loadCheck.open(QIODevice::WriteOnly);
+ }
QString pluginPath = qApp->applicationDirPath() + "/" + ToQString(AppConfig::pluginPath());
log::debug("looking for plugins in {}", QDir::toNativeSeparators(pluginPath));
@@ -388,13 +407,20 @@ void PluginContainer::loadPlugins() while (iter.hasNext()) {
iter.next();
- if (m_Organizer->settings().plugins().blacklisted(iter.fileName())) {
- log::debug("plugin \"{}\" blacklisted", iter.fileName());
- continue;
+
+ if (m_Organizer) {
+ if (m_Organizer->settings().plugins().blacklisted(iter.fileName())) {
+ log::debug("plugin \"{}\" blacklisted", iter.fileName());
+ continue;
+ }
}
- loadCheck.write(iter.fileName().toUtf8());
- loadCheck.write("\n");
- loadCheck.flush();
+
+ if (loadCheck.isOpen()) {
+ loadCheck.write(iter.fileName().toUtf8());
+ loadCheck.write("\n");
+ loadCheck.flush();
+ }
+
QString pluginName = iter.filePath();
if (QLibrary::isLibrary(pluginName)) {
std::unique_ptr<QPluginLoader> pluginLoader(new QPluginLoader(pluginName, this));
@@ -416,12 +442,16 @@ void PluginContainer::loadPlugins() }
// remove the load check file on success
- loadCheck.remove();
+ if (loadCheck.isOpen()) {
+ loadCheck.remove();
+ }
- bf::at_key<IPluginDiagnose>(m_Plugins).push_back(m_Organizer);
bf::at_key<IPluginDiagnose>(m_Plugins).push_back(this);
- m_Organizer->connectPlugins(this);
+ if (m_Organizer) {
+ bf::at_key<IPluginDiagnose>(m_Plugins).push_back(m_Organizer);
+ m_Organizer->connectPlugins(this);
+ }
}
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index a4c1ec6d..7134d246 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -1671,3 +1671,63 @@ void PluginList::managedGameChanged(const IPluginGame *gamePlugin) {
m_GamePlugin = gamePlugin;
}
+
+
+
+QStringList DummyPluginList::pluginNames() const
+{
+ return {};
+}
+
+IPluginList::PluginStates DummyPluginList::state(const QString &name) const
+{
+ return 0;
+}
+
+void DummyPluginList::setState(const QString &name, PluginStates state)
+{
+}
+
+int DummyPluginList::priority(const QString &name) const
+{
+ return -1;
+}
+
+int DummyPluginList::loadOrder(const QString &name) const
+{
+ return -1;
+}
+
+void DummyPluginList::setLoadOrder(const QStringList &pluginList)
+{
+}
+
+bool DummyPluginList::isMaster(const QString &name) const
+{
+ return false;
+}
+
+QStringList DummyPluginList::masters(const QString &name) const
+{
+ return {};
+}
+
+QString DummyPluginList::origin(const QString &name) const
+{
+ return {};
+}
+
+bool DummyPluginList::onRefreshed(const std::function<void()> &callback)
+{
+ return true;
+}
+
+bool DummyPluginList::onPluginMoved(const std::function<void (const QString &, int, int)> &func)
+{
+ return true;
+}
+
+bool DummyPluginList::onPluginStateChanged(const std::function<void (const QString &, PluginStates)> &func)
+{
+ return true;
+}
diff --git a/src/pluginlist.h b/src/pluginlist.h index 0b49b86f..bfadaf4f 100644 --- a/src/pluginlist.h +++ b/src/pluginlist.h @@ -410,6 +410,24 @@ private: bool hasInfo(const ESPInfo& esp, const AdditionalInfo* info) const;
};
+
+class DummyPluginList : public MOBase::IPluginList
+{
+public:
+ QStringList pluginNames() const override;
+ PluginStates state(const QString &name) const override;
+ void setState(const QString &name, PluginStates state) override;
+ int priority(const QString &name) const override;
+ int loadOrder(const QString &name) const override;
+ void setLoadOrder(const QStringList &pluginList) override;
+ bool isMaster(const QString &name) const override;
+ QStringList masters(const QString &name) const override;
+ QString origin(const QString &name) const override;
+ bool onRefreshed(const std::function<void()> &callback) override;
+ bool onPluginMoved(const std::function<void (const QString &, int, int)> &func) override;
+ bool onPluginStateChanged(const std::function<void (const QString &, PluginStates)> &func) override;
+};
+
#pragma warning(pop)
#endif // PLUGINLIST_H
diff --git a/src/settings.cpp b/src/settings.cpp index b286510d..593d66bf 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1812,37 +1812,6 @@ NexusSettings::NexusSettings(Settings& parent, QSettings& settings) { } -bool NexusSettings::apiKey(QString& apiKey) const -{ - QString tempKey = getWindowsCredential("APIKEY"); - if (tempKey.isEmpty()) - return false; - - apiKey = tempKey; - return true; -} - -bool NexusSettings::setApiKey(const QString& apiKey) -{ - if (!setWindowsCredential("APIKEY", apiKey)) { - const auto e = GetLastError(); - log::error("Storing API key failed: {}", formatSystemMessage(e)); - return false; - } - - return true; -} - -bool NexusSettings::clearApiKey() -{ - return setApiKey(""); -} - -bool NexusSettings::hasApiKey() const -{ - return !getWindowsCredential("APIKEY").isEmpty(); -} - bool NexusSettings::endorsementIntegration() const { return get<bool>(m_Settings, "Settings", "endorsement_integration", true); @@ -2224,6 +2193,37 @@ void GlobalSettings::setHideTutorialQuestion(bool b) settings().setValue("HideTutorialQuestion", b); } +bool GlobalSettings::nexusApiKey(QString& apiKey) +{ + QString tempKey = getWindowsCredential("APIKEY"); + if (tempKey.isEmpty()) + return false; + + apiKey = tempKey; + return true; +} + +bool GlobalSettings::setNexusApiKey(const QString& apiKey) +{ + if (!setWindowsCredential("APIKEY", apiKey)) { + const auto e = GetLastError(); + log::error("Storing API key failed: {}", formatSystemMessage(e)); + return false; + } + + return true; +} + +bool GlobalSettings::clearNexusApiKey() +{ + return setNexusApiKey(""); +} + +bool GlobalSettings::hasNexusApiKey() +{ + return !getWindowsCredential("APIKEY").isEmpty(); +} + void GlobalSettings::resetDialogs() { setHideCreateInstanceIntro(false); diff --git a/src/settings.h b/src/settings.h index a9501b9d..f71949d2 100644 --- a/src/settings.h +++ b/src/settings.h @@ -498,24 +498,6 @@ class NexusSettings public: NexusSettings(Settings& parent, QSettings& settings); - // if the key exists from the credentials store, puts it in `apiKey` and - // returns true; otherwise, returns false and leaves `apiKey` untouched - // - bool apiKey(QString& apiKey) const; - - // sets the api key in the credentials store, removes it if empty; returns - // false on errors - // - bool setApiKey(const QString& apiKey); - - // removes the api key from the credentials store; returns false on errors - // - bool clearApiKey(); - - // returns whether an API key is currently stored - // - bool hasApiKey() const; - // returns whether endorsement integration is enabled // bool endorsementIntegration() const; @@ -844,6 +826,24 @@ public: static bool hideTutorialQuestion(); static void setHideTutorialQuestion(bool b); + // if the key exists from the credentials store, puts it in `apiKey` and + // returns true; otherwise, returns false and leaves `apiKey` untouched + // + static bool nexusApiKey(QString& apiKey); + + // sets the api key in the credentials store, removes it if empty; returns + // false on errors + // + static bool setNexusApiKey(const QString& apiKey); + + // removes the api key from the credentials store; returns false on errors + // + static bool clearNexusApiKey(); + + // returns whether an API key is currently stored + // + static bool hasNexusApiKey(); + // resets anything that the user can disable static void resetDialogs(); diff --git a/src/settingsdialognexus.cpp b/src/settingsdialognexus.cpp index 54af9b59..1ed4c58f 100644 --- a/src/settingsdialognexus.cpp +++ b/src/settingsdialognexus.cpp @@ -72,13 +72,14 @@ private: NexusConnectionUI::NexusConnectionUI( - Settings& s, QWidget* parent, + Settings* s, QAbstractButton* connectButton, QAbstractButton* disconnectButton, QAbstractButton* manualButton, QListWidget* logList) : - m_parent(parent), m_settings(s), + m_parent(parent), + m_settings(s), m_connect(connectButton), m_disconnect(disconnectButton), m_manual(manualButton), @@ -96,7 +97,7 @@ NexusConnectionUI::NexusConnectionUI( QObject::connect(manualButton, &QPushButton::clicked, [&]{ manual(); }); } - if (m_settings.nexus().hasApiKey()) { + if (GlobalSettings::hasNexusApiKey()) { addLog(tr("Connected.")); } else { addLog(tr("Not connected.")); @@ -162,7 +163,7 @@ void NexusConnectionUI::validateKey(const QString& key) { if (!m_nexusValidator) { m_nexusValidator.reset(new NexusKeyValidator( - *NexusInterface::instance().getAccessManager())); + m_settings, *NexusInterface::instance().getAccessManager())); m_nexusValidator->finished = [&](auto&& r, auto&& m, auto&& u) { onValidatorFinished(r, m, u); @@ -231,7 +232,7 @@ void NexusConnectionUI::addLog(const QString& s) bool NexusConnectionUI::setKey(const QString& key) { - const bool ret = m_settings.nexus().setApiKey(key); + const bool ret = GlobalSettings::setNexusApiKey(key); updateState(); emit keyChanged(); @@ -241,7 +242,7 @@ bool NexusConnectionUI::setKey(const QString& key) bool NexusConnectionUI::clearKey() { - const auto ret = m_settings.nexus().clearApiKey(); + const auto ret = GlobalSettings::clearNexusApiKey(); NexusInterface::instance().getAccessManager()->clearApiKey(); updateState(); @@ -274,7 +275,7 @@ void NexusConnectionUI::updateState() setButton(m_disconnect, false); setButton(m_manual, true, QObject::tr("Cancel")); } - else if (m_settings.nexus().hasApiKey()) { + else if (GlobalSettings::hasNexusApiKey()) { // api key is present setButton(m_connect, false, QObject::tr("Connect to Nexus")); setButton(m_disconnect, true); @@ -327,7 +328,8 @@ NexusSettingsTab::NexusSettingsTab(Settings& s, SettingsDialog& d) } m_connectionUI.reset(new NexusConnectionUI( - settings(), &dialog(), + &dialog(), + &settings(), ui->nexusConnect, ui->nexusDisconnect, ui->nexusManualKey, diff --git a/src/settingsdialognexus.h b/src/settingsdialognexus.h index a2d6a4f8..c915accf 100644 --- a/src/settingsdialognexus.h +++ b/src/settingsdialognexus.h @@ -13,8 +13,8 @@ class NexusConnectionUI : public QObject public: NexusConnectionUI( - Settings& s, QWidget* parent, + Settings* s, QAbstractButton* connectButton, QAbstractButton* disconnectButton, QAbstractButton* manualButton, @@ -30,7 +30,7 @@ signals: private: QWidget* m_parent; - Settings& m_settings; + Settings* m_settings; QAbstractButton* m_connect; QAbstractButton* m_disconnect; QAbstractButton* m_manual; |
