aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2016-08-06 15:39:29 +0200
committerPetr Mrázek <peterix@gmail.com>2016-08-07 11:48:15 +0200
commitbc6d1b5304f715ad0d8be27efd6630f820572da4 (patch)
tree6f42bdd351664b6f828247b4860ee3ad723b0971
parentc44d41ee9b132d4f757658bd62d4b115b7887fe3 (diff)
downloadPrismLauncher-bc6d1b5304f715ad0d8be27efd6630f820572da4.tar.gz
PrismLauncher-bc6d1b5304f715ad0d8be27efd6630f820572da4.tar.bz2
PrismLauncher-bc6d1b5304f715ad0d8be27efd6630f820572da4.zip
GH-338, GH-513, GH-700 Unify edit instance with console window
* The resulting instance window can be closed at any point. * Main window is kept open and running instances are marked with a badge. * Multiple instances can now run from the same MultiMC - it's even more **multi** now. * MultiMC can be entirely closed, keeping Minecraft(s) running.
-rw-r--r--api/logic/BaseInstance.cpp16
-rw-r--r--api/logic/BaseInstance.h8
-rw-r--r--api/logic/minecraft/MinecraftInstance.cpp4
-rw-r--r--application/CMakeLists.txt5
-rw-r--r--application/ConsoleWindow.cpp260
-rw-r--r--application/InstancePageProvider.h2
-rw-r--r--application/InstanceWindow.cpp226
-rw-r--r--application/InstanceWindow.h (renamed from application/ConsoleWindow.h)32
-rw-r--r--application/LaunchInteraction.cpp33
-rw-r--r--application/LaunchInteraction.h5
-rw-r--r--application/MainWindow.cpp66
-rw-r--r--application/MainWindow.h8
-rw-r--r--application/SettingsUI.cpp9
-rw-r--r--application/SettingsUI.h2
-rw-r--r--application/groupview/InstanceDelegate.cpp4
-rw-r--r--application/pages/LogPage.cpp75
-rw-r--r--application/pages/LogPage.h5
-rw-r--r--application/resources/instances/instances.qrc1
-rw-r--r--application/resources/instances/status-running.pngbin0 -> 1059 bytes
-rw-r--r--application/resources/multimc/16x16/status-running.pngbin0 -> 675 bytes
-rw-r--r--application/resources/multimc/22x22/status-running.pngbin0 -> 957 bytes
-rw-r--r--application/resources/multimc/24x24/status-running.pngbin0 -> 1059 bytes
-rw-r--r--application/resources/multimc/32x32/status-running.pngbin0 -> 1425 bytes
-rw-r--r--application/resources/multimc/48x48/status-running.pngbin0 -> 2288 bytes
-rw-r--r--application/resources/multimc/64x64/status-running.pngbin0 -> 3178 bytes
-rw-r--r--application/resources/multimc/multimc.qrc9
-rw-r--r--application/resources/multimc/scalable/status-running.svg187
-rw-r--r--application/widgets/PageContainer.cpp22
-rw-r--r--application/widgets/PageContainer.h2
29 files changed, 630 insertions, 351 deletions
diff --git a/api/logic/BaseInstance.cpp b/api/logic/BaseInstance.cpp
index ce55d5e4..9dee2c38 100644
--- a/api/logic/BaseInstance.cpp
+++ b/api/logic/BaseInstance.cpp
@@ -92,11 +92,14 @@ bool BaseInstance::isRunning() const
void BaseInstance::setRunning(bool running)
{
- if(running && !m_isRunning)
+ if(running == m_isRunning)
+ return;
+
+ if(running)
{
m_timeStarted = QDateTime::currentDateTime();
}
- else if(!running && m_isRunning)
+ else
{
qint64 current = settings()->get("totalTimePlayed").toLongLong();
QDateTime timeEnded = QDateTime::currentDateTime();
@@ -104,6 +107,8 @@ void BaseInstance::setRunning(bool running)
emit propertiesChanged(this);
}
m_isRunning = running;
+
+ emit runningStatusChanged(running);
}
int64_t BaseInstance::totalTimePlayed() const
@@ -179,7 +184,7 @@ void BaseInstance::unsetFlag(const BaseInstance::InstanceFlag flag)
bool BaseInstance::canLaunch() const
{
- return !(flags() & VersionBrokenFlag);
+ return (!(flags() & VersionBrokenFlag)) && (!isRunning());
}
bool BaseInstance::reload()
@@ -268,3 +273,8 @@ QStringList BaseInstance::extraArguments() const
{
return Commandline::splitArgs(settings()->get("JvmArgs").toString());
}
+
+std::shared_ptr<LaunchTask> BaseInstance::getLaunchTask()
+{
+ return m_launchProcess;
+}
diff --git a/api/logic/BaseInstance.h b/api/logic/BaseInstance.h
index f0fb6096..9a6976cb 100644
--- a/api/logic/BaseInstance.h
+++ b/api/logic/BaseInstance.h
@@ -157,6 +157,9 @@ public:
/// returns a valid launcher (task container)
virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) = 0;
+ /// returns the current launch task (if any)
+ std::shared_ptr<LaunchTask> getLaunchTask();
+
/*!
* Returns a task that should be done right before launch
* This task should do any extra preparations needed
@@ -231,6 +234,10 @@ signals:
void flagsChanged();
+ void launchTaskChanged(std::shared_ptr<LaunchTask>);
+
+ void runningStatusChanged(bool running);
+
protected slots:
void iconUpdated(QString key);
@@ -240,6 +247,7 @@ protected:
SettingsObjectPtr m_settings;
InstanceFlags m_flags;
bool m_isRunning = false;
+ std::shared_ptr<LaunchTask> m_launchProcess;
QDateTime m_timeStarted;
};
diff --git a/api/logic/minecraft/MinecraftInstance.cpp b/api/logic/minecraft/MinecraftInstance.cpp
index f706c16d..b64d9bd2 100644
--- a/api/logic/minecraft/MinecraftInstance.cpp
+++ b/api/logic/minecraft/MinecraftInstance.cpp
@@ -465,7 +465,9 @@ std::shared_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr s
{
process->setCensorFilter(createCensorFilterFromSession(session));
}
- return process;
+ m_launchProcess = process;
+ emit launchTaskChanged(m_launchProcess);
+ return m_launchProcess;
}
QString MinecraftInstance::launchMethod()
diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt
index 9d71f977..46c496e2 100644
--- a/application/CMakeLists.txt
+++ b/application/CMakeLists.txt
@@ -103,12 +103,11 @@ SET(MULTIMC_SOURCES
# GUI - windows
MainWindow.h
MainWindow.cpp
- ConsoleWindow.h
- ConsoleWindow.cpp
+ InstanceWindow.h
+ InstanceWindow.cpp
# GUI - settings-specific wrappers for paged dialog
SettingsUI.h
- SettingsUI.cpp
# Processes
LaunchInteraction.h
diff --git a/application/ConsoleWindow.cpp b/application/ConsoleWindow.cpp
deleted file mode 100644
index e620d700..00000000
--- a/application/ConsoleWindow.cpp
+++ /dev/null
@@ -1,260 +0,0 @@
-/* Copyright 2013-2015 MultiMC Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "ConsoleWindow.h"
-#include "MultiMC.h"
-
-#include <QScrollBar>
-#include <QMessageBox>
-#include <QSystemTrayIcon>
-#include <QHBoxLayout>
-#include <QPushButton>
-#include <qlayoutitem.h>
-#include <QCloseEvent>
-
-#include <dialogs/CustomMessageBox.h>
-#include <dialogs/ProgressDialog.h>
-#include "widgets/PageContainer.h"
-#include "pages/LogPage.h"
-#include "InstancePageProvider.h"
-
-#include "icons/IconList.h"
-
-class LogPageProvider : public BasePageProvider
-{
-public:
- LogPageProvider(BasePageProviderPtr parent, BasePage * log_page)
- {
- m_parent = parent;
- m_log_page = log_page;
- }
- virtual QString dialogTitle() {return "Fake";};
- virtual QList<BasePage *> getPages()
- {
- auto pages = m_parent->getPages();
- pages.prepend(m_log_page);
- return pages;
- }
-private:
- BasePageProviderPtr m_parent;
- BasePage * m_log_page;
-};
-
-ConsoleWindow::ConsoleWindow(std::shared_ptr<LaunchTask> proc, QWidget *parent)
- : QMainWindow(parent), m_proc(proc)
-{
- setAttribute(Qt::WA_DeleteOnClose);
-
- auto instance = m_proc->instance();
- auto icon = MMC->icons()->getIcon(instance->iconKey());
- QString windowTitle = tr("Console window for ") + instance->name();
-
- // Set window properties
- {
- setWindowIcon(icon);
- setWindowTitle(windowTitle);
- }
-
- // Add page container
- {
- auto mainLayout = new QVBoxLayout;
- auto provider = std::make_shared<InstancePageProvider>(m_proc->instance());
- auto baseprovider = std::dynamic_pointer_cast<BasePageProvider>(provider);
- auto proxy_provider = std::make_shared<LogPageProvider>(baseprovider, new LogPage(m_proc));
- m_container = new PageContainer(proxy_provider, "console", this);
- mainLayout->addWidget(m_container);
- mainLayout->setSpacing(0);
- mainLayout->setContentsMargins(0,0,0,0);
- setLayout(mainLayout);
- setCentralWidget(m_container);
- }
-
- // Add custom buttons to the page container layout.
- {
- auto horizontalLayout = new QHBoxLayout();
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
- horizontalLayout->setContentsMargins(6, -1, 6, -1);
-
- auto btnHelp = new QPushButton();
- btnHelp->setText(tr("Help"));
- horizontalLayout->addWidget(btnHelp);
- connect(btnHelp, SIGNAL(clicked(bool)), m_container, SLOT(help()));
-
- auto spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
- horizontalLayout->addSpacerItem(spacer);
-
- m_killButton = new QPushButton();
- m_killButton->setText(tr("Kill Minecraft"));
- horizontalLayout->addWidget(m_killButton);
- connect(m_killButton, SIGNAL(clicked(bool)), SLOT(on_btnKillMinecraft_clicked()));
-
- m_closeButton = new QPushButton();
- m_closeButton->setText(tr("Close"));
- horizontalLayout->addWidget(m_closeButton);
- connect(m_closeButton, SIGNAL(clicked(bool)), SLOT(on_closeButton_clicked()));
-
- m_container->addButtons(horizontalLayout);
- }
-
- // restore window state
- {
- auto base64State = MMC->settings()->get("ConsoleWindowState").toByteArray();
- restoreState(QByteArray::fromBase64(base64State));
- auto base64Geometry = MMC->settings()->get("ConsoleWindowGeometry").toByteArray();
- restoreGeometry(QByteArray::fromBase64(base64Geometry));
- }
-
- // Set up tray icon
- {
- m_trayIcon = new QSystemTrayIcon(icon, this);
- m_trayIcon->setToolTip(windowTitle);
-
- connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
- SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
- m_trayIcon->show();
- }
-
- // Set up signal connections
- connect(m_proc.get(), &LaunchTask::succeeded, this, &ConsoleWindow::onSucceeded);
- connect(m_proc.get(), &LaunchTask::failed, this, &ConsoleWindow::onFailed);
- connect(m_proc.get(), &LaunchTask::requestProgress, this, &ConsoleWindow::onProgressRequested);
-
- setMayClose(false);
-
- if (m_proc->instance()->settings()->get("ShowConsole").toBool())
- {
- show();
- }
-}
-
-void ConsoleWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
-{
- switch (reason)
- {
- case QSystemTrayIcon::Trigger:
- {
- toggleConsole();
- }
- default:
- return;
- }
-}
-
-void ConsoleWindow::on_closeButton_clicked()
-{
- close();
-}
-
-void ConsoleWindow::setMayClose(bool mayclose)
-{
- if(mayclose)
- m_closeButton->setText(tr("Close"));
- else
- m_closeButton->setText(tr("Hide"));
- m_mayclose = mayclose;
-}
-
-void ConsoleWindow::toggleConsole()
-{
- if (isVisible())
- {
- if(!isActiveWindow())
- {
- activateWindow();
- return;
- }
- hide();
- }
- else
- {
- show();
- }
-}
-
-void ConsoleWindow::closeEvent(QCloseEvent *event)
-{
- if (!m_mayclose)
- {
- toggleConsole();
- event->ignore();
- }
- else if(m_container->requestClose(event))
- {
- MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
- MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
-
- emit isClosing();
- m_trayIcon->hide();
- event->accept();
- }
-}
-
-void ConsoleWindow::on_btnKillMinecraft_clicked()
-{
- m_killButton->setEnabled(false);
- auto response = CustomMessageBox::selectable(
- this, tr("Kill Minecraft?"),
- tr("This can cause the instance to get corrupted and should only be used if Minecraft "
- "is frozen for some reason"),
- QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
- if (response == QMessageBox::Yes)
- m_proc->abort();
- else
- m_killButton->setEnabled(true);
-}
-
-void ConsoleWindow::onSucceeded()
-{
- m_killButton->setEnabled(false);
- setMayClose(true);
- if (m_proc->instance()->settings()->get("AutoCloseConsole").toBool() && m_container->requestClose(nullptr))
- {
- this->close();
- return;
- }
- if (!isVisible())
- {
- show();
- }
- // Raise Window
- if (MMC->settings()->get("RaiseConsole").toBool())
- {
- raise();
- activateWindow();
- }
-}
-
-void ConsoleWindow::onFailed(QString reason)
-{
- m_killButton->setEnabled(false);
- setMayClose(true);
- if (!isVisible())
- {
- show();
- }
-}
-
-void ConsoleWindow::onProgressRequested(Task* task)
-{
- ProgressDialog progDialog(this);
- m_proc->proceed();
- progDialog.execWithTask(task);
-}
-
-
-ConsoleWindow::~ConsoleWindow()
-{
-
-}
diff --git a/application/InstancePageProvider.h b/application/InstancePageProvider.h
index dfc2e4dd..1d6cc5d7 100644
--- a/application/InstancePageProvider.h
+++ b/application/InstancePageProvider.h
@@ -3,6 +3,7 @@
#include "minecraft/legacy/LegacyInstance.h"
#include <FileSystem.h>
#include "pages/BasePage.h"
+#include "pages/LogPage.h"
#include "pages/VersionPage.h"
#include "pages/ModFolderPage.h"
#include "pages/ResourcePackPage.h"
@@ -29,6 +30,7 @@ public:
virtual QList<BasePage *> getPages() override
{
QList<BasePage *> values;
+ values.append(new LogPage(inst));
std::shared_ptr<OneSixInstance> onesix = std::dynamic_pointer_cast<OneSixInstance>(inst);
if(onesix)
{
diff --git a/application/InstanceWindow.cpp b/application/InstanceWindow.cpp
new file mode 100644
index 00000000..dfc7b815
--- /dev/null
+++ b/application/InstanceWindow.cpp
@@ -0,0 +1,226 @@
+/* Copyright 2013-2015 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InstanceWindow.h"
+#include "MultiMC.h"
+
+#include <QScrollBar>
+#include <QMessageBox>
+#include <QHBoxLayout>
+#include <QPushButton>
+#include <qlayoutitem.h>
+#include <QCloseEvent>
+
+#include <dialogs/CustomMessageBox.h>
+#include <dialogs/ProgressDialog.h>
+#include "widgets/PageContainer.h"
+#include "InstancePageProvider.h"
+
+#include "icons/IconList.h"
+
+InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent)
+ : QMainWindow(parent), m_instance(instance)
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+
+ auto icon = MMC->icons()->getIcon(m_instance->iconKey());
+ QString windowTitle = tr("Console window for ") + m_instance->name();
+
+ // Set window properties
+ {
+ setWindowIcon(icon);
+ setWindowTitle(windowTitle);
+ }
+
+ // Add page container
+ {
+ auto mainLayout = new QVBoxLayout;
+ auto provider = std::make_shared<InstancePageProvider>(m_instance);
+ m_container = new PageContainer(provider, "console", this);
+ mainLayout->addWidget(m_container);
+ mainLayout->setSpacing(0);
+ mainLayout->setContentsMargins(0,0,0,0);
+ setLayout(mainLayout);
+ setCentralWidget(m_container);
+ }
+
+ // Add custom buttons to the page container layout.
+ {
+ auto horizontalLayout = new QHBoxLayout();
+ horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setContentsMargins(6, -1, 6, -1);
+
+ auto btnHelp = new QPushButton();
+ btnHelp->setText(tr("Help"));
+ horizontalLayout->addWidget(btnHelp);
+ connect(btnHelp, SIGNAL(clicked(bool)), m_container, SLOT(help()));
+
+ auto spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ horizontalLayout->addSpacerItem(spacer);
+
+ m_killButton = new QPushButton();
+ horizontalLayout->addWidget(m_killButton);
+ setKillButton(m_instance->isRunning());
+ connect(m_killButton, SIGNAL(clicked(bool)), SLOT(on_btnKillMinecraft_clicked()));
+
+ m_closeButton = new QPushButton();
+ m_closeButton->setText(tr("Close"));
+ horizontalLayout->addWidget(m_closeButton);
+ connect(m_closeButton, SIGNAL(clicked(bool)), SLOT(on_closeButton_clicked()));
+
+ m_container->addButtons(horizontalLayout);
+ }
+
+ // restore window state
+ {
+ auto base64State = MMC->settings()->get("ConsoleWindowState").toByteArray();
+ restoreState(QByteArray::fromBase64(base64State));
+ auto base64Geometry = MMC->settings()->get("ConsoleWindowGeometry").toByteArray();
+ restoreGeometry(QByteArray::fromBase64(base64Geometry));
+ }
+
+ // set up instance and launch process recognition
+ {
+ auto launchTask = m_instance->getLaunchTask();
+ on_InstanceLaunchTask_changed(launchTask);
+ connect(m_instance.get(), &BaseInstance::launchTaskChanged,
+ this, &InstanceWindow::on_InstanceLaunchTask_changed);
+ connect(m_instance.get(), &BaseInstance::runningStatusChanged,
+ this, &InstanceWindow::on_RunningState_changed);
+ }
+ show();
+}
+
+void InstanceWindow::setKillButton(bool kill)
+{
+ if(kill)
+ {
+ m_killButton->setText(tr("Kill"));
+ m_killButton->setToolTip(tr("Kill the running instance"));
+ }
+ else
+ {
+ m_killButton->setText(tr("Launch"));
+ m_killButton->setToolTip(tr("Launch the instance"));
+ }
+}
+
+void InstanceWindow::on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc)
+{
+ if(m_proc)
+ {
+ disconnect(m_proc.get(), &LaunchTask::succeeded, this, &InstanceWindow::onSucceeded);
+ disconnect(m_proc.get(), &LaunchTask::failed, this, &InstanceWindow::onFailed);
+ disconnect(m_proc.get(), &LaunchTask::requestProgress, this, &InstanceWindow::onProgressRequested);
+ }
+
+ m_proc = proc;
+
+ if(m_proc)
+ {
+ // Set up signal connections
+ connect(m_proc.get(), &LaunchTask::succeeded, this, &InstanceWindow::onSucceeded);
+ connect(m_proc.get(), &LaunchTask::failed, this, &InstanceWindow::onFailed);
+ connect(m_proc.get(), &LaunchTask::requestProgress, this, &InstanceWindow::onProgressRequested);
+ }
+}
+
+void InstanceWindow::on_RunningState_changed(bool running)
+{
+ setKillButton(running);
+ m_container->refresh();
+}
+
+void InstanceWindow::on_closeButton_clicked()
+{
+ close();
+}
+
+void InstanceWindow::closeEvent(QCloseEvent *event)
+{
+ MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
+ MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
+
+ if(m_container->requestClose(event))
+ {
+ emit isClosing();
+ event->accept();
+ }
+}
+
+void InstanceWindow::on_btnKillMinecraft_clicked()
+{
+ if(m_instance->isRunning())
+ {
+ auto response = CustomMessageBox::selectable(
+ this, tr("Kill Minecraft?"),
+ tr("This can cause the instance to get corrupted and should only be used if Minecraft "
+ "is frozen for some reason"),
+ QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
+ if (response == QMessageBox::Yes)
+ {
+ m_proc->abort();
+ }
+ }
+ else
+ {
+ m_launchController.reset(new LaunchController());
+ m_launchController->setInstance(m_instance);
+ m_launchController->setOnline(true);
+ m_launchController->setParentWidget(this);
+ m_launchController->start();
+ }
+}
+
+void InstanceWindow::onSucceeded()
+{
+ if (m_instance->settings()->get("AutoCloseConsole").toBool() && m_container->requestClose(nullptr))
+ {
+ this->close();
+ return;
+ }
+ // Raise Window
+ if (MMC->settings()->get("RaiseConsole").toBool())
+ {
+ show();
+ raise();
+ activateWindow();
+ }
+}
+
+void InstanceWindow::onFailed(QString reason)
+{
+}
+
+void InstanceWindow::onProgressRequested(Task* task)
+{
+ ProgressDialog progDialog(this);
+ m_proc->proceed();
+ progDialog.execWithTask(task);
+}
+
+QString InstanceWindow::instanceId()
+{
+ return m_instance->id();
+}
+
+bool InstanceWindow::selectPage(QString pageId)
+{
+ return m_container->selectPage(pageId);
+}
+
+InstanceWindow::~InstanceWindow()
+{
+}
diff --git a/application/ConsoleWindow.h b/application/InstanceWindow.h
index ac5a6fd1..7ffc4142 100644
--- a/application/ConsoleWindow.h
+++ b/application/InstanceWindow.h
@@ -16,25 +16,25 @@
#pragma once
#include <QMainWindow>
+#include "LaunchInteraction.h"
+#include <QObjectPtr.h>
#include <QSystemTrayIcon>
#include "launch/LaunchTask.h"
+#include "pages/BasePageContainer.h"
class QPushButton;
class PageContainer;
-class ConsoleWindow : public QMainWindow
+class InstanceWindow : public QMainWindow, public BasePageContainer
{
Q_OBJECT
public:
- explicit ConsoleWindow(std::shared_ptr<LaunchTask> proc, QWidget *parent = 0);
- virtual ~ConsoleWindow();
+ explicit InstanceWindow(InstancePtr proc, QWidget *parent = 0);
+ virtual ~InstanceWindow();
- /**
- * @brief specify if the window is allowed to close
- * @param mayclose
- * used to keep it alive while MC runs
- */
- void setMayClose(bool mayclose);
+ bool selectPage(QString pageId) override;
+
+ QString instanceId();
signals:
void isClosing();
@@ -48,18 +48,20 @@ slots:
void onFailed(QString reason);
void onProgressRequested(Task *task);
- // FIXME: add handlers for the other MinecraftLauncher signals (pre/post launch command
- // failures)
+ void on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc);
+ void on_RunningState_changed(bool running);
- void iconActivated(QSystemTrayIcon::ActivationReason);
- void toggleConsole();
protected:
- void closeEvent(QCloseEvent *);
+ void closeEvent(QCloseEvent *) override;
+
+private:
+ void setKillButton(bool kill);
private:
std::shared_ptr<LaunchTask> m_proc;
+ unique_qobject_ptr<LaunchController> m_launchController;
+ InstancePtr m_instance;
bool m_mayclose = true;
- QSystemTrayIcon *m_trayIcon = nullptr;
PageContainer *m_container = nullptr;
QPushButton *m_closeButton = nullptr;
QPushButton *m_killButton = nullptr;
diff --git a/application/LaunchInteraction.cpp b/application/LaunchInteraction.cpp
index 1caa054a..80a3368d 100644
--- a/application/LaunchInteraction.cpp
+++ b/application/LaunchInteraction.cpp
@@ -1,11 +1,12 @@
#include "LaunchInteraction.h"
+#include "MainWindow.h"
#include <minecraft/auth/MojangAccountList.h>
#include "MultiMC.h"
#include "dialogs/CustomMessageBox.h"
#include "dialogs/AccountSelectDialog.h"
#include "dialogs/ProgressDialog.h"
#include "dialogs/EditAccountDialog.h"
-#include "ConsoleWindow.h"
+#include "InstanceWindow.h"
#include "BuildConfig.h"
#include "JavaCommon.h"
#include "SettingsUI.h"
@@ -204,13 +205,20 @@ void LaunchController::launchInstance()
return;
}
- if(m_parentWidget)
+ auto mainWindow = qobject_cast<MainWindow *>(m_parentWidget);
+ auto instanceWindow = qobject_cast<InstanceWindow *>(m_parentWidget);
+ if(mainWindow)
{
- m_parentWidget->hide();
+ m_console = mainWindow->showInstanceWindow(m_instance);
+ }
+ else if(instanceWindow)
+ {
+ // NOOP
+ }
+ else
+ {
+ m_console = new InstanceWindow(m_instance);
}
-
- m_console = new ConsoleWindow(m_launcher);
- connect(m_console, &ConsoleWindow::isClosing, this, &LaunchController::instanceEnded);
connect(m_launcher.get(), &LaunchTask::readyForLaunch, this, &LaunchController::readyForLaunch);
m_launcher->prependStep(std::make_shared<TextPrint>(m_launcher.get(), "MultiMC version: " + BuildConfig.printableVersionString() + "\n\n", MessageLevel::MultiMC));
@@ -222,6 +230,7 @@ void LaunchController::readyForLaunch()
if (!m_profiler)
{
m_launcher->proceed();
+ emitSucceeded();
return;
}
@@ -230,6 +239,7 @@ void LaunchController::readyForLaunch()
{
m_launcher->abort();
QMessageBox::critical(m_parentWidget, tr("Error"), tr("Couldn't start profiler: %1").arg(error));
+ emitFailed("Profiler startup failed");
return;
}
BaseProfiler *profilerInstance = m_profiler->createProfiler(m_launcher->instance(), this);
@@ -246,6 +256,7 @@ void LaunchController::readyForLaunch()
msg.setModal(true);
msg.exec();
m_launcher->proceed();
+ emitSucceeded();
});
connect(profilerInstance, &BaseProfiler::abortLaunch, [this](const QString & message)
{
@@ -257,15 +268,7 @@ void LaunchController::readyForLaunch()
msg.setModal(true);
msg.exec();
m_launcher->abort();
+ emitFailed("Profiler startup failed");
});
profilerInstance->beginProfiling(m_launcher);
}
-
-void LaunchController::instanceEnded()
-{
- if(m_parentWidget)
- {
- m_parentWidget->show();
- }
- emitSucceeded();
-}
diff --git a/application/LaunchInteraction.h b/application/LaunchInteraction.h
index b0932e9b..55cb1e58 100644
--- a/application/LaunchInteraction.h
+++ b/application/LaunchInteraction.h
@@ -3,7 +3,7 @@
#include <BaseInstance.h>
#include <tools/BaseProfiler.h>
-class ConsoleWindow;
+class InstanceWindow;
class LaunchController: public Task
{
Q_OBJECT
@@ -36,14 +36,13 @@ private:
private slots:
void readyForLaunch();
- void instanceEnded();
private:
BaseProfilerFactory *m_profiler = nullptr;
bool m_online = true;
InstancePtr m_instance;
QWidget * m_parentWidget = nullptr;
- ConsoleWindow *m_console = nullptr;
+ InstanceWindow *m_console = nullptr;
AuthSessionPtr m_session;
std::shared_ptr <LaunchTask> m_launcher;
};
diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp
index 06d165da..88c0fc09 100644
--- a/application/MainWindow.cpp
+++ b/application/MainWindow.cpp
@@ -67,6 +67,7 @@
#include <updater/UpdateChecker.h>
#include <DesktopServices.h>
+#include "InstanceWindow.h"
#include "InstancePageProvider.h"
#include "InstanceProxyModel.h"
#include "JavaCommon.h"
@@ -1424,24 +1425,62 @@ void MainWindow::on_actionSettings_triggered()
update();
}
+InstanceWindow *MainWindow::showInstanceWindow(InstancePtr instance, QString page)
+{
+ if(!instance)
+ return nullptr;
+ auto id = instance->id();
+ InstanceWindow * window = nullptr;
+
+ auto iter = m_instanceWindows.find(id);
+ if(iter != m_instanceWindows.end())
+ {
+ window = *iter;
+ window->raise();
+ window->activateWindow();
+ }
+ else
+ {
+ window = new InstanceWindow(instance, this);
+ m_instanceWindows[id] = window;
+ connect(window, &InstanceWindow::isClosing, this, &MainWindow::on_instanceWindowClose);
+ }
+ if(!page.isEmpty())
+ {
+ window->selectPage(page);
+ }
+ return window;
+}
+
+void MainWindow::on_instanceWindowClose()
+{
+ auto senderWindow = qobject_cast<InstanceWindow *>(QObject::sender());
+ if(!senderWindow)
+ {
+ return;
+ }
+ m_instanceWindows.remove(senderWindow->instanceId());
+}
+
+
void MainWindow::on_actionInstanceSettings_triggered()
{
- SettingsUI::ShowInstancePageDialog(m_selectedInstance, this, "settings");
+ showInstanceWindow(m_selectedInstance, "settings");
}
void MainWindow::on_actionEditInstNotes_triggered()
{
- SettingsUI::ShowInstancePageDialog(m_selectedInstance, this, "notes");
+ showInstanceWindow(m_selectedInstance, "notes");
}
void MainWindow::on_actionEditInstance_triggered()
{
- SettingsUI::ShowInstancePageDialog(m_selectedInstance, this);
+ showInstanceWindow(m_selectedInstance);
}
void MainWindow::on_actionScreenshots_triggered()
{
- SettingsUI::ShowInstancePageDialog(m_selectedInstance, this, "screenshots");
+ showInstanceWindow(m_selectedInstance, "screenshots");
}
void MainWindow::on_actionManageAccounts_triggered()
@@ -1586,16 +1625,19 @@ void MainWindow::on_actionLaunchInstanceOffline_triggered()