diff options
| author | isanae <14251494+isanae@users.noreply.github.com> | 2021-01-10 22:06:38 -0500 |
|---|---|---|
| committer | isanae <14251494+isanae@users.noreply.github.com> | 2021-01-18 08:20:07 -0500 |
| commit | 3bca0e761597f590fa3b1c6a57ee325e774e3f49 (patch) | |
| tree | 34a49c4754a26073a59f658b905b5cdae72e2235 /src | |
| parent | 59f055ba93381b965cdc04557ac1dce2df36bd07 (diff) | |
split run() into setup() and run()
this is so command line processing can happen outside of MOApplication
many important objects were local to run(), so they're not members of MOApplication instead
Diffstat (limited to 'src')
| -rw-r--r-- | src/instancemanager.cpp | 10 | ||||
| -rw-r--r-- | src/instancemanager.h | 4 | ||||
| -rw-r--r-- | src/main.cpp | 60 | ||||
| -rw-r--r-- | src/moapplication.cpp | 174 | ||||
| -rw-r--r-- | src/moapplication.h | 27 |
5 files changed, 152 insertions, 123 deletions
diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp index 18604bf1..a9905b75 100644 --- a/src/instancemanager.cpp +++ b/src/instancemanager.cpp @@ -544,7 +544,7 @@ void InstanceManager::clearOverrides() m_overrideProfileName = {}; } -std::optional<Instance> InstanceManager::currentInstance() const +std::unique_ptr<Instance> InstanceManager::currentInstance() const { const QString profile = m_overrideProfileName ? *m_overrideProfileName : ""; @@ -555,20 +555,20 @@ std::optional<Instance> InstanceManager::currentInstance() const if (!allowedToChangeInstance()) { // force portable instance - return Instance(portablePath(), true, profile); + return std::make_unique<Instance>(portablePath(), true, profile); } if (name.isEmpty()) { if (portableInstanceExists()) { // use portable - return Instance(portablePath(), true, profile); + return std::make_unique<Instance>(portablePath(), true, profile); } else { // no instance set return {}; } } - return Instance(instancePath(name), false, profile); + return std::make_unique<Instance>(instancePath(name), false, profile); } void InstanceManager::clearCurrentInstance() @@ -772,7 +772,7 @@ bool InstanceManager::validInstanceName(const QString& instanceName) const -std::optional<Instance> selectInstance() +std::unique_ptr<Instance> selectInstance() { auto& m = InstanceManager::singleton(); diff --git a/src/instancemanager.h b/src/instancemanager.h index 73082da2..893b88e4 100644 --- a/src/instancemanager.h +++ b/src/instancemanager.h @@ -264,7 +264,7 @@ public: // instance name in the registry is empty or non-existent and there is no // portable instance set up // - std::optional<Instance> currentInstance() const; + std::unique_ptr<Instance> currentInstance() const; // sets the instance name in the registry so the same instance is opened next // time MO runs @@ -359,7 +359,7 @@ enum class SetupInstanceResults // instance manager dialog and returns the selected instance or empty if the // user cancelled // -std::optional<Instance> selectInstance(); +std::unique_ptr<Instance> selectInstance(); // calls instance.setup() tries to handle problems by itself: // diff --git a/src/main.cpp b/src/main.cpp index 877236e1..362caaad 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,8 +4,10 @@ #include "organizercore.h" #include "commandline.h" #include "env.h" +#include "instancemanager.h" #include "thread_utils.h" #include "shared/util.h" +#include <report.h> #include <log.h> using namespace MOBase; @@ -31,7 +33,7 @@ int main(int argc, char *argv[]) TimeThis tt("main()"); QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - MOApplication app(cl, argc, argv); + MOApplication app(argc, argv); MOMultiProcess multiProcess(cl.multiple()); if (multiProcess.ephemeral()) { @@ -40,7 +42,61 @@ int main(int argc, char *argv[]) tt.stop(); - return app.run(multiProcess); + + // MO runs in a loop because it can be restarted in several ways, such as + // when switching instances or changing some settings + for (;;) + { + try + { + auto& m = InstanceManager::singleton(); + + if (cl.instance()) { + m.overrideInstance(*cl.instance()); + } + + if (cl.profile()) { + m.overrideProfile(*cl.profile()); + } + + { + const auto r = app.setup(multiProcess); + + if (r == RestartExitCode) { + // resets things when MO is "restarted" + app.resetForRestart(); + + // don't reprocess command line + cl.clear(); + + continue; + } + } + + if (auto r=cl.setupCore(app.core())) { + return *r; + } + + const auto r = app.run(multiProcess); + + if (r == RestartExitCode) { + // resets things when MO is "restarted" + app.resetForRestart(); + + // don't reprocess command line + cl.clear(); + + continue; + } + + return r; + } + catch (const std::exception &e) + { + reportError(e.what()); + return 1; + } + } } int forwardToPrimary(MOMultiProcess& multiProcess, const cl::CommandLine& cl) diff --git a/src/moapplication.cpp b/src/moapplication.cpp index 9a77c17e..d1622d59 100644 --- a/src/moapplication.cpp +++ b/src/moapplication.cpp @@ -155,77 +155,43 @@ void addDllsToPath() }
-MOApplication::MOApplication(cl::CommandLine& cl, int& argc, char** argv)
- : QApplication(argc, argv), m_cl(cl)
+MOApplication::MOApplication(int& argc, char** argv)
+ : QApplication(argc, argv)
{
TimeThis tt("MOApplication()");
- connect(&m_StyleWatcher, &QFileSystemWatcher::fileChanged, [&](auto&& file){
+ connect(&m_styleWatcher, &QFileSystemWatcher::fileChanged, [&](auto&& file){
log::debug("style file '{}' changed, reloading", file);
updateStyle(file);
});
- m_DefaultStyle = style()->objectName();
+ m_defaultStyle = style()->objectName();
setStyle(new ProxyStyle(style()));
addDllsToPath();
}
-int MOApplication::run(MOMultiProcess& multiProcess)
+OrganizerCore& MOApplication::core()
{
- TimeThis tt("MOApplication run() to doOneRun()");
-
- auto& m = InstanceManager::singleton();
-
- if (m_cl.instance())
- m.overrideInstance(*m_cl.instance());
+ return *m_core;
+}
- if (m_cl.profile()) {
- m.overrideProfile(*m_cl.profile());
- }
+int MOApplication::setup(MOMultiProcess& multiProcess)
+{
+ TimeThis tt("MOApplication setup()");
// makes plugin data path available to plugins, see
// IOrganizer::getPluginDataPath()
MOBase::details::setPluginDataPath(OrganizerCore::pluginDataPath());
- // MO runs in a loop because it can be restarted in several ways, such as
- // when switching instances or changing some settings
- for (;;)
- {
- try
- {
- tt.stop();
-
- const auto r = doOneRun(multiProcess);
-
- if (r == RestartExitCode) {
- // resets things when MO is "restarted"
- resetForRestart();
- continue;
- }
-
- return r;
- }
- catch (const std::exception &e)
- {
- reportError(e.what());
- return 1;
- }
- }
-}
-
-int MOApplication::doOneRun(MOMultiProcess& multiProcess)
-{
- TimeThis tt("MOApplication::doOneRun() instances");
-
// figuring out the current instance
- auto currentInstance = getCurrentInstance();
- if (!currentInstance) {
+ m_instance = getCurrentInstance();
+ if (!m_instance) {
return 1;
}
// first time the data path is available, set the global property and log
// directory, then log a bunch of debug stuff
- const QString dataPath = currentInstance->directory();
+ const QString dataPath = m_instance->directory();
setProperty("dataPath", dataPath);
if (!setLogDirectory(dataPath)) {
@@ -245,7 +211,7 @@ int MOApplication::doOneRun(MOMultiProcess& multiProcess) log::debug("another instance of MO is running but --multiple was given");
}
- log::info("data path: {}", currentInstance->directory());
+ log::info("data path: {}", m_instance->directory());
log::info("working directory: {}", QDir::currentPath());
@@ -261,44 +227,41 @@ int MOApplication::doOneRun(MOMultiProcess& multiProcess) // loading settings
- Settings settings(currentInstance->iniPath(), true);
- log::getDefault().setLevel(settings.diagnostics().logLevel());
- log::debug("using ini at '{}'", settings.filename());
+ m_settings.reset(new Settings(m_instance->iniPath(), true));
+ log::getDefault().setLevel(m_settings->diagnostics().logLevel());
+ log::debug("using ini at '{}'", m_settings->filename());
- OrganizerCore::setGlobalCoreDumpType(settings.diagnostics().coreDumpType());
+ OrganizerCore::setGlobalCoreDumpType(m_settings->diagnostics().coreDumpType());
tt.start("MOApplication::doOneRun() log and checks");
// logging and checking
env::Environment env;
- env.dump(settings);
- settings.dump();
+ env.dump(*m_settings);
+ m_settings->dump();
sanity::checkEnvironment(env);
- const auto moduleNotification = env.onModuleLoaded(qApp, [](auto&& m) {
+ m_modules = std::move(env.onModuleLoaded(qApp, [](auto&& m) {
if (m.interesting()) {
log::debug("loaded module {}", m.toString());
}
sanity::checkIncompatibleModule(m);
- });
+ }));
- // this must outlive `organizer`
- std::unique_ptr<PluginContainer> pluginContainer;
-
// nexus interface
tt.start("MOApplication::doOneRun() NexusInterface");
log::debug("initializing nexus interface");
- NexusInterface ni(&settings);
+ m_nexus.reset(new NexusInterface(m_settings.get()));
// organizer core
tt.start("MOApplication::doOneRun() OrganizerCore");
log::debug("initializing core");
- OrganizerCore organizer(settings);
- if (!organizer.bootstrap()) {
+ m_core.reset(new OrganizerCore(*m_settings));
+ if (!m_core->bootstrap()) {
reportError("failed to set up data paths");
InstanceManager::singleton().clearCurrentInstance();
return 1;
@@ -308,58 +271,59 @@ int MOApplication::doOneRun(MOMultiProcess& multiProcess) tt.start("MOApplication::doOneRun() plugins");
log::debug("initializing plugins");
- pluginContainer = std::make_unique<PluginContainer>(&organizer);
- pluginContainer->loadPlugins();
+ m_plugins = std::make_unique<PluginContainer>(m_core.get());
+ m_plugins->loadPlugins();
// instance
- if (auto r=setupInstanceLoop(*currentInstance, *pluginContainer)) {
+ if (auto r=setupInstanceLoop(*m_instance, *m_plugins)) {
return *r;
}
- if (currentInstance->isPortable()) {
+ if (m_instance->isPortable()) {
log::debug("this is a portable instance");
}
tt.start("MOApplication::doOneRun() OrganizerCore setup");
- sanity::checkPaths(*currentInstance->gamePlugin(), settings);
+ sanity::checkPaths(*m_instance->gamePlugin(), *m_settings);
// setting up organizer core
- organizer.setManagedGame(currentInstance->gamePlugin());
- organizer.createDefaultProfile();
+ m_core->setManagedGame(m_instance->gamePlugin());
+ m_core->createDefaultProfile();
log::info(
"using game plugin '{}' ('{}', variant {}, steam id '{}') at {}",
- currentInstance->gamePlugin()->gameName(),
- currentInstance->gamePlugin()->gameShortName(),
- (settings.game().edition().value_or("").isEmpty() ?
- "(none)" : *settings.game().edition()),
- currentInstance->gamePlugin()->steamAPPId(),
- currentInstance->gamePlugin()->gameDirectory().absolutePath());
+ m_instance->gamePlugin()->gameName(),
+ m_instance->gamePlugin()->gameShortName(),
+ (m_settings->game().edition().value_or("").isEmpty() ?
+ "(none)" : *m_settings->game().edition()),
+ m_instance->gamePlugin()->steamAPPId(),
+ m_instance->gamePlugin()->gameDirectory().absolutePath());
CategoryFactory::instance().loadCategories();
- organizer.updateExecutablesList();
- organizer.updateModInfoFromDisc();
- organizer.setCurrentProfile(currentInstance->profileName());
+ m_core->updateExecutablesList();
+ m_core->updateModInfoFromDisc();
+ m_core->setCurrentProfile(m_instance->profileName());
+
+ return 0;
+}
+int MOApplication::run(MOMultiProcess& multiProcess)
+{
// checking command line
- tt.start("MOApplication::doOneRun() command line");
- if (auto r=m_cl.setupCore(organizer)) {
- return *r;
- }
+ TimeThis tt("MOApplication::run()");
// show splash
tt.start("MOApplication::doOneRun() splash");
- MOSplash splash(
- settings, currentInstance->directory(), currentInstance->gamePlugin());
+ MOSplash splash(*m_settings, m_instance->directory(), m_instance->gamePlugin());
tt.start("MOApplication::doOneRun() finishing");
// start an api check
QString apiKey;
if (GlobalSettings::nexusApiKey(apiKey)) {
- ni.getAccessManager()->apiCheck(apiKey);
+ m_nexus->getAccessManager()->apiCheck(apiKey);
}
// tutorials
@@ -367,12 +331,12 @@ int MOApplication::doOneRun(MOMultiProcess& multiProcess) TutorialManager::init(
qApp->applicationDirPath() + "/"
+ QString::fromStdWString(AppConfig::tutorialsPath()) + "/",
- &organizer);
+ m_core.get());
// styling
- if (!setStyleFile(settings.interface().styleName().value_or(""))) {
+ if (!setStyleFile(m_settings->interface().styleName().value_or(""))) {
// disable invalid stylesheet
- settings.interface().setStyleName("");
+ m_settings->interface().setStyleName("");
}
@@ -380,16 +344,16 @@ int MOApplication::doOneRun(MOMultiProcess& multiProcess) {
tt.start("MOApplication::doOneRun() MainWindow setup");
- MainWindow mainWindow(settings, organizer, *pluginContainer);
+ MainWindow mainWindow(*m_settings, *m_core, *m_plugins);
// the nexus interface can show dialogs, make sure they're parented to the
// main window
- ni.getAccessManager()->setTopLevelWidget(&mainWindow);
+ m_nexus->getAccessManager()->setTopLevelWidget(&mainWindow);
QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), this,
SLOT(setStyleFile(QString)));
- QObject::connect(&multiProcess, SIGNAL(messageSent(QString)), &organizer,
+ QObject::connect(&multiProcess, SIGNAL(messageSent(QString)), m_core.get(),
SLOT(externalMessage(QString)));
@@ -404,16 +368,16 @@ int MOApplication::doOneRun(MOMultiProcess& multiProcess) mainWindow.close();
// main window is about to be destroyed
- ni.getAccessManager()->setTopLevelWidget(nullptr);
+ m_nexus->getAccessManager()->setTopLevelWidget(nullptr);
}
// reset geometry if the flag was set from the settings dialog
- settings.geometry().resetIfNeeded();
+ m_settings->geometry().resetIfNeeded();
return res;
}
-std::optional<Instance> MOApplication::getCurrentInstance()
+std::unique_ptr<Instance> MOApplication::getCurrentInstance()
{
auto& m = InstanceManager::singleton();
auto currentInstance = m.currentInstance();
@@ -422,8 +386,6 @@ std::optional<Instance> MOApplication::getCurrentInstance() {
// clear any overrides that might have been given on the command line
m.clearOverrides();
- m_cl.clear();
-
currentInstance = selectInstance();
}
else
@@ -433,7 +395,6 @@ std::optional<Instance> MOApplication::getCurrentInstance() // clear any overrides that might have been given on the command line
m.clearOverrides();
- m_cl.clear();
if (m.hasAnyInstances()) {
MOShared::criticalOnTop(QObject::tr(
@@ -496,31 +457,34 @@ void MOApplication::resetForRestart() // the previous instance gets deleted
log::getDefault().setFile({});
- // don't reprocess command line
- m_cl.clear();
-
// clear instance and profile overrides
InstanceManager::singleton().clearOverrides();
+
+ m_core = {};
+ m_plugins = {};
+ m_nexus = {};
+ m_settings = {};
+ m_instance = {};
}
bool MOApplication::setStyleFile(const QString& styleName)
{
// remove all files from watch
- QStringList currentWatch = m_StyleWatcher.files();
+ QStringList currentWatch = m_styleWatcher.files();
if (currentWatch.count() != 0) {
- m_StyleWatcher.removePaths(currentWatch);
+ m_styleWatcher.removePaths(currentWatch);
}
// set new stylesheet or clear it
if (styleName.length() != 0) {
QString styleSheetName = applicationDirPath() + "/" + MOBase::ToQString(AppConfig::stylesheetsPath()) + "/" + styleName;
if (QFile::exists(styleSheetName)) {
- m_StyleWatcher.addPath(styleSheetName);
+ m_styleWatcher.addPath(styleSheetName);
updateStyle(styleSheetName);
} else {
updateStyle(styleName);
}
} else {
- setStyle(new ProxyStyle(QStyleFactory::create(m_DefaultStyle)));
+ setStyle(new ProxyStyle(QStyleFactory::create(m_defaultStyle)));
setStyleSheet("");
}
return true;
@@ -551,7 +515,7 @@ void MOApplication::updateStyle(const QString& fileName) setStyleSheet("");
setStyle(new ProxyStyle(QStyleFactory::create(fileName)));
} else {
- setStyle(new ProxyStyle(QStyleFactory::create(m_DefaultStyle)));
+ setStyle(new ProxyStyle(QStyleFactory::create(m_defaultStyle)));
if (QFile::exists(fileName)) {
setStyleSheet(QString("file:///%1").arg(fileName));
} else {
diff --git a/src/moapplication.h b/src/moapplication.h index 91b8023a..7e427ca8 100644 --- a/src/moapplication.h +++ b/src/moapplication.h @@ -27,20 +27,24 @@ class Settings; class MOMultiProcess;
class Instance;
class PluginContainer;
+class OrganizerCore;
+class NexusInterface;
namespace MOBase { class IPluginGame; }
-namespace cl { class CommandLine; }
+namespace env { class ModuleNotification; }
class MOApplication : public QApplication
{
Q_OBJECT
public:
- MOApplication(cl::CommandLine& cl, int& argc, char** argv);
+ MOApplication(int& argc, char** argv);
- // sets up everything, creates the main window and runs it
- //
+ int setup(MOMultiProcess& multiProcess);
int run(MOMultiProcess& multiProcess);
+ void resetForRestart();
+
+ OrganizerCore& core();
virtual bool notify(QObject* receiver, QEvent* event);
@@ -51,16 +55,21 @@ private slots: void updateStyle(const QString& fileName);
private:
- QFileSystemWatcher m_StyleWatcher;
- QString m_DefaultStyle;
- cl::CommandLine& m_cl;
+ QFileSystemWatcher m_styleWatcher;
+ QString m_defaultStyle;
+ std::unique_ptr<env::ModuleNotification> m_modules;
+
+ std::unique_ptr<Instance> m_instance;
+ std::unique_ptr<Settings> m_settings;
+ std::unique_ptr<NexusInterface> m_nexus;
+ std::unique_ptr<PluginContainer> m_plugins;
+ std::unique_ptr<OrganizerCore> m_core;
int doOneRun(MOMultiProcess& multiProcess);
- std::optional<Instance> getCurrentInstance();
+ std::unique_ptr<Instance> getCurrentInstance();
std::optional<int> setupInstanceLoop(Instance& currentInstance, PluginContainer& pc);
void purgeOldFiles();
- void resetForRestart();
};
|
