// SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2023 TheKodeToad * * 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. * * 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * 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. */ #include "InstanceWindow.h" #include "Application.h" #include #include #include #include #include #include #include "ui/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 = APPLICATION->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 provider = std::make_shared(m_instance); m_container = new PageContainer(provider.get(), "console", this); m_container->setParentContainer(this); setCentralWidget(m_container); setContentsMargins(0, 0, 0, 0); } // 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, &QPushButton::clicked, m_container, &PageContainer::help); auto spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalLayout->addSpacerItem(spacer); m_launchButton = new QToolButton(this); m_launchButton->setText(tr("&Launch")); m_launchButton->setToolTip(tr("Launch the instance")); m_launchButton->setPopupMode(QToolButton::MenuButtonPopup); m_launchButton->setMinimumWidth(80); // HACK!! horizontalLayout->addWidget(m_launchButton); connect(m_launchButton, &QPushButton::clicked, this, [this] { APPLICATION->launch(m_instance); }); m_killButton = new QPushButton(this); m_killButton->setText(tr("&Kill")); m_killButton->setToolTip(tr("Kill the running instance")); horizontalLayout->addWidget(m_killButton); connect(m_killButton, &QPushButton::clicked, this, [this] { APPLICATION->kill(m_instance); }); updateButtons(); m_closeButton = new QPushButton(); m_closeButton->setText(tr("Close")); horizontalLayout->addWidget(m_closeButton); connect(m_closeButton, &QPushButton::clicked, this, &QMainWindow::close); m_container->addButtons(horizontalLayout); connect(m_instance.get(), &BaseInstance::profilerChanged, this, &InstanceWindow::updateButtons); connect(APPLICATION, &Application::globalSettingsClosed, this, &InstanceWindow::updateButtons); } // restore window state { auto base64State = APPLICATION->settings()->get("ConsoleWindowState").toByteArray(); restoreState(QByteArray::fromBase64(base64State)); auto base64Geometry = APPLICATION->settings()->get("ConsoleWindowGeometry").toByteArray(); restoreGeometry(QByteArray::fromBase64(base64Geometry)); } // set up instance and launch process recognition { auto launchTask = m_instance->getLaunchTask(); instanceLaunchTaskChanged(launchTask); connect(m_instance.get(), &BaseInstance::launchTaskChanged, this, &InstanceWindow::instanceLaunchTaskChanged); connect(m_instance.get(), &BaseInstance::runningStatusChanged, this, &InstanceWindow::runningStateChanged); } // set up instance destruction detection { connect(m_instance.get(), &BaseInstance::statusChanged, this, &InstanceWindow::on_instanceStatusChanged); } // add ourself as the modpack page's instance window { static_cast(m_container->getPage("managed_pack"))->setInstanceWindow(this); } show(); } void InstanceWindow::on_instanceStatusChanged(BaseInstance::Status, BaseInstance::Status newStatus) { if(newStatus == BaseInstance::Status::Gone) { m_doNotSave = true; close(); } } void InstanceWindow::updateButtons() { m_launchButton->setEnabled(m_instance->canLaunch()); m_killButton->setEnabled(m_instance->isRunning()); QMenu *launchMenu = m_launchButton->menu(); if (launchMenu) launchMenu->clear(); else launchMenu = new QMenu(this); m_instance->populateLaunchMenu(launchMenu); m_launchButton->setMenu(launchMenu); } void InstanceWindow::instanceLaunchTaskChanged(shared_qobject_ptr proc) { m_proc = proc; } void InstanceWindow::runningStateChanged(bool running) { updateButtons(); m_container->refreshContainer(); if(running) { selectPage("log"); } } void InstanceWindow::closeEvent(QCloseEvent *event) { bool proceed = true; if(!m_doNotSave) { proceed &= m_container->prepareToClose(); } if(!proceed) { return; } APPLICATION->settings()->set("ConsoleWindowState", saveState().toBase64()); APPLICATION->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64()); emit isClosing(); event->accept(); } bool InstanceWindow::saveAll() { return m_container->saveAll(); } QString InstanceWindow::instanceId() { return m_instance->id(); } bool InstanceWindow::selectPage(QString pageId) { return m_container->selectPage(pageId); } void InstanceWindow::refreshContainer() { m_container->refreshContainer(); } bool InstanceWindow::requestClose() { if(m_container->prepareToClose()) { close(); return true; } return false; }