2022-05-26 22:18:54 +01:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
/*
|
2023-06-19 23:36:18 +01:00
|
|
|
* Prism Launcher - Minecraft Launcher
|
2022-05-26 22:18:54 +01:00
|
|
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
2023-06-19 23:36:18 +01:00
|
|
|
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
2016-08-06 14:39:29 +01:00
|
|
|
*
|
2022-05-26 22:18:54 +01:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, version 3.
|
2016-08-06 14:39:29 +01:00
|
|
|
*
|
2022-05-26 22:18:54 +01:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2016-08-06 14:39:29 +01:00
|
|
|
*
|
2022-05-26 22:18:54 +01:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following copyright and
|
|
|
|
* permission notice:
|
|
|
|
*
|
|
|
|
* Copyright 2013-2021 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.
|
2016-08-06 14:39:29 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "InstanceWindow.h"
|
2021-11-20 15:22:22 +00:00
|
|
|
#include "Application.h"
|
2016-08-06 14:39:29 +01:00
|
|
|
|
|
|
|
#include <qlayoutitem.h>
|
|
|
|
#include <QCloseEvent>
|
2023-08-14 17:16:53 +01:00
|
|
|
#include <QHBoxLayout>
|
|
|
|
#include <QMessageBox>
|
|
|
|
#include <QPushButton>
|
|
|
|
#include <QScrollBar>
|
2016-08-06 14:39:29 +01:00
|
|
|
|
2021-11-22 02:55:16 +00:00
|
|
|
#include "ui/dialogs/CustomMessageBox.h"
|
|
|
|
#include "ui/dialogs/ProgressDialog.h"
|
|
|
|
#include "ui/widgets/PageContainer.h"
|
|
|
|
|
2016-08-06 14:39:29 +01:00
|
|
|
#include "InstancePageProvider.h"
|
|
|
|
|
|
|
|
#include "icons/IconList.h"
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
InstanceWindow::InstanceWindow(InstancePtr instance, QWidget* parent) : QMainWindow(parent), m_instance(instance)
|
2016-08-06 14:39:29 +01:00
|
|
|
{
|
2018-07-15 13:51:05 +01:00
|
|
|
setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
|
2021-11-20 15:22:22 +00:00
|
|
|
auto icon = APPLICATION->icons()->getIcon(m_instance->iconKey());
|
2018-07-15 13:51:05 +01:00
|
|
|
QString windowTitle = tr("Console window for ") + m_instance->name();
|
|
|
|
|
|
|
|
// Set window properties
|
|
|
|
{
|
|
|
|
setWindowIcon(icon);
|
|
|
|
setWindowTitle(windowTitle);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add page container
|
|
|
|
{
|
|
|
|
auto provider = std::make_shared<InstancePageProvider>(m_instance);
|
|
|
|
m_container = new PageContainer(provider.get(), "console", this);
|
|
|
|
m_container->setParentContainer(this);
|
|
|
|
setCentralWidget(m_container);
|
2019-08-02 22:52:19 +01:00
|
|
|
setContentsMargins(0, 0, 0, 0);
|
2018-07-15 13:51:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
connect(m_killButton, SIGNAL(clicked(bool)), SLOT(on_btnKillMinecraft_clicked()));
|
|
|
|
|
|
|
|
m_launchOfflineButton = new QPushButton();
|
|
|
|
horizontalLayout->addWidget(m_launchOfflineButton);
|
|
|
|
m_launchOfflineButton->setText(tr("Launch Offline"));
|
2022-07-11 19:46:11 +01:00
|
|
|
|
|
|
|
m_launchDemoButton = new QPushButton();
|
|
|
|
horizontalLayout->addWidget(m_launchDemoButton);
|
|
|
|
m_launchDemoButton->setText(tr("Launch Demo"));
|
|
|
|
|
2018-07-15 13:51:05 +01:00
|
|
|
updateLaunchButtons();
|
|
|
|
connect(m_launchOfflineButton, SIGNAL(clicked(bool)), SLOT(on_btnLaunchMinecraftOffline_clicked()));
|
2022-07-11 19:46:11 +01:00
|
|
|
connect(m_launchDemoButton, SIGNAL(clicked(bool)), SLOT(on_btnLaunchMinecraftDemo_clicked()));
|
2018-07-15 13:51:05 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
{
|
2021-11-20 15:22:22 +00:00
|
|
|
auto base64State = APPLICATION->settings()->get("ConsoleWindowState").toByteArray();
|
2018-07-15 13:51:05 +01:00
|
|
|
restoreState(QByteArray::fromBase64(base64State));
|
2021-11-20 15:22:22 +00:00
|
|
|
auto base64Geometry = APPLICATION->settings()->get("ConsoleWindowGeometry").toByteArray();
|
2018-07-15 13:51:05 +01:00
|
|
|
restoreGeometry(QByteArray::fromBase64(base64Geometry));
|
|
|
|
}
|
|
|
|
|
|
|
|
// set up instance and launch process recognition
|
|
|
|
{
|
|
|
|
auto launchTask = m_instance->getLaunchTask();
|
2022-05-16 19:34:07 +01:00
|
|
|
instanceLaunchTaskChanged(launchTask);
|
|
|
|
connect(m_instance.get(), &BaseInstance::launchTaskChanged, this, &InstanceWindow::instanceLaunchTaskChanged);
|
|
|
|
connect(m_instance.get(), &BaseInstance::runningStatusChanged, this, &InstanceWindow::runningStateChanged);
|
2018-07-15 13:51:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// set up instance destruction detection
|
|
|
|
{
|
|
|
|
connect(m_instance.get(), &BaseInstance::statusChanged, this, &InstanceWindow::on_instanceStatusChanged);
|
|
|
|
}
|
2022-10-14 18:36:48 +01:00
|
|
|
|
|
|
|
// add ourself as the modpack page's instance window
|
|
|
|
{
|
|
|
|
static_cast<ManagedPackPage*>(m_container->getPage("managed_pack"))->setInstanceWindow(this);
|
|
|
|
}
|
|
|
|
|
2018-07-15 13:51:05 +01:00
|
|
|
show();
|
2016-08-06 14:39:29 +01:00
|
|
|
}
|
|
|
|
|
2016-10-02 23:55:54 +01:00
|
|
|
void InstanceWindow::on_instanceStatusChanged(BaseInstance::Status, BaseInstance::Status newStatus)
|
|
|
|
{
|
2023-08-14 17:16:53 +01:00
|
|
|
if (newStatus == BaseInstance::Status::Gone) {
|
2018-07-15 13:51:05 +01:00
|
|
|
m_doNotSave = true;
|
|
|
|
close();
|
|
|
|
}
|
2016-10-02 23:55:54 +01:00
|
|
|
}
|
|
|
|
|
2017-09-20 22:38:31 +01:00
|
|
|
void InstanceWindow::updateLaunchButtons()
|
2016-08-06 14:39:29 +01:00
|
|
|
{
|
2023-08-14 17:16:53 +01:00
|
|
|
if (m_instance->isRunning()) {
|
2018-07-15 13:51:05 +01:00
|
|
|
m_launchOfflineButton->setEnabled(false);
|
2022-07-11 19:46:11 +01:00
|
|
|
m_launchDemoButton->setEnabled(false);
|
2018-07-15 13:51:05 +01:00
|
|
|
m_killButton->setText(tr("Kill"));
|
2021-02-05 01:46:09 +00:00
|
|
|
m_killButton->setObjectName("killButton");
|
2018-07-15 13:51:05 +01:00
|
|
|
m_killButton->setToolTip(tr("Kill the running instance"));
|
2023-08-14 17:16:53 +01:00
|
|
|
} else if (!m_instance->canLaunch()) {
|
2018-07-15 13:51:05 +01:00
|
|
|
m_launchOfflineButton->setEnabled(false);
|
2022-07-11 19:46:11 +01:00
|
|
|
m_launchDemoButton->setEnabled(false);
|
2018-07-15 13:51:05 +01:00
|
|
|
m_killButton->setText(tr("Launch"));
|
2021-02-05 01:46:09 +00:00
|
|
|
m_killButton->setObjectName("launchButton");
|
2018-07-15 13:51:05 +01:00
|
|
|
m_killButton->setToolTip(tr("Launch the instance"));
|
|
|
|
m_killButton->setEnabled(false);
|
2023-08-14 17:16:53 +01:00
|
|
|
} else {
|
2018-07-15 13:51:05 +01:00
|
|
|
m_launchOfflineButton->setEnabled(true);
|
2022-09-15 23:23:58 +01:00
|
|
|
|
|
|
|
// Disable demo-mode if not available.
|
|
|
|
auto instance = dynamic_cast<MinecraftInstance*>(m_instance.get());
|
|
|
|
if (instance) {
|
|
|
|
m_launchDemoButton->setEnabled(instance->supportsDemo());
|
|
|
|
}
|
|
|
|
|
2018-07-15 13:51:05 +01:00
|
|
|
m_killButton->setText(tr("Launch"));
|
2021-02-05 01:46:09 +00:00
|
|
|
m_killButton->setObjectName("launchButton");
|
2018-07-15 13:51:05 +01:00
|
|
|
m_killButton->setToolTip(tr("Launch the instance"));
|
|
|
|
}
|
2021-02-05 02:18:21 +00:00
|
|
|
// NOTE: this is a hack to force the button to recalculate its style
|
|
|
|
m_killButton->setStyleSheet("/* */");
|
|
|
|
m_killButton->setStyleSheet(QString());
|
2016-08-06 14:39:29 +01:00
|
|
|
}
|
|
|
|
|
2017-04-26 19:51:50 +01:00
|
|
|
void InstanceWindow::on_btnLaunchMinecraftOffline_clicked()
|
|
|
|
{
|
2022-07-11 19:46:11 +01:00
|
|
|
APPLICATION->launch(m_instance, false, false, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstanceWindow::on_btnLaunchMinecraftDemo_clicked()
|
|
|
|
{
|
|
|
|
APPLICATION->launch(m_instance, false, true, nullptr);
|
2017-04-26 19:51:50 +01:00
|
|
|
}
|
|
|
|
|
2022-05-16 19:34:07 +01:00
|
|
|
void InstanceWindow::instanceLaunchTaskChanged(shared_qobject_ptr<LaunchTask> proc)
|
2016-08-06 14:39:29 +01:00
|
|
|
{
|
2018-07-15 13:51:05 +01:00
|
|
|
m_proc = proc;
|
2016-08-06 14:39:29 +01:00
|
|
|
}
|
|
|
|
|
2022-05-16 19:34:07 +01:00
|
|
|
void InstanceWindow::runningStateChanged(bool running)
|
2016-08-06 14:39:29 +01:00
|
|
|
{
|
2018-07-15 13:51:05 +01:00
|
|
|
updateLaunchButtons();
|
|
|
|
m_container->refreshContainer();
|
2023-08-14 17:16:53 +01:00
|
|
|
if (running) {
|
2019-07-23 23:24:02 +01:00
|
|
|
selectPage("log");
|
|
|
|
}
|
2016-08-06 14:39:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void InstanceWindow::on_closeButton_clicked()
|
|
|
|
{
|
2018-07-15 13:51:05 +01:00
|
|
|
close();
|
2016-08-06 14:39:29 +01:00
|
|
|
}
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
void InstanceWindow::closeEvent(QCloseEvent* event)
|
2016-08-06 14:39:29 +01:00
|
|
|
{
|
2018-07-15 13:51:05 +01:00
|
|
|
bool proceed = true;
|
2023-08-14 17:16:53 +01:00
|
|
|
if (!m_doNotSave) {
|
2018-07-15 13:51:05 +01:00
|
|
|
proceed &= m_container->prepareToClose();
|
|
|
|
}
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
if (!proceed) {
|
2018-07-15 13:51:05 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-20 15:22:22 +00:00
|
|
|
APPLICATION->settings()->set("ConsoleWindowState", saveState().toBase64());
|
|
|
|
APPLICATION->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
|
2018-07-15 13:51:05 +01:00
|
|
|
emit isClosing();
|
|
|
|
event->accept();
|
2016-08-06 14:39:29 +01:00
|
|
|
}
|
|
|
|
|
2016-10-28 02:36:29 +01:00
|
|
|
bool InstanceWindow::saveAll()
|
|
|
|
{
|
2018-07-15 13:51:05 +01:00
|
|
|
return m_container->saveAll();
|
2016-10-28 02:36:29 +01:00
|
|
|
}
|
|
|
|
|
2016-08-06 14:39:29 +01:00
|
|
|
void InstanceWindow::on_btnKillMinecraft_clicked()
|
|
|
|
{
|
2023-08-14 17:16:53 +01:00
|
|
|
if (m_instance->isRunning()) {
|
2021-11-20 15:22:22 +00:00
|
|
|
APPLICATION->kill(m_instance);
|
2023-08-14 17:16:53 +01:00
|
|
|
} else {
|
2022-07-11 19:46:11 +01:00
|
|
|
APPLICATION->launch(m_instance, true, false, nullptr);
|
2018-07-15 13:51:05 +01:00
|
|
|
}
|
2016-08-06 14:39:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QString InstanceWindow::instanceId()
|
|
|
|
{
|
2018-07-15 13:51:05 +01:00
|
|
|
return m_instance->id();
|
2016-08-06 14:39:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool InstanceWindow::selectPage(QString pageId)
|
|
|
|
{
|
2018-07-15 13:51:05 +01:00
|
|
|
return m_container->selectPage(pageId);
|
2016-08-06 14:39:29 +01:00
|
|
|
}
|
|
|
|
|
2023-06-22 13:11:55 +01:00
|
|
|
BasePage* InstanceWindow::selectedPage() const
|
2023-06-19 22:42:27 +01:00
|
|
|
{
|
|
|
|
return m_container->selectedPage();
|
|
|
|
}
|
|
|
|
|
2016-11-06 23:18:27 +00:00
|
|
|
void InstanceWindow::refreshContainer()
|
|
|
|
{
|
2018-07-15 13:51:05 +01:00
|
|
|
m_container->refreshContainer();
|
2016-11-06 23:18:27 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 17:16:53 +01:00
|
|
|
InstanceWindow::~InstanceWindow() {}
|
2017-09-26 18:04:37 +01:00
|
|
|
|
|
|
|
bool InstanceWindow::requestClose()
|
|
|
|
{
|
2023-08-14 17:16:53 +01:00
|
|
|
if (m_container->prepareToClose()) {
|
2018-07-15 13:51:05 +01:00
|
|
|
close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2017-09-26 18:04:37 +01:00
|
|
|
}
|