From cc1de6a64991a942fdbbb6cdfe24ea1ee268fffb Mon Sep 17 00:00:00 2001 From: Jan Dalheimer Date: Fri, 7 Mar 2014 15:46:56 +0100 Subject: [PATCH 1/3] Fix another GroupView bug --- gui/groupview/GroupView.cpp | 12 ++++++++++++ gui/groupview/GroupView.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/gui/groupview/GroupView.cpp b/gui/groupview/GroupView.cpp index 5f3e3dec4..b650efee8 100644 --- a/gui/groupview/GroupView.cpp +++ b/gui/groupview/GroupView.cpp @@ -45,6 +45,12 @@ GroupView::~GroupView() m_groups.clear(); } +void GroupView::setModel(QAbstractItemModel *model) +{ + QAbstractItemView::setModel(model); + connect(model, &QAbstractItemModel::modelReset, this, &GroupView::modelReset); +} + void GroupView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles) { @@ -133,6 +139,12 @@ void GroupView::updateGeometries() viewport()->update(); } +void GroupView::modelReset() +{ + scheduleDelayedItemsLayout(); + executeDelayedItemsLayout(); +} + bool GroupView::isIndexHidden(const QModelIndex &index) const { Group *cat = category(index); diff --git a/gui/groupview/GroupView.h b/gui/groupview/GroupView.h index e8f9107cb..b3ab53578 100644 --- a/gui/groupview/GroupView.h +++ b/gui/groupview/GroupView.h @@ -24,6 +24,8 @@ public: GroupView(QWidget *parent = 0); ~GroupView(); + void setModel(QAbstractItemModel *model) override; + /// return geometry rectangle occupied by the specified model item QRect geometryRect(const QModelIndex &index) const; /// return visual rectangle occupied by the specified model item @@ -69,6 +71,7 @@ slots: virtual void rowsInserted(const QModelIndex &parent, int start, int end) override; virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override; virtual void updateGeometries() override; + void modelReset(); protected: virtual bool isIndexHidden(const QModelIndex &index) const override; From 44f21406e91c68b230d38441b950eb7c3d6a8ec5 Mon Sep 17 00:00:00 2001 From: Jan Dalheimer Date: Sun, 9 Mar 2014 08:18:50 +0100 Subject: [PATCH 2/3] Some pre/post related stuff Reload the onesix version config after the commands (addresses https://www.pivotaltracker.com/story/show/60360652) Add a few more variables and also substitute them in the command (fixes https://www.pivotaltracker.com/story/show/66994828) --- logic/BaseInstance.cpp | 6 ++ logic/BaseInstance.h | 2 + logic/MinecraftProcess.cpp | 200 +++++++++++++++++++++++-------------- logic/MinecraftProcess.h | 7 ++ logic/OneSixInstance.cpp | 5 + logic/OneSixInstance.h | 2 + 6 files changed, 149 insertions(+), 73 deletions(-) diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index d78f1ea01..aea91ef2f 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -169,6 +169,12 @@ bool BaseInstance::canLaunch() const return !(flags() & VersionBrokenFlag); } +bool BaseInstance::reload() +{ + // TODO reload the instance settings + return true; +} + QString BaseInstance::baseJar() const { I_D(BaseInstance); diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index 27f939bcf..195fd3393 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -190,6 +190,8 @@ public: bool canLaunch() const; + virtual bool reload(); + signals: /*! * \brief Signal emitted when properties relevant to the instance view change diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp index 89cd71ed3..1001cee58 100644 --- a/logic/MinecraftProcess.cpp +++ b/logic/MinecraftProcess.cpp @@ -49,9 +49,11 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst) #endif // export some infos - env.insert("INST_NAME", inst->name()); - env.insert("INST_ID", inst->id()); - env.insert("INST_DIR", QDir(inst->instanceRoot()).absolutePath()); + auto variables = getVariables(); + for (auto it = variables.begin(); it != variables.end(); ++it) + { + env.insert(it.key(), it.value()); + } this->setProcessEnvironment(env); m_prepostlaunchprocess.setProcessEnvironment(env); @@ -63,10 +65,10 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst) // Log prepost launch command output (can be disabled.) if (m_instance->settings().get("LogPrePostOutput").toBool()) { - connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardError, - this, &MinecraftProcess::on_prepost_stdErr); - connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardOutput, - this, &MinecraftProcess::on_prepost_stdOut); + connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardError, this, + &MinecraftProcess::on_prepost_stdErr); + connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardOutput, this, + &MinecraftProcess::on_prepost_stdOut); } } @@ -79,10 +81,10 @@ void MinecraftProcess::setWorkdir(QString path) QString MinecraftProcess::censorPrivateInfo(QString in) { - if(!m_session) + if (!m_session) return in; - if(m_session->session != "-") + if (m_session->session != "-") in.replace(m_session->session, ""); in.replace(m_session->access_token, ""); in.replace(m_session->client_token, ""); @@ -113,7 +115,7 @@ MessageLevel::Enum MinecraftProcess::guessLevel(const QString &line, MessageLeve level = MessageLevel::Fatal; if (line.contains("[DEBUG]")) level = MessageLevel::Debug; - if(line.contains("overwriting existing")) + if (line.contains("overwriting existing")) level = MessageLevel::Fatal; return level; } @@ -139,17 +141,15 @@ MessageLevel::Enum MinecraftProcess::getLevel(const QString &levelName) return MessageLevel::Message; } -void MinecraftProcess::logOutput(const QStringList &lines, - MessageLevel::Enum defaultLevel, +void MinecraftProcess::logOutput(const QStringList &lines, MessageLevel::Enum defaultLevel, bool guessLevel, bool censor) { for (int i = 0; i < lines.size(); ++i) logOutput(lines[i], defaultLevel, guessLevel, censor); } -void MinecraftProcess::logOutput(QString line, - MessageLevel::Enum defaultLevel, - bool guessLevel, bool censor) +void MinecraftProcess::logOutput(QString line, MessageLevel::Enum defaultLevel, bool guessLevel, + bool censor) { MessageLevel::Enum level = defaultLevel; @@ -251,33 +251,7 @@ void MinecraftProcess::finish(int code, ExitStatus status) m_prepostlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(code)); // run post-exit - QString postlaunch_cmd = m_instance->settings().get("PostExitCommand").toString(); - if (!postlaunch_cmd.isEmpty()) - { - emit log(tr("Running Post-Launch command: %1").arg(postlaunch_cmd)); - m_prepostlaunchprocess.start(postlaunch_cmd); - m_prepostlaunchprocess.waitForFinished(); - // Flush console window - if (!m_err_leftover.isEmpty()) - { - logOutput(m_err_leftover, MessageLevel::PrePost); - m_err_leftover.clear(); - } - if (!m_out_leftover.isEmpty()) - { - logOutput(m_out_leftover, MessageLevel::PrePost); - m_out_leftover.clear(); - } - if (m_prepostlaunchprocess.exitStatus() != NormalExit) - { - emit log(tr("Post-Launch command failed with code %1.\n\n").arg(m_prepostlaunchprocess.exitCode()), - MessageLevel::Error); - emit postlaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(), - m_prepostlaunchprocess.exitStatus()); - } - else - emit log(tr("Post-Launch command ran successfully.\n\n")); - } + postLaunch(); m_instance->cleanupAfterRun(); emit ended(m_instance, code, status); } @@ -288,14 +262,12 @@ void MinecraftProcess::killMinecraft() kill(); } -void MinecraftProcess::arm() +bool MinecraftProcess::preLaunch() { - emit log("MultiMC version: " + MMC->version().toString() + "\n\n"); - emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n"); - QString prelaunch_cmd = m_instance->settings().get("PreLaunchCommand").toString(); if (!prelaunch_cmd.isEmpty()) { + prelaunch_cmd = substituteVariables(prelaunch_cmd); // Launch emit log(tr("Running Pre-Launch command: %1").arg(prelaunch_cmd)); m_prepostlaunchprocess.start(prelaunch_cmd); @@ -315,45 +287,127 @@ void MinecraftProcess::arm() // Process return values if (m_prepostlaunchprocess.exitStatus() != NormalExit) { - emit log(tr("Pre-Launch command failed with code %1.\n\n").arg(m_prepostlaunchprocess.exitCode()), + emit log(tr("Pre-Launch command failed with code %1.\n\n") + .arg(m_prepostlaunchprocess.exitCode()), MessageLevel::Fatal); m_instance->cleanupAfterRun(); emit prelaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(), m_prepostlaunchprocess.exitStatus()); - return; + return false; } else emit log(tr("Pre-Launch command ran successfully.\n\n")); + + return m_instance->reload(); + } + return true; +} +bool MinecraftProcess::postLaunch() +{ + QString postlaunch_cmd = m_instance->settings().get("PostExitCommand").toString(); + if (!postlaunch_cmd.isEmpty()) + { + postlaunch_cmd = substituteVariables(postlaunch_cmd); + emit log(tr("Running Post-Launch command: %1").arg(postlaunch_cmd)); + m_prepostlaunchprocess.start(postlaunch_cmd); + m_prepostlaunchprocess.waitForFinished(); + // Flush console window + if (!m_err_leftover.isEmpty()) + { + logOutput(m_err_leftover, MessageLevel::PrePost); + m_err_leftover.clear(); + } + if (!m_out_leftover.isEmpty()) + { + logOutput(m_out_leftover, MessageLevel::PrePost); + m_out_leftover.clear(); + } + if (m_prepostlaunchprocess.exitStatus() != NormalExit) + { + emit log(tr("Post-Launch command failed with code %1.\n\n") + .arg(m_prepostlaunchprocess.exitCode()), + MessageLevel::Error); + emit postlaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(), + m_prepostlaunchprocess.exitStatus()); + } + else + emit log(tr("Post-Launch command ran successfully.\n\n")); + + return m_instance->reload(); + } + return true; +} + +QMap MinecraftProcess::getVariables() const +{ + QMap out; + out.insert("INST_NAME", m_instance->name()); + out.insert("INST_ID", m_instance->id()); + out.insert("INST_DIR", QDir(m_instance->instanceRoot()).absolutePath()); + out.insert("INST_MC_DIR", QDir(m_instance->minecraftRoot()).absolutePath()); + out.insert("INST_JAVA", m_instance->settings().get("JavaPath").toString()); + out.insert("INST_JAVA_ARGS", javaArguments().join(' ')); + return out; +} +QString MinecraftProcess::substituteVariables(const QString &cmd) const +{ + QString out = cmd; + auto variables = getVariables(); + for (auto it = variables.begin(); it != variables.end(); ++it) + { + out.replace("$" + it.key(), it.value()); + } + auto env = QProcessEnvironment::systemEnvironment(); + for (auto var : env.keys()) + { + out.replace("$" + var, env.value(var)); + } + return out; +} + +QStringList MinecraftProcess::javaArguments() const +{ + QStringList args; + + // custom args go first. we want to override them if we have our own here. + args.append(m_instance->extraArguments()); + +// OSX dock icon and name +#ifdef OSX + args << "-Xdock:icon=icon.png"; + args << QString("-Xdock:name=\"%1\"").arg(m_instance->windowTitle()); +#endif + +// HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767 +#ifdef Q_OS_WIN32 + args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_" + "minecraft.exe.heapdump"); +#endif + + args << QString("-Xms%1m").arg(m_instance->settings().get("MinMemAlloc").toInt()); + args << QString("-Xmx%1m").arg(m_instance->settings().get("MaxMemAlloc").toInt()); + args << QString("-XX:PermSize=%1m").arg(m_instance->settings().get("PermGen").toInt()); + if (!m_nativeFolder.isEmpty()) + args << QString("-Djava.library.path=%1").arg(m_nativeFolder); + args << "-jar" << PathCombine(MMC->bin(), "jars", "NewLaunch.jar"); + + return args; +} + +void MinecraftProcess::arm() +{ + emit log("MultiMC version: " + MMC->version().toString() + "\n\n"); + emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n"); + + if (!preLaunch()) + { + return; } m_instance->setLastLaunch(); auto &settings = m_instance->settings(); - //////////// java arguments //////////// - QStringList args; - { - // custom args go first. we want to override them if we have our own here. - args.append(m_instance->extraArguments()); - - // OSX dock icon and name - #ifdef OSX - args << "-Xdock:icon=icon.png"; - args << QString("-Xdock:name=\"%1\"").arg(m_instance->windowTitle()); - #endif - - // HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767 - #ifdef Q_OS_WIN32 - args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_" - "minecraft.exe.heapdump"); - #endif - - args << QString("-Xms%1m").arg(settings.get("MinMemAlloc").toInt()); - args << QString("-Xmx%1m").arg(settings.get("MaxMemAlloc").toInt()); - args << QString("-XX:PermSize=%1m").arg(settings.get("PermGen").toInt()); - if(!m_nativeFolder.isEmpty()) - args << QString("-Djava.library.path=%1").arg(m_nativeFolder); - args << "-jar" << PathCombine(MMC->bin(), "jars", "NewLaunch.jar"); - } + QStringList args = javaArguments(); QString JavaPath = m_instance->settings().get("JavaPath").toString(); emit log("Java path is:\n" + JavaPath + "\n\n"); diff --git a/logic/MinecraftProcess.h b/logic/MinecraftProcess.h index 56340962d..d91dad56d 100644 --- a/logic/MinecraftProcess.h +++ b/logic/MinecraftProcess.h @@ -131,6 +131,13 @@ protected: QString launchScript; QString m_nativeFolder; + bool preLaunch(); + bool postLaunch(); + QMap getVariables() const; + QString substituteVariables(const QString &cmd) const; + + QStringList javaArguments() const; + protected slots: void finish(int, QProcess::ExitStatus status); diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 10411c560..4f8fef5b5 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -413,6 +413,11 @@ bool OneSixInstance::providesVersionFile() const return false; } +bool OneSixInstance::reload() +{ + return BaseInstance::reload() && reloadVersion(); +} + QString OneSixInstance::loaderModsDir() const { return PathCombine(minecraftRoot(), "mods"); diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h index 06fd9de30..fafb34a0a 100644 --- a/logic/OneSixInstance.h +++ b/logic/OneSixInstance.h @@ -75,6 +75,8 @@ public: virtual QStringList externalPatches() const; virtual bool providesVersionFile() const; + bool reload() override; + signals: void versionReloaded(); From f1dc4568020d222803d54fdcece324a14c9266c7 Mon Sep 17 00:00:00 2001 From: Jan Dalheimer Date: Sun, 9 Mar 2014 08:43:08 +0100 Subject: [PATCH 3/3] Also reload the instance cfg While this should work, there don't seem to be any places where the signals are listened for, so changes probably will only be available when calling Setting::get TODO: Fix that ^ --- depends/settings/inisettingsobject.cpp | 5 +++++ depends/settings/inisettingsobject.h | 2 ++ depends/settings/settingsobject.cpp | 9 +++++++++ depends/settings/settingsobject.h | 6 ++++++ logic/BaseInstance.cpp | 3 +-- 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/depends/settings/inisettingsobject.cpp b/depends/settings/inisettingsobject.cpp index 5e52a56f3..2cee8e3c1 100644 --- a/depends/settings/inisettingsobject.cpp +++ b/depends/settings/inisettingsobject.cpp @@ -28,6 +28,11 @@ void INISettingsObject::setFilePath(const QString &filePath) m_filePath = filePath; } +bool INISettingsObject::reload() +{ + return m_ini.loadFile(m_filePath) && SettingsObject::reload(); +} + void INISettingsObject::changeSetting(const Setting &setting, QVariant value) { if (contains(setting.id())) diff --git a/depends/settings/inisettingsobject.h b/depends/settings/inisettingsobject.h index 8badc0c68..123708960 100644 --- a/depends/settings/inisettingsobject.h +++ b/depends/settings/inisettingsobject.h @@ -47,6 +47,8 @@ public: */ virtual void setFilePath(const QString &filePath); + bool reload() override; + protected slots: virtual void changeSetting(const Setting &setting, QVariant value); diff --git a/depends/settings/settingsobject.cpp b/depends/settings/settingsobject.cpp index 43fc989a1..0e3030df7 100644 --- a/depends/settings/settingsobject.cpp +++ b/depends/settings/settingsobject.cpp @@ -126,6 +126,15 @@ bool SettingsObject::contains(const QString &id) return m_settings.contains(id); } +bool SettingsObject::reload() +{ + for (auto setting : m_settings.values()) + { + setting->set(setting->get()); + } + return true; +} + void SettingsObject::connectSignals(const Setting &setting) { connect(&setting, SIGNAL(settingChanged(const Setting &, QVariant)), diff --git a/depends/settings/settingsobject.h b/depends/settings/settingsobject.h index 27746f2dc..b1b26b094 100644 --- a/depends/settings/settingsobject.h +++ b/depends/settings/settingsobject.h @@ -113,6 +113,12 @@ public: */ bool contains(const QString &id); + /*! + * \brief Reloads the settings and emit signals for changed settings + * \return True if reloading was successful + */ + virtual bool reload(); + signals: /*! * \brief Signal emitted when one of this SettingsObject object's settings changes. diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index aea91ef2f..c565ab597 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -171,8 +171,7 @@ bool BaseInstance::canLaunch() const bool BaseInstance::reload() { - // TODO reload the instance settings - return true; + return settings().reload(); } QString BaseInstance::baseJar() const