diff options
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();
};
|
