diff options
Diffstat (limited to 'application/pages/instance')
35 files changed, 0 insertions, 6609 deletions
diff --git a/application/pages/instance/GameOptionsPage.cpp b/application/pages/instance/GameOptionsPage.cpp deleted file mode 100644 index 782f2ab3..00000000 --- a/application/pages/instance/GameOptionsPage.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "GameOptionsPage.h" -#include "ui_GameOptionsPage.h" -#include "minecraft/MinecraftInstance.h" -#include "minecraft/gameoptions/GameOptions.h" - -GameOptionsPage::GameOptionsPage(MinecraftInstance * inst, QWidget* parent) - : QWidget(parent), ui(new Ui::GameOptionsPage) -{ - ui->setupUi(this); - ui->tabWidget->tabBar()->hide(); - m_model = inst->gameOptionsModel(); - ui->optionsView->setModel(m_model.get()); - auto head = ui->optionsView->header(); - if(head->count()) - { - head->setSectionResizeMode(0, QHeaderView::ResizeToContents); - for(int i = 1; i < head->count(); i++) - { - head->setSectionResizeMode(i, QHeaderView::Stretch); - } - } -} - -GameOptionsPage::~GameOptionsPage() -{ - // m_model->save(); -} - -void GameOptionsPage::openedImpl() -{ - // m_model->observe(); -} - -void GameOptionsPage::closedImpl() -{ - // m_model->unobserve(); -} diff --git a/application/pages/instance/GameOptionsPage.h b/application/pages/instance/GameOptionsPage.h deleted file mode 100644 index 0fd2fbff..00000000 --- a/application/pages/instance/GameOptionsPage.h +++ /dev/null @@ -1,63 +0,0 @@ -/* 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. - */ - -#pragma once - -#include <QWidget> -#include <QString> - -#include "pages/BasePage.h" -#include <MultiMC.h> - -namespace Ui -{ -class GameOptionsPage; -} - -class GameOptions; -class MinecraftInstance; - -class GameOptionsPage : public QWidget, public BasePage -{ - Q_OBJECT - -public: - explicit GameOptionsPage(MinecraftInstance *inst, QWidget *parent = 0); - virtual ~GameOptionsPage(); - - void openedImpl() override; - void closedImpl() override; - - virtual QString displayName() const override - { - return tr("Game Options"); - } - virtual QIcon icon() const override - { - return MMC->getThemedIcon("settings"); - } - virtual QString id() const override - { - return "gameoptions"; - } - virtual QString helpPage() const override - { - return "Game-Options-management"; - } - -private: // data - Ui::GameOptionsPage *ui = nullptr; - std::shared_ptr<GameOptions> m_model; -}; diff --git a/application/pages/instance/GameOptionsPage.ui b/application/pages/instance/GameOptionsPage.ui deleted file mode 100644 index f0a5ce0e..00000000 --- a/application/pages/instance/GameOptionsPage.ui +++ /dev/null @@ -1,88 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>GameOptionsPage</class> - <widget class="QWidget" name="GameOptionsPage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>706</width> - <height>575</height> - </rect> - </property> - <layout class="QGridLayout" name="gridLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item row="0" column="0"> - <widget class="QTabWidget" name="tabWidget"> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="tab"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <attribute name="title"> - <string notr="true">Tab 1</string> - </attribute> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0" colspan="2"> - <widget class="QTreeView" name="optionsView"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="acceptDrops"> - <bool>true</bool> - </property> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::SingleSelection</enum> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectRows</enum> - </property> - <property name="iconSize"> - <size> - <width>64</width> - <height>64</height> - </size> - </property> - <property name="rootIsDecorated"> - <bool>false</bool> - </property> - <attribute name="headerStretchLastSection"> - <bool>false</bool> - </attribute> - </widget> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>tabWidget</tabstop> - <tabstop>optionsView</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/application/pages/instance/InstanceSettingsPage.cpp b/application/pages/instance/InstanceSettingsPage.cpp deleted file mode 100644 index 7bd424c0..00000000 --- a/application/pages/instance/InstanceSettingsPage.cpp +++ /dev/null @@ -1,338 +0,0 @@ -#include "InstanceSettingsPage.h" -#include "ui_InstanceSettingsPage.h" - -#include <QFileDialog> -#include <QDialog> -#include <QMessageBox> - -#include "dialogs/VersionSelectDialog.h" -#include "JavaCommon.h" -#include "MultiMC.h" - -#include <java/JavaInstallList.h> -#include <FileSystem.h> -#include <sys.h> -#include <widgets/CustomCommands.h> - -InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) - : QWidget(parent), ui(new Ui::InstanceSettingsPage), m_instance(inst) -{ - m_settings = inst->settings(); - ui->setupUi(this); - auto sysMB = Sys::getSystemRam() / Sys::mebibyte; - ui->maxMemSpinBox->setMaximum(sysMB); - connect(ui->openGlobalJavaSettingsButton, &QCommandLinkButton::clicked, this, &InstanceSettingsPage::globalSettingsButtonClicked); - connect(MMC, &MultiMC::globalSettingsAboutToOpen, this, &InstanceSettingsPage::applySettings); - connect(MMC, &MultiMC::globalSettingsClosed, this, &InstanceSettingsPage::loadSettings); - loadSettings(); -} - -bool InstanceSettingsPage::shouldDisplay() const -{ - return !m_instance->isRunning(); -} - -InstanceSettingsPage::~InstanceSettingsPage() -{ - delete ui; -} - -void InstanceSettingsPage::globalSettingsButtonClicked(bool) -{ - switch(ui->settingsTabs->currentIndex()) { - case 0: - MMC->ShowGlobalSettings(this, "java-settings"); - return; - case 1: - MMC->ShowGlobalSettings(this, "minecraft-settings"); - return; - case 2: - MMC->ShowGlobalSettings(this, "custom-commands"); - return; - } -} - -bool InstanceSettingsPage::apply() -{ - applySettings(); - return true; -} - -void InstanceSettingsPage::applySettings() -{ - SettingsObject::Lock lock(m_settings); - - // Console - bool console = ui->consoleSettingsBox->isChecked(); - m_settings->set("OverrideConsole", console); - if (console) - { - m_settings->set("ShowConsole", ui->showConsoleCheck->isChecked()); - m_settings->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked()); - m_settings->set("ShowConsoleOnError", ui->showConsoleErrorCheck->isChecked()); - } - else - { - m_settings->reset("ShowConsole"); - m_settings->reset("AutoCloseConsole"); - m_settings->reset("ShowConsoleOnError"); - } - - // Window Size - bool window = ui->windowSizeGroupBox->isChecked(); - m_settings->set("OverrideWindow", window); - if (window) - { - m_settings->set("LaunchMaximized", ui->maximizedCheckBox->isChecked()); - m_settings->set("MinecraftWinWidth", ui->windowWidthSpinBox->value()); - m_settings->set("MinecraftWinHeight", ui->windowHeightSpinBox->value()); - } - else - { - m_settings->reset("LaunchMaximized"); - m_settings->reset("MinecraftWinWidth"); - m_settings->reset("MinecraftWinHeight"); - } - - // Memory - bool memory = ui->memoryGroupBox->isChecked(); - m_settings->set("OverrideMemory", memory); - if (memory) - { - int min = ui->minMemSpinBox->value(); - int max = ui->maxMemSpinBox->value(); - if(min < max) - { - m_settings->set("MinMemAlloc", min); - m_settings->set("MaxMemAlloc", max); - } - else - { - m_settings->set("MinMemAlloc", max); - m_settings->set("MaxMemAlloc", min); - } - m_settings->set("PermGen", ui->permGenSpinBox->value()); - } - else - { - m_settings->reset("MinMemAlloc"); - m_settings->reset("MaxMemAlloc"); - m_settings->reset("PermGen"); - } - - // Java Install Settings - bool javaInstall = ui->javaSettingsGroupBox->isChecked(); - m_settings->set("OverrideJavaLocation", javaInstall); - if (javaInstall) - { - m_settings->set("JavaPath", ui->javaPathTextBox->text()); - } - else - { - m_settings->reset("JavaPath"); - } - - // Java arguments - bool javaArgs = ui->javaArgumentsGroupBox->isChecked(); - m_settings->set("OverrideJavaArgs", javaArgs); - if(javaArgs) - { - m_settings->set("JvmArgs", ui->jvmArgsTextBox->toPlainText().replace("\n", " ")); - JavaCommon::checkJVMArgs(m_settings->get("JvmArgs").toString(), this->parentWidget()); - } - else - { - m_settings->reset("JvmArgs"); - } - - // old generic 'override both' is removed. - m_settings->reset("OverrideJava"); - - // Custom Commands - bool custcmd = ui->customCommands->checked(); - m_settings->set("OverrideCommands", custcmd); - if (custcmd) - { - m_settings->set("PreLaunchCommand", ui->customCommands->prelaunchCommand()); - m_settings->set("WrapperCommand", ui->customCommands->wrapperCommand()); - m_settings->set("PostExitCommand", ui->customCommands->postexitCommand()); - } - else - { - m_settings->reset("PreLaunchCommand"); - m_settings->reset("WrapperCommand"); - m_settings->reset("PostExitCommand"); - } - - // Workarounds - bool workarounds = ui->nativeWorkaroundsGroupBox->isChecked(); - m_settings->set("OverrideNativeWorkarounds", workarounds); - if(workarounds) - { - m_settings->set("UseNativeOpenAL", ui->useNativeOpenALCheck->isChecked()); - m_settings->set("UseNativeGLFW", ui->useNativeGLFWCheck->isChecked()); - } - else - { - m_settings->reset("UseNativeOpenAL"); - m_settings->reset("UseNativeGLFW"); - } - - // Game time - bool gameTime = ui->gameTimeGroupBox->isChecked(); - m_settings->set("OverrideGameTime", gameTime); - if (gameTime) - { - m_settings->set("ShowGameTime", ui->showGameTime->isChecked()); - m_settings->set("RecordGameTime", ui->recordGameTime->isChecked()); - } - else - { - m_settings->reset("ShowGameTime"); - m_settings->reset("RecordGameTime"); - } - - // Join server on launch - bool joinServerOnLaunch = ui->serverJoinGroupBox->isChecked(); - m_settings->set("JoinServerOnLaunch", joinServerOnLaunch); - if (joinServerOnLaunch) - { - m_settings->set("JoinServerOnLaunchAddress", ui->serverJoinAddress->text()); - } - else - { - m_settings->reset("JoinServerOnLaunchAddress"); - } -} - -void InstanceSettingsPage::loadSettings() -{ - // Console - ui->consoleSettingsBox->setChecked(m_settings->get("OverrideConsole").toBool()); - ui->showConsoleCheck->setChecked(m_settings->get("ShowConsole").toBool()); - ui->autoCloseConsoleCheck->setChecked(m_settings->get("AutoCloseConsole").toBool()); - ui->showConsoleErrorCheck->setChecked(m_settings->get("ShowConsoleOnError").toBool()); - - // Window Size - ui->windowSizeGroupBox->setChecked(m_settings->get("OverrideWindow").toBool()); - ui->maximizedCheckBox->setChecked(m_settings->get("LaunchMaximized").toBool()); - ui->windowWidthSpinBox->setValue(m_settings->get("MinecraftWinWidth").toInt()); - ui->windowHeightSpinBox->setValue(m_settings->get("MinecraftWinHeight").toInt()); - - // Memory - ui->memoryGroupBox->setChecked(m_settings->get("OverrideMemory").toBool()); - int min = m_settings->get("MinMemAlloc").toInt(); - int max = m_settings->get("MaxMemAlloc").toInt(); - if(min < max) - { - ui->minMemSpinBox->setValue(min); - ui->maxMemSpinBox->setValue(max); - } - else - { - ui->minMemSpinBox->setValue(max); - ui->maxMemSpinBox->setValue(min); - } - ui->permGenSpinBox->setValue(m_settings->get("PermGen").toInt()); - bool permGenVisible = m_settings->get("PermGenVisible").toBool(); - ui->permGenSpinBox->setVisible(permGenVisible); - ui->labelPermGen->setVisible(permGenVisible); - ui->labelPermgenNote->setVisible(permGenVisible); - - - // Java Settings - bool overrideJava = m_settings->get("OverrideJava").toBool(); - bool overrideLocation = m_settings->get("OverrideJavaLocation").toBool() || overrideJava; - bool overrideArgs = m_settings->get("OverrideJavaArgs").toBool() || overrideJava; - - ui->javaSettingsGroupBox->setChecked(overrideLocation); - ui->javaPathTextBox->setText(m_settings->get("JavaPath").toString()); - - ui->javaArgumentsGroupBox->setChecked(overrideArgs); - ui->jvmArgsTextBox->setPlainText(m_settings->get("JvmArgs").toString()); - - // Custom commands - ui->customCommands->initialize( - true, - m_settings->get("OverrideCommands").toBool(), - m_settings->get("PreLaunchCommand").toString(), - m_settings->get("WrapperCommand").toString(), - m_settings->get("PostExitCommand").toString() - ); - - // Workarounds - ui->nativeWorkaroundsGroupBox->setChecked(m_settings->get("OverrideNativeWorkarounds").toBool()); - ui->useNativeGLFWCheck->setChecked(m_settings->get("UseNativeGLFW").toBool()); - ui->useNativeOpenALCheck->setChecked(m_settings->get("UseNativeOpenAL").toBool()); - - // Miscellanous - ui->gameTimeGroupBox->setChecked(m_settings->get("OverrideGameTime").toBool()); - ui->showGameTime->setChecked(m_settings->get("ShowGameTime").toBool()); - ui->recordGameTime->setChecked(m_settings->get("RecordGameTime").toBool()); - - ui->serverJoinGroupBox->setChecked(m_settings->get("JoinServerOnLaunch").toBool()); - ui->serverJoinAddress->setText(m_settings->get("JoinServerOnLaunchAddress").toString()); -} - -void InstanceSettingsPage::on_javaDetectBtn_clicked() -{ - JavaInstallPtr java; - - VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true); - vselect.setResizeOn(2); - vselect.exec(); - - if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) - { - java = std::dynamic_pointer_cast<JavaInstall>(vselect.selectedVersion()); - ui->javaPathTextBox->setText(java->path); - bool visible = java->id.requiresPermGen() && m_settings->get("OverrideMemory").toBool(); - ui->permGenSpinBox->setVisible(visible); - ui->labelPermGen->setVisible(visible); - ui->labelPermgenNote->setVisible(visible); - m_settings->set("PermGenVisible", visible); - } -} - -void InstanceSettingsPage::on_javaBrowseBtn_clicked() -{ - QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable")); - - // do not allow current dir - it's dirty. Do not allow dirs that don't exist - if(raw_path.isEmpty()) - { - return; - } - QString cooked_path = FS::NormalizePath(raw_path); - - QFileInfo javaInfo(cooked_path); - if(!javaInfo.exists() || !javaInfo.isExecutable()) - { - return; - } - ui->javaPathTextBox->setText(cooked_path); - - // custom Java could be anything... enable perm gen option - ui->permGenSpinBox->setVisible(true); - ui->labelPermGen->setVisible(true); - ui->labelPermgenNote->setVisible(true); - m_settings->set("PermGenVisible", true); -} - -void InstanceSettingsPage::on_javaTestBtn_clicked() -{ - if(checker) - { - return; - } - checker.reset(new JavaCommon::TestCheck( - this, ui->javaPathTextBox->text(), ui->jvmArgsTextBox->toPlainText().replace("\n", " "), - ui->minMemSpinBox->value(), ui->maxMemSpinBox->value(), ui->permGenSpinBox->value())); - connect(checker.get(), SIGNAL(finished()), SLOT(checkerFinished())); - checker->run(); -} - -void InstanceSettingsPage::checkerFinished() -{ - checker.reset(); -} diff --git a/application/pages/instance/InstanceSettingsPage.h b/application/pages/instance/InstanceSettingsPage.h deleted file mode 100644 index 068213a8..00000000 --- a/application/pages/instance/InstanceSettingsPage.h +++ /dev/null @@ -1,76 +0,0 @@ -/* 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. - */ - -#pragma once - -#include <QWidget> - -#include "java/JavaChecker.h" -#include "BaseInstance.h" -#include <QObjectPtr.h> -#include "pages/BasePage.h" -#include "JavaCommon.h" -#include "MultiMC.h" - -class JavaChecker; -namespace Ui -{ -class InstanceSettingsPage; -} - -class InstanceSettingsPage : public QWidget, public BasePage -{ - Q_OBJECT - -public: - explicit InstanceSettingsPage(BaseInstance *inst, QWidget *parent = 0); - virtual ~InstanceSettingsPage(); - virtual QString displayName() const override - { - return tr("Settings"); - } - virtual QIcon icon() const override - { - return MMC->getThemedIcon("instance-settings"); - } - virtual QString id() const override - { - return "settings"; - } - virtual bool apply() override; - virtual QString helpPage() const override - { - return "Instance-settings"; - } - virtual bool shouldDisplay() const override; - -private slots: - void on_javaDetectBtn_clicked(); - void on_javaTestBtn_clicked(); - void on_javaBrowseBtn_clicked(); - - void applySettings(); - void loadSettings(); - - void checkerFinished(); - - void globalSettingsButtonClicked(bool checked); - -private: - Ui::InstanceSettingsPage *ui; - BaseInstance *m_instance; - SettingsObjectPtr m_settings; - unique_qobject_ptr<JavaCommon::TestCheck> checker; -}; diff --git a/application/pages/instance/InstanceSettingsPage.ui b/application/pages/instance/InstanceSettingsPage.ui deleted file mode 100644 index e569ce56..00000000 --- a/application/pages/instance/InstanceSettingsPage.ui +++ /dev/null @@ -1,548 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>InstanceSettingsPage</class> - <widget class="QWidget" name="InstanceSettingsPage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>691</width> - <height>581</height> - </rect> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QCommandLinkButton" name="openGlobalJavaSettingsButton"> - <property name="text"> - <string>Open Global Settings</string> - </property> - <property name="description"> - <string>The settings here are overrides for global settings.</string> - </property> - </widget> - </item> - <item> - <widget class="QTabWidget" name="settingsTabs"> - <property name="tabShape"> - <enum>QTabWidget::Rounded</enum> - </property> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="minecraftTab"> - <attribute name="title"> - <string notr="true">Java</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_5"> - <item> - <widget class="QGroupBox" name="javaSettingsGroupBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Java insta&llation</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0" colspan="3"> - <widget class="QLineEdit" name="javaPathTextBox"/> - </item> - <item row="1" column="0"> - <widget class="QPushButton" name="javaDetectBtn"> - <property name="text"> - <string>Auto-detect...</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QPushButton" name="javaBrowseBtn"> - <property name="text"> - <string>Browse...</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QPushButton" name="javaTestBtn"> - <property name="text"> - <string>Test</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="memoryGroupBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Memor&y</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0"> - <widget class="QLabel" name="labelMinMem"> - <property name="text"> - <string>Minimum memory allocation:</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSpinBox" name="maxMemSpinBox"> - <property name="toolTip"> - <string>The maximum amount of memory Minecraft is allowed to use.</string> - </property> - <property name="suffix"> - <string notr="true"> MiB</string> - </property> - <property name="minimum"> - <number>128</number> - </property> - <property name="maximum"> - <number>65536</number> - </property> - <property name="singleStep"> - <number>128</number> - </property> - <property name="value"> - <number>1024</number> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QSpinBox" name="minMemSpinBox"> - <property name="toolTip"> - <string>The amount of memory Minecraft is started with.</string> - </property> - <property name="suffix"> - <string notr="true"> MiB</string> - </property> - <property name="minimum"> - <number>128</number> - </property> - <property name="maximum"> - <number>65536</number> - </property> - <property name="singleStep"> - <number>128</number> - </property> - <property name="value"> - <number>256</number> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QSpinBox" name="permGenSpinBox"> - <property name="toolTip"> - <string>The amount of memory available to store loaded Java classes.</string> - </property> - <property name="suffix"> - <string notr="true"> MiB</string> - </property> - <property name="minimum"> - <number>64</number> - </property> - <property name="maximum"> - <number>999999999</number> - </property> - <property name="singleStep"> - <number>8</number> - </property> - <property name="value"> - <number>64</number> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="labelPermGen"> - <property name="text"> - <string notr="true">PermGen:</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="labelMaxMem"> - <property name="text"> - <string>Maximum memory allocation:</string> - </property> - </widget> - </item> - <item row="3" column="0" colspan="2"> - <widget class="QLabel" name="labelPermgenNote"> - <property name="text"> - <string>Note: Permgen is set automatically by Java 8 and later</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="javaArgumentsGroupBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Java argumen&ts</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout_5"> - <item row="1" column="1"> - <widget class="QPlainTextEdit" name="jvmArgsTextBox"/> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="javaTab"> - <attribute name="title"> - <string>Game windows</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <widget class="QGroupBox" name="windowSizeGroupBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Game Window</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_4"> - <item> - <widget class="QCheckBox" name="maximizedCheckBox"> - <property name="text"> - <string>Start Minecraft maximized?</string> - </property> - </widget> - </item> - <item> - <layout class="QGridLayout" name="gridLayoutWindowSize"> - <item row="1" column="0"> - <widget class="QLabel" name="labelWindowHeight"> - <property name="text"> - <string>Window height:</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="labelWindowWidth"> - <property name="text"> - <string>Window width:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QSpinBox" name="windowWidthSpinBox"> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>65536</number> - </property> - <property name="singleStep"> - <number>1</number> - </property> - <property name="value"> - <number>854</number> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSpinBox" name="windowHeightSpinBox"> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>65536</number> - </property> - <property name="value"> - <number>480</number> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="consoleSettingsBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Conso&le Settings</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QCheckBox" name="showConsoleCheck"> - <property name="text"> - <string>Show console while the game is running?</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="autoCloseConsoleCheck"> - <property name="text"> - <string>Automatically close console when the game quits?</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="showConsoleErrorCheck"> - <property name="text"> - <string>Show console when the game crashes?</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacerMinecraft_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>88</width> - <height>125</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <widget class="QWidget" name="tab"> - <attribute name="title"> - <string>Custom commands</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_6"> - <item> - <widget class="CustomCommands" name="customCommands" native="true"/> - </item> - </layout> - </widget> - <widget class="QWidget" name="workaroundsPage"> - <attribute name="title"> - <string>Workarounds</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_8"> - <item> - <widget class="QGroupBox" name="nativeWorkaroundsGroupBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Native libraries</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_7"> - <item> - <widget class="QCheckBox" name="useNativeGLFWCheck"> - <property name="text"> - <string>Use system installation of GLFW</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="useNativeOpenALCheck"> - <property name="text"> - <string>Use system installation of OpenAL</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <widget class="QWidget" name="miscellanousPage"> - <attribute name="title"> - <string>Miscellanous</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_9"> - <item> - <widget class="QGroupBox" name="gameTimeGroupBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Override global game time settings</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_10"> - <item> - <widget class="QCheckBox" name="showGameTime"> - <property name="text"> - <string>Show time spent playing this instance</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="recordGameTime"> - <property name="text"> - <string>Record time spent playing this instance</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="serverJoinGroupBox"> - <property name="title"> - <string>Set a server to join on launch</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_11"> - <item> - <layout class="QGridLayout" name="serverJoinLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="serverJoinAddressLabel"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Server address:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="serverJoinAddress"/> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacerMiscellanous"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>CustomCommands</class> - <extends>QWidget</extends> - <header>widgets/CustomCommands.h</header> - <container>1</container> - </customwidget> - </customwidgets> - <tabstops> - <tabstop>openGlobalJavaSettingsButton</tabstop> - <tabstop>settingsTabs</tabstop> - <tabstop>javaSettingsGroupBox</tabstop> - <tabstop>javaPathTextBox</tabstop> - <tabstop>javaDetectBtn</tabstop> - <tabstop>javaBrowseBtn</tabstop> - <tabstop>javaTestBtn</tabstop> - <tabstop>memoryGroupBox</tabstop> - <tabstop>minMemSpinBox</tabstop> - <tabstop>maxMemSpinBox</tabstop> - <tabstop>permGenSpinBox</tabstop> - <tabstop>javaArgumentsGroupBox</tabstop> - <tabstop>jvmArgsTextBox</tabstop> - <tabstop>windowSizeGroupBox</tabstop> - <tabstop>maximizedCheckBox</tabstop> - <tabstop>windowWidthSpinBox</tabstop> - <tabstop>windowHeightSpinBox</tabstop> - <tabstop>consoleSettingsBox</tabstop> - <tabstop>showConsoleCheck</tabstop> - <tabstop>autoCloseConsoleCheck</tabstop> - <tabstop>showConsoleErrorCheck</tabstop> - <tabstop>nativeWorkaroundsGroupBox</tabstop> - <tabstop>useNativeGLFWCheck</tabstop> - <tabstop>useNativeOpenALCheck</tabstop> - <tabstop>showGameTime</tabstop> - <tabstop>recordGameTime</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/application/pages/instance/LegacyUpgradePage.cpp b/application/pages/instance/LegacyUpgradePage.cpp deleted file mode 100644 index af800b03..00000000 --- a/application/pages/instance/LegacyUpgradePage.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "LegacyUpgradePage.h" -#include "ui_LegacyUpgradePage.h" - -#include "InstanceList.h" -#include "minecraft/legacy/LegacyInstance.h" -#include "minecraft/legacy/LegacyUpgradeTask.h" -#include "MultiMC.h" -#include "dialogs/CustomMessageBox.h" -#include "dialogs/ProgressDialog.h" - -LegacyUpgradePage::LegacyUpgradePage(InstancePtr inst, QWidget *parent) - : QWidget(parent), ui(new Ui::LegacyUpgradePage), m_inst(inst) -{ - ui->setupUi(this); -} - -LegacyUpgradePage::~LegacyUpgradePage() -{ - delete ui; -} - -void LegacyUpgradePage::runModalTask(Task *task) -{ - connect(task, &Task::failed, [this](QString reason) - { - CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Warning)->show(); - }); - ProgressDialog loadDialog(this); - loadDialog.setSkipButton(true, tr("Abort")); - if(loadDialog.execWithTask(task) == QDialog::Accepted) - { - m_container->requestClose(); - } -} - -void LegacyUpgradePage::on_upgradeButton_clicked() -{ - QString newName = tr("%1 (Migrated)").arg(m_inst->name()); - auto upgradeTask = new LegacyUpgradeTask(m_inst); - upgradeTask->setName(newName); - upgradeTask->setGroup(MMC->instances()->getInstanceGroup(m_inst->id())); - upgradeTask->setIcon(m_inst->iconKey()); - unique_qobject_ptr<Task> task(MMC->instances()->wrapInstanceTask(upgradeTask)); - runModalTask(task.get()); -} - -bool LegacyUpgradePage::shouldDisplay() const -{ - return !m_inst->isRunning(); -} diff --git a/application/pages/instance/LegacyUpgradePage.h b/application/pages/instance/LegacyUpgradePage.h deleted file mode 100644 index df34e33a..00000000 --- a/application/pages/instance/LegacyUpgradePage.h +++ /dev/null @@ -1,64 +0,0 @@ -/* 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. - */ - -#pragma once - -#include <QWidget> - -#include "minecraft/legacy/LegacyInstance.h" -#include "pages/BasePage.h" -#include <MultiMC.h> -#include "tasks/Task.h" - -namespace Ui -{ -class LegacyUpgradePage; -} - -class LegacyUpgradePage : public QWidget, public BasePage -{ - Q_OBJECT - -public: - explicit LegacyUpgradePage(InstancePtr inst, QWidget *parent = 0); - virtual ~LegacyUpgradePage(); - virtual QString displayName() const override - { - return tr("Upgrade"); - } - virtual QIcon icon() const override - { - return MMC->getThemedIcon("checkupdate"); - } - virtual QString id() const override - { - return "upgrade"; - } - virtual QString helpPage() const override - { - return "Legacy-upgrade"; - } - virtual bool shouldDisplay() const override; - -private slots: - void on_upgradeButton_clicked(); - -private: - void runModalTask(Task *task); - -private: - Ui::LegacyUpgradePage *ui; - InstancePtr m_inst; -}; diff --git a/application/pages/instance/LegacyUpgradePage.ui b/application/pages/instance/LegacyUpgradePage.ui deleted file mode 100644 index a94ee039..00000000 --- a/application/pages/instance/LegacyUpgradePage.ui +++ /dev/null @@ -1,47 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>LegacyUpgradePage</class> - <widget class="QWidget" name="LegacyUpgradePage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>546</width> - <height>405</height> - </rect> - </property> - <layout class="QVBoxLayout" name="verticalLayout_5"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QTextBrowser" name="textBrowser"> - <property name="html"> - <string><html><body><h1>Upgrade is required</h1><p>MultiMC now supports old Minecraft versions and all the required features in the new (OneSix) instance format. As a consequence, the old (Legacy) format has been entirely disabled and old instances need to be upgraded.</p><p>The upgrade will create a new instance with the same contents as the current one, in the new format. The original instance will remain untouched, in case anything goes wrong in the process.</p><p>Please report any issues on our <a href="https://github.com/MultiMC/MultiMC5/issues">github issues page</a>.</p><p>There is also a <a href="https://discord.gg/GtPmv93">discord channel for testing here</a>.</p></body></html></string> - </property> - <property name="openExternalLinks"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QCommandLinkButton" name="upgradeButton"> - <property name="text"> - <string>Upgrade the instance</string> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/application/pages/instance/LogPage.cpp b/application/pages/instance/LogPage.cpp deleted file mode 100644 index 3d2085c6..00000000 --- a/application/pages/instance/LogPage.cpp +++ /dev/null @@ -1,312 +0,0 @@ -#include "LogPage.h" -#include "ui_LogPage.h" - -#include "MultiMC.h" - -#include <QIcon> -#include <QScrollBar> -#include <QShortcut> - -#include "launch/LaunchTask.h" -#include <settings/Setting.h> -#include "GuiUtil.h" -#include <ColorCache.h> - -class LogFormatProxyModel : public QIdentityProxyModel -{ -public: - LogFormatProxyModel(QObject* parent = nullptr) : QIdentityProxyModel(parent) - { - } - QVariant data(const QModelIndex &index, int role) const override - { - switch(role) - { - case Qt::FontRole: - return m_font; - case Qt::TextColorRole: - { - MessageLevel::Enum level = (MessageLevel::Enum) QIdentityProxyModel::data(index, LogModel::LevelRole).toInt(); - return m_colors->getFront(level); - } - case Qt::BackgroundRole: - { - MessageLevel::Enum level = (MessageLevel::Enum) QIdentityProxyModel::data(index, LogModel::LevelRole).toInt(); - return m_colors->getBack(level); - } - default: - return QIdentityProxyModel::data(index, role); - } - } - - void setFont(QFont font) - { - m_font = font; - } - - void setColors(LogColorCache* colors) - { - m_colors.reset(colors); - } - - QModelIndex find(const QModelIndex &start, const QString &value, bool reverse) const - { - QModelIndex parentIndex = parent(start); - auto compare = [&](int r) -> QModelIndex - { - QModelIndex idx = index(r, start.column(), parentIndex); - if (!idx.isValid() || idx == start) - { - return QModelIndex(); - } - QVariant v = data(idx, Qt::DisplayRole); - QString t = v.toString(); - if (t.contains(value, Qt::CaseInsensitive)) - return idx; - return QModelIndex(); - }; - if(reverse) - { - int from = start.row(); - int to = 0; - - for (int i = 0; i < 2; ++i) - { - for (int r = from; (r >= to); --r) - { - auto idx = compare(r); - if(idx.isValid()) - return idx; - } - // prepare for the next iteration - from = rowCount() - 1; - to = start.row(); - } - } - else - { - int from = start.row(); - int to = rowCount(parentIndex); - - for (int i = 0; i < 2; ++i) - { - for (int r = from; (r < to); ++r) - { - auto idx = compare(r); - if(idx.isValid()) - return idx; - } - // prepare for the next iteration - from = 0; - to = start.row(); - } - } - return QModelIndex(); - } -private: - QFont m_font; - std::unique_ptr<LogColorCache> m_colors; -}; - -LogPage::LogPage(InstancePtr instance, QWidget *parent) - : QWidget(parent), ui(new Ui::LogPage), m_instance(instance) -{ - ui->setupUi(this); - ui->tabWidget->tabBar()->hide(); - - m_proxy = new LogFormatProxyModel(this); - // set up text colors in the log proxy and adapt them to the current theme foreground and background - { - auto origForeground = ui->text->palette().color(ui->text->foregroundRole()); - auto origBackground = ui->text->palette().color(ui->text->backgroundRole()); - m_proxy->setColors(new LogColorCache(origForeground, origBackground)); - } - - // set up fonts in the log proxy - { - QString fontFamily = MMC->settings()->get("ConsoleFont").toString(); - bool conversionOk = false; - int fontSize = MMC->settings()->get("ConsoleFontSize").toInt(&conversionOk); - if(!conversionOk) - { - fontSize = 11; - } - m_proxy->setFont(QFont(fontFamily, fontSize)); - } - - ui->text->setModel(m_proxy); - - // set up instance and launch process recognition - { - auto launchTask = m_instance->getLaunchTask(); - if(launchTask) - { - setInstanceLaunchTaskChanged(launchTask, true); - } - connect(m_instance.get(), &BaseInstance::launchTaskChanged, this, &LogPage::onInstanceLaunchTaskChanged); - } - - auto findShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this); - connect(findShortcut, SIGNAL(activated()), SLOT(findActivated())); - auto findNextShortcut = new QShortcut(QKeySequence(QKeySequence::FindNext), this); - connect(findNextShortcut, SIGNAL(activated()), SLOT(findNextActivated())); - connect(ui->searchBar, SIGNAL(returnPressed()), SLOT(on_findButton_clicked())); - auto findPreviousShortcut = new QShortcut(QKeySequence(QKeySequence::FindPrevious), this); - connect(findPreviousShortcut, SIGNAL(activated()), SLOT(findPreviousActivated())); -} - -LogPage::~LogPage() -{ - delete ui; -} - -void LogPage::modelStateToUI() -{ - if(m_model->wrapLines()) - { - ui->text->setWordWrap(true); - ui->wrapCheckbox->setCheckState(Qt::Checked); - } - else - { - ui->text->setWordWrap(false); - ui->wrapCheckbox->setCheckState(Qt::Unchecked); - } - if(m_model->suspended()) - { - ui->trackLogCheckbox->setCheckState(Qt::Unchecked); - } - else - { - ui->trackLogCheckbox->setCheckState(Qt::Checked); - } -} - -void LogPage::UIToModelState() -{ - if(!m_model) - { - return; - } - m_model->setLineWrap(ui->wrapCheckbox->checkState() == Qt::Checked); - m_model->suspend(ui->trackLogCheckbox->checkState() != Qt::Checked); -} - -void LogPage::setInstanceLaunchTaskChanged(shared_qobject_ptr<LaunchTask> proc, bool initial) -{ - m_process = proc; - if(m_process) - { - m_model = proc->getLogModel(); - m_proxy->setSourceModel(m_model.get()); - if(initial) - { - modelStateToUI(); - } - else - { - UIToModelState(); - } - } - else - { - m_proxy->setSourceModel(nullptr); - m_model.reset(); - } -} - -void LogPage::onInstanceLaunchTaskChanged(shared_qobject_ptr<LaunchTask> proc) -{ - setInstanceLaunchTaskChanged(proc, false); -} - -bool LogPage::apply() -{ - return true; -} - -bool LogPage::shouldDisplay() const -{ - return m_instance->isRunning() || m_proxy->rowCount() > 0; -} - -void LogPage::on_btnPaste_clicked() -{ - if(!m_model) - return; - - //FIXME: turn this into a proper task and move the upload logic out of GuiUtil! - m_model->append(MessageLevel::MultiMC, QString("MultiMC: Log upload triggered at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))); - auto url = GuiUtil::uploadPaste(m_model->toPlainText(), this); - if(!url.isEmpty()) - { - m_model->append(MessageLevel::MultiMC, QString("MultiMC: Log uploaded to: %1").arg(url)); - } - else - { - m_model->append(MessageLevel::Error, "MultiMC: Log upload failed!"); - } -} - -void LogPage::on_btnCopy_clicked() -{ - if(!m_model) - return; - m_model->append(MessageLevel::MultiMC, QString("Clipboard copy at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))); - GuiUtil::setClipboardText(m_model->toPlainText()); -} - -void LogPage::on_btnClear_clicked() -{ - if(!m_model) - return; - m_model->clear(); - m_container->refreshContainer(); -} - -void LogPage::on_btnBottom_clicked() -{ - ui->text->scrollToBottom(); -} - -void LogPage::on_trackLogCheckbox_clicked(bool checked) -{ - if(!m_model) - return; - m_model->suspend(!checked); -} - -void LogPage::on_wrapCheckbox_clicked(bool checked) -{ - ui->text->setWordWrap(checked); - if(!m_model) - return; - m_model->setLineWrap(checked); -} - -void LogPage::on_findButton_clicked() -{ - auto modifiers = QApplication::keyboardModifiers(); - bool reverse = modifiers & Qt::ShiftModifier; - ui->text->findNext(ui->searchBar->text(), reverse); -} - -void LogPage::findNextActivated() -{ - ui->text->findNext(ui->searchBar->text(), false); -} - -void LogPage::findPreviousActivated() -{ - ui->text->findNext(ui->searchBar->text(), true); -} - -void LogPage::findActivated() -{ - // focus the search bar if it doesn't have focus - if (!ui->searchBar->hasFocus()) - { - ui->searchBar->setFocus(); - ui->searchBar->selectAll(); - } -} diff --git a/application/pages/instance/LogPage.h b/application/pages/instance/LogPage.h deleted file mode 100644 index b0b0e04b..00000000 --- a/application/pages/instance/LogPage.h +++ /dev/null @@ -1,86 +0,0 @@ -/* 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. - */ - -#pragma once - -#include <QWidget> - -#include "BaseInstance.h" -#include "launch/LaunchTask.h" -#include "pages/BasePage.h" -#include <MultiMC.h> - -namespace Ui -{ -class LogPage; -} -class QTextCharFormat; -class LogFormatProxyModel; - -class LogPage : public QWidget, public BasePage -{ - Q_OBJECT - -public: - explicit LogPage(InstancePtr instance, QWidget *parent = 0); - virtual ~LogPage(); - virtual QString displayName() const override - { - return tr("Minecraft Log"); - } - virtual QIcon icon() const override - { - return MMC->getThemedIcon("log"); - } - virtual QString id() const override - { - return "console"; - } - virtual bool apply() override; - virtual QString helpPage() const override - { - return "Minecraft-Logs"; - } - virtual bool shouldDisplay() const override; - -private slots: - void on_btnPaste_clicked(); - void on_btnCopy_clicked(); - void on_btnClear_clicked(); - void on_btnBottom_clicked(); - - void on_trackLogCheckbox_clicked(bool checked); - void on_wrapCheckbox_clicked(bool checked); - - void on_findButton_clicked(); - void findActivated(); - void findNextActivated(); - void findPreviousActivated(); - - void onInstanceLaunchTaskChanged(shared_qobject_ptr<LaunchTask> proc); - -private: - void modelStateToUI(); - void UIToModelState(); - void setInstanceLaunchTaskChanged(shared_qobject_ptr<LaunchTask> proc, bool initial); - -private: - Ui::LogPage *ui; - InstancePtr m_instance; - shared_qobject_ptr<LaunchTask> m_process; - - LogFormatProxyModel * m_proxy; - shared_qobject_ptr <LogModel> m_model; -}; diff --git a/application/pages/instance/LogPage.ui b/application/pages/instance/LogPage.ui deleted file mode 100644 index 4843d7c3..00000000 --- a/application/pages/instance/LogPage.ui +++ /dev/null @@ -1,182 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>LogPage</class> - <widget class="QWidget" name="LogPage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>825</width> - <height>782</height> - </rect> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QTabWidget" name="tabWidget"> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="tab"> - <attribute name="title"> - <string notr="true">Tab 1</string> - </attribute> - <layout class="QGridLayout" name="gridLayout"> - <item row="1" column="0" colspan="5"> - <widget class="LogView" name="text"> - <property name="undoRedoEnabled"> - <bool>false</bool> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - <property name="plainText"> - <string notr="true"/> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - <property name="centerOnScroll"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="0" column="0" colspan="5"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QCheckBox" name="trackLogCheckbox"> - <property name="text"> - <string>Keep updating</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="wrapCheckbox"> - <property name="text"> - <string>Wrap lines</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="btnCopy"> - <property name="toolTip"> - <string>Copy the whole log into the clipboard</string> - </property> - <property name="text"> - <string>&Copy</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="btnPaste"> - <property name="toolTip"> - <string>Upload the log to paste.ee - it will stay online for a month</string> - </property> - <property name="text"> - <string>Upload</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="btnClear"> - <property name="toolTip"> - <string>Clear the log</string> - </property> - <property name="text"> - <string>Clear</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Search:</string> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QPushButton" name="findButton"> - <property name="text"> - <string>Find</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLineEdit" name="searchBar"/> - </item> - <item row="2" column="4"> - <widget class="QPushButton" name="btnBottom"> - <property name="toolTip"> - <string>Scroll all the way to bottom</string> - </property> - <property name="text"> - <string>Bottom</string> - </property> - </widget> - </item> - <item row="2" column="3"> - <widget class="Line" name="line"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - </widget> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>LogView</class> - <extends>QPlainTextEdit</extends> - <header>widgets/LogView.h</header> - </customwidget> - </customwidgets> - <tabstops> - <tabstop>tabWidget</tabstop> - <tabstop>trackLogCheckbox</tabstop> - <tabstop>wrapCheckbox</tabstop> - <tabstop>btnCopy</tabstop> - <tabstop>btnPaste</tabstop> - <tabstop>btnClear</tabstop> - <tabstop>text</tabstop> - <tabstop>searchBar</tabstop> - <tabstop>findButton</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/application/pages/instance/ModFolderPage.cpp b/application/pages/instance/ModFolderPage.cpp deleted file mode 100644 index 98f20e77..00000000 --- a/application/pages/instance/ModFolderPage.cpp +++ /dev/null @@ -1,363 +0,0 @@ -/* 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 "ModFolderPage.h" -#include "ui_ModFolderPage.h" - -#include <QMessageBox> -#include <QEvent> -#include <QKeyEvent> -#include <QAbstractItemModel> -#include <QMenu> - -#include "MultiMC.h" -#include "dialogs/CustomMessageBox.h" -#include <GuiUtil.h> -#include "minecraft/mod/ModFolderModel.h" -#include "minecraft/mod/Mod.h" -#include "minecraft/VersionFilterData.h" -#include "minecraft/PackProfile.h" -#include <DesktopServices.h> - -#include <QSortFilterProxyModel> -#include "Version.h" - -namespace { - // FIXME: wasteful - void RemoveThePrefix(QString & string) { - QRegularExpression regex(QStringLiteral("^(([Tt][Hh][eE])|([Tt][eE][Hh])) +")); - string.remove(regex); - string = string.trimmed(); - } -} - -class ModSortProxy : public QSortFilterProxyModel -{ -public: - explicit ModSortProxy(QObject *parent = 0) : QSortFilterProxyModel(parent) - { - } - -protected: - bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const override { - ModFolderModel *model = qobject_cast<ModFolderModel *>(sourceModel()); - if(!model) { - return false; - } - const auto &mod = model->at(source_row); - if(mod.name().contains(filterRegExp())) { - return true; - } - if(mod.description().contains(filterRegExp())) { - return true; - } - for(auto & author: mod.authors()) { - if (author.contains(filterRegExp())) { - return true; - } - } - return false; - } - - bool lessThan(const QModelIndex & source_left, const QModelIndex & source_right) const override - { - ModFolderModel *model = qobject_cast<ModFolderModel *>(sourceModel()); - if( - !model || - !source_left.isValid() || - !source_right.isValid() || - source_left.column() != source_right.column() - ) { - return QSortFilterProxyModel::lessThan(source_left, source_right); - } - - // we are now guaranteed to have two valid indexes in the same column... we love the provided invariants unconditionally and proceed. - - auto column = (ModFolderModel::Columns) source_left.column(); - bool invert = false; - switch(column) { - // GH-2550 - sort by enabled/disabled - case ModFolderModel::ActiveColumn: { - auto dataL = source_left.data(Qt::CheckStateRole).toBool(); - auto dataR = source_right.data(Qt::CheckStateRole).toBool(); - if(dataL != dataR) { - return dataL > dataR; - } - // fallthrough - invert = sortOrder() == Qt::DescendingOrder; - } - // GH-2722 - sort mod names in a way that discards "The" prefixes - case ModFolderModel::NameColumn: { - auto dataL = model->data(model->index(source_left.row(), ModFolderModel::NameColumn)).toString(); - RemoveThePrefix(dataL); - auto dataR = model->data(model->index(source_right.row(), ModFolderModel::NameColumn)).toString(); - RemoveThePrefix(dataR); - - auto less = dataL.compare(dataR, sortCaseSensitivity()); - if(less != 0) { - return invert ? (less > 0) : (less < 0); - } - // fallthrough - invert = sortOrder() == Qt::DescendingOrder; - } - // GH-2762 - sort versions by parsing them as versions - case ModFolderModel::VersionColumn: { - auto dataL = Version(model->data(model->index(source_left.row(), ModFolderModel::VersionColumn)).toString()); - auto dataR = Version(model->data(model->index(source_right.row(), ModFolderModel::VersionColumn)).toString()); - return invert ? (dataL > dataR) : (dataL < dataR); - } - default: { - return QSortFilterProxyModel::lessThan(source_left, source_right); - } - } - } -}; - -ModFolderPage::ModFolderPage( - BaseInstance *inst, - std::shared_ptr<ModFolderModel> mods, - QString id, - QString iconName, - QString displayName, - QString helpPage, - QWidget *parent -) : - QMainWindow(parent), - ui(new Ui::ModFolderPage) -{ - ui->setupUi(this); - ui->actionsToolbar->insertSpacer(ui->actionView_configs); - - m_inst = inst; - on_RunningState_changed(m_inst && m_inst->isRunning()); - m_mods = mods; - m_id = id; - m_displayName = displayName; - m_iconName = iconName; - m_helpName = helpPage; - m_fileSelectionFilter = "%1 (*.zip *.jar)"; - m_filterModel = new ModSortProxy(this); - m_filterModel->setDynamicSortFilter(true); - m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive); - m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive); - m_filterModel->setSourceModel(m_mods.get()); - m_filterModel->setFilterKeyColumn(-1); - ui->modTreeView->setModel(m_filterModel); - ui->modTreeView->installEventFilter(this); - ui->modTreeView->sortByColumn(1, Qt::AscendingOrder); - ui->modTreeView->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->modTreeView, &ModListView::customContextMenuRequested, this, &ModFolderPage::ShowContextMenu); - connect(ui->modTreeView, &ModListView::activated, this, &ModFolderPage::modItemActivated); - - auto smodel = ui->modTreeView->selectionModel(); - connect(smodel, &QItemSelectionModel::currentChanged, this, &ModFolderPage::modCurrent); - connect(ui->filterEdit, &QLineEdit::textChanged, this, &ModFolderPage::on_filterTextChanged); - connect(m_inst, &BaseInstance::runningStatusChanged, this, &ModFolderPage::on_RunningState_changed); -} - -void ModFolderPage::modItemActivated(const QModelIndex&) -{ - if(!m_controlsEnabled) { - return; - } - auto selection = m_filterModel->mapSelectionToSource(ui->modTreeView->selectionModel()->selection()); - m_mods->setModStatus(selection.indexes(), ModFolderModel::Toggle); -} - -QMenu * ModFolderPage::createPopupMenu() -{ - QMenu* filteredMenu = QMainWindow::createPopupMenu(); - filteredMenu->removeAction(ui->actionsToolbar->toggleViewAction() ); - return filteredMenu; -} - -void ModFolderPage::ShowContextMenu(const QPoint& pos) -{ - auto menu = ui->actionsToolbar->createContextMenu(this, tr("Context menu")); - menu->exec(ui->modTreeView->mapToGlobal(pos)); - delete menu; -} - -void ModFolderPage::openedImpl() -{ - m_mods->startWatching(); -} - -void ModFolderPage::closedImpl() -{ - m_mods->stopWatching(); -} - -void ModFolderPage::on_filterTextChanged(const QString& newContents) -{ - m_viewFilter = newContents; - m_filterModel->setFilterFixedString(m_viewFilter); -} - - -CoreModFolderPage::CoreModFolderPage(BaseInstance *inst, std::shared_ptr<ModFolderModel> mods, - QString id, QString iconName, QString displayName, - QString helpPage, QWidget *parent) - : ModFolderPage(inst, mods, id, iconName, displayName, helpPage, parent) -{ -} - -ModFolderPage::~ModFolderPage() -{ - m_mods->stopWatching(); - delete ui; -} - -void ModFolderPage::on_RunningState_changed(bool running) -{ - if(m_controlsEnabled == !running) { - return; - } - m_controlsEnabled = !running; - ui->actionAdd->setEnabled(m_controlsEnabled); - ui->actionDisable->setEnabled(m_controlsEnabled); - ui->actionEnable->setEnabled(m_controlsEnabled); - ui->actionRemove->setEnabled(m_controlsEnabled); -} - -bool ModFolderPage::shouldDisplay() const -{ - return true; -} - -bool CoreModFolderPage::shouldDisplay() const -{ - if (ModFolderPage::shouldDisplay()) - { - auto inst = dynamic_cast<MinecraftInstance *>(m_inst); - if (!inst) - return true; - auto version = inst->getPackProfile(); - if (!version) - return true; - if(!version->getComponent("net.minecraftforge")) - { - return false; - } - if(!version->getComponent("net.minecraft")) - { - return false; - } - if(version->getComponent("net.minecraft")->getReleaseDateTime() < g_VersionFilterData.legacyCutoffDate) - { - return true; - } - } - return false; -} - -bool ModFolderPage::modListFilter(QKeyEvent *keyEvent) -{ - switch (keyEvent->key()) - { - case Qt::Key_Delete: - on_actionRemove_triggered(); - return true; - case Qt::Key_Plus: - on_actionAdd_triggered(); - return true; - default: - break; - } - return QWidget::eventFilter(ui->modTreeView, keyEvent); -} - -bool ModFolderPage::eventFilter(QObject *obj, QEvent *ev) -{ - if (ev->type() != QEvent::KeyPress) - { - return QWidget::eventFilter(obj, ev); - } - QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev); - if (obj == ui->modTreeView) - return modListFilter(keyEvent); - return QWidget::eventFilter(obj, ev); -} - -void ModFolderPage::on_actionAdd_triggered() -{ - if(!m_controlsEnabled) { - return; - } - auto list = GuiUtil::BrowseForFiles( - m_helpName, - tr("Select %1", - "Select whatever type of files the page contains. Example: 'Loader Mods'") - .arg(m_displayName), - m_fileSelectionFilter.arg(m_displayName), MMC->settings()->get("CentralModsDir").toString(), - this->parentWidget()); - if (!list.empty()) - { - for (auto filename : list) - { - m_mods->installMod(filename); - } - } -} - -void ModFolderPage::on_actionEnable_triggered() -{ - if(!m_controlsEnabled) { - return; - } - auto selection = m_filterModel->mapSelectionToSource(ui->modTreeView->selectionModel()->selection()); - m_mods->setModStatus(selection.indexes(), ModFolderModel::Enable); -} - -void ModFolderPage::on_actionDisable_triggered() -{ - if(!m_controlsEnabled) { - return; - } - auto selection = m_filterModel->mapSelectionToSource(ui->modTreeView->selectionModel()->selection()); - m_mods->setModStatus(selection.indexes(), ModFolderModel::Disable); -} - -void ModFolderPage::on_actionRemove_triggered() -{ - if(!m_controlsEnabled) { - return; - } - auto selection = m_filterModel->mapSelectionToSource(ui->modTreeView->selectionModel()->selection()); - m_mods->deleteMods(selection.indexes()); -} - -void ModFolderPage::on_actionView_configs_triggered() -{ - DesktopServices::openDirectory(m_inst->instanceConfigFolder(), true); -} - -void ModFolderPage::on_actionView_Folder_triggered() -{ - DesktopServices::openDirectory(m_mods->dir().absolutePath(), true); -} - -void ModFolderPage::modCurrent(const QModelIndex ¤t, const QModelIndex &previous) -{ - if (!current.isValid()) - { - ui->frame->clear(); - return; - } - auto sourceCurrent = m_filterModel->mapToSource(current); - int row = sourceCurrent.row(); - Mod &m = m_mods->operator[](row); - ui->frame->updateWithMod(m); -} diff --git a/application/pages/instance/ModFolderPage.h b/application/pages/instance/ModFolderPage.h deleted file mode 100644 index f653a8c0..00000000 --- a/application/pages/instance/ModFolderPage.h +++ /dev/null @@ -1,119 +0,0 @@ -/* 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. - */ - -#pragma once - -#include <QMainWindow> - -#include "minecraft/MinecraftInstance.h" -#include "pages/BasePage.h" -#include <MultiMC.h> - -class ModFolderModel; -namespace Ui -{ -class ModFolderPage; -} - -class ModFolderPage : public QMainWindow, public BasePage -{ - Q_OBJECT - -public: - explicit ModFolderPage( - BaseInstance *inst, - std::shared_ptr<ModFolderModel> mods, - QString id, - QString iconName, - QString displayName, - QString helpPage = "", - QWidget *parent = 0 - ); - virtual ~ModFolderPage(); - - void setFilter(const QString & filter) - { - m_fileSelectionFilter = filter; - } - - virtual QString displayName() const override - { - return m_displayName; - } - virtual QIcon icon() const override - { - return MMC->getThemedIcon(m_iconName); - } - virtual QString id() const override - { - return m_id; - } - virtual QString helpPage() const override - { - return m_helpName; - } - virtual bool shouldDisplay() const override; - - virtual void openedImpl() override; - virtual void closedImpl() override; -protected: - bool eventFilter(QObject *obj, QEvent *ev) override; - bool modListFilter(QKeyEvent *ev); - QMenu * createPopupMenu() override; - -protected: - BaseInstance *m_inst = nullptr; - -protected: - Ui::ModFolderPage *ui = nullptr; - std::shared_ptr<ModFolderModel> m_mods; - QSortFilterProxyModel *m_filterModel = nullptr; - QString m_iconName; - QString m_id; - QString m_displayName; - QString m_helpName; - QString m_fileSelectionFilter; - QString m_viewFilter; - bool m_controlsEnabled = true; - -public -slots: - void modCurrent(const QModelIndex ¤t, const QModelIndex &previous); - -private -slots: - void modItemActivated(const QModelIndex &index); - void on_filterTextChanged(const QString & newContents); - void on_RunningState_changed(bool running); - void on_actionAdd_triggered(); - void on_actionRemove_triggered(); - void on_actionEnable_triggered(); - void on_actionDisable_triggered(); - void on_actionView_Folder_triggered(); - void on_actionView_configs_triggered(); - void ShowContextMenu(const QPoint &pos); -}; - -class CoreModFolderPage : public ModFolderPage -{ -public: - explicit CoreModFolderPage(BaseInstance *inst, std::shared_ptr<ModFolderModel> mods, QString id, - QString iconName, QString displayName, QString helpPage = "", - QWidget *parent = 0); - virtual ~CoreModFolderPage() - { - } - virtual bool shouldDisplay() const; -}; diff --git a/application/pages/instance/ModFolderPage.ui b/application/pages/instance/ModFolderPage.ui deleted file mode 100644 index 954a0167..00000000 --- a/application/pages/instance/ModFolderPage.ui +++ /dev/null @@ -1,164 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>ModFolderPage</class> - <widget class="QMainWindow" name="ModFolderPage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>1042</width> - <height>501</height> - </rect> - </property> - <widget class="QWidget" name="centralwidget"> - <layout class="QGridLayout" name="gridLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item row="4" column="1" colspan="3"> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="1"> - <widget class="QLineEdit" name="filterEdit"> - <property name="clearButtonEnabled"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="filterLabel"> - <property name="text"> - <string>Filter:</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="2" column="1" colspan="3"> - <widget class="MCModInfoFrame" name="frame"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item row="1" column="1" colspan="3"> - <widget class="ModListView" name="modTreeView"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="acceptDrops"> - <bool>true</bool> - </property> - <property name="dragDropMode"> - <enum>QAbstractItemView::DropOnly</enum> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="WideBar" name="actionsToolbar"> - <property name="windowTitle"> - <string>Actions</string> - </property> - <property name="toolButtonStyle"> - <enum>Qt::ToolButtonTextOnly</enum> - </property> - <attribute name="toolBarArea"> - <enum>RightToolBarArea</enum> - </attribute> - <attribute name="toolBarBreak"> - <bool>false</bool> - </attribute> - <addaction name="actionAdd"/> - <addaction name="separator"/> - <addaction name="actionRemove"/> - <addaction name="actionEnable"/> - <addaction name="actionDisable"/> - <addaction name="actionView_configs"/> - <addaction name="actionView_Folder"/> - </widget> - <action name="actionAdd"> - <property name="text"> - <string>&Add</string> - </property> - <property name="toolTip"> - <string>Add mods</string> - </property> - </action> - <action name="actionRemove"> - <property name="text"> - <string>&Remove</string> - </property> - <property name="toolTip"> - <string>Remove selected mods</string> - </property> - </action> - <action name="actionEnable"> - <property name="text"> - <string>&Enable</string> - </property> - <property name="toolTip"> - <string>Enable selected mods</string> - </property> - </action> - <action name="actionDisable"> - <property name="text"> - <string>&Disable</string> - </property> - <property name="toolTip"> - <string>Disable selected mods</string> - </property> - </action> - <action name="actionView_configs"> - <property name="text"> - <string>View &Configs</string> - </property> - <property name="toolTip"> - <string>Open the 'config' folder in the system file manager.</string> - </property> - </action> - <action name="actionView_Folder"> - <property name="text"> - <string>View &Folder</string> - </property> - </action> - </widget> - <customwidgets> - <customwidget> - <class>ModListView</class> - <extends>QTreeView</extends> - <header>widgets/ModListView.h</header> - </customwidget> - <customwidget> - <class>MCModInfoFrame</class> - <extends>QFrame</extends> - <header>widgets/MCModInfoFrame.h</header> - <container>1</container> - </customwidget> - <customwidget> - <class>WideBar</class> - <extends>QToolBar</extends> - <header>widgets/WideBar.h</header> - </customwidget> - </customwidgets> - <tabstops> - <tabstop>modTreeView</tabstop> - <tabstop>filterEdit</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/application/pages/instance/NotesPage.cpp b/application/pages/instance/NotesPage.cpp deleted file mode 100644 index fa966c91..00000000 --- a/application/pages/instance/NotesPage.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "NotesPage.h" -#include "ui_NotesPage.h" -#include <QTabBar> - -NotesPage::NotesPage(BaseInstance *inst, QWidget *parent) - : QWidget(parent), ui(new Ui::NotesPage), m_inst(inst) -{ - ui->setupUi(this); - ui->noteEditor->setText(m_inst->notes()); -} - -NotesPage::~NotesPage() -{ - delete ui; -} - -bool NotesPage::apply() -{ - m_inst->setNotes(ui->noteEditor->toPlainText()); - return true; -} diff --git a/application/pages/instance/NotesPage.h b/application/pages/instance/NotesPage.h deleted file mode 100644 index d0c00ac1..00000000 --- a/application/pages/instance/NotesPage.h +++ /dev/null @@ -1,60 +0,0 @@ -/* 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. - */ - -#pragma once - -#include <QWidget> - -#include "BaseInstance.h" -#include "pages/BasePage.h" -#include <MultiMC.h> - -namespace Ui -{ -class NotesPage; -} - -class NotesPage : public QWidget, public BasePage -{ - Q_OBJECT - -public: - explicit NotesPage(BaseInstance *inst, QWidget *parent = 0); - virtual ~NotesPage(); - virtual QString displayName() const override - { - return tr("Notes"); - } - virtual QIcon icon() const override - { - auto icon = MMC->getThemedIcon("notes"); - if(icon.isNull()) - icon = MMC->getThemedIcon("news"); - return icon; - } - virtual QString id() const override - { - return "notes"; - } - virtual bool apply() override; - virtual QString helpPage() const override - { - return "Notes"; - } - -private: - Ui::NotesPage *ui; - BaseInstance *m_inst; -}; diff --git a/application/pages/instance/NotesPage.ui b/application/pages/instance/NotesPage.ui deleted file mode 100644 index 67cb261c..00000000 --- a/application/pages/instance/NotesPage.ui +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>NotesPage</class> - <widget class="QWidget" name="NotesPage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>731</width> - <height>538</height> - </rect> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QTextEdit" name="noteEditor"> - <property name="verticalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOn</enum> - </property> - <property name="tabChangesFocus"> - <bool>true</bool> - </property> - <property name="acceptRichText"> - <bool>false</bool> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextEditable|Qt::TextEditorInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>noteEditor</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/application/pages/instance/OtherLogsPage.cpp b/application/pages/instance/OtherLogsPage.cpp deleted file mode 100644 index b67b84bd..00000000 --- a/application/pages/instance/OtherLogsPage.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* 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 "OtherLogsPage.h" -#include "ui_OtherLogsPage.h" - -#include <QMessageBox> - -#include "GuiUtil.h" -#include "RecursiveFileSystemWatcher.h" -#include <GZip.h> -#include <FileSystem.h> -#include <QShortcut> - -OtherLogsPage::OtherLogsPage(QString path, IPathMatcher::Ptr fileFilter, QWidget *parent) - : QWidget(parent), ui(new Ui::OtherLogsPage), m_path(path), m_fileFilter(fileFilter), - m_watcher(new RecursiveFileSystemWatcher(this)) -{ - ui->setupUi(this); - ui->tabWidget->tabBar()->hide(); - - m_watcher->setMatcher(fileFilter); - m_watcher->setRootDir(QDir::current().absoluteFilePath(m_path)); - - connect(m_watcher, &RecursiveFileSystemWatcher::filesChanged, this, &OtherLogsPage::populateSelectLogBox); - populateSelectLogBox(); - - auto findShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this); - connect(findShortcut, &QShortcut::activated, this, &OtherLogsPage::findActivated); - - auto findNextShortcut = new QShortcut(QKeySequence(QKeySequence::FindNext), this); - connect(findNextShortcut, &QShortcut::activated, this, &OtherLogsPage::findNextActivated); - - auto findPreviousShortcut = new QShortcut(QKeySequence(QKeySequence::FindPrevious), this); - connect(findPreviousShortcut, &QShortcut::activated, this, &OtherLogsPage::findPreviousActivated); - - connect(ui->searchBar, &QLineEdit::returnPressed, this, &OtherLogsPage::on_findButton_clicked); -} - -OtherLogsPage::~OtherLogsPage() -{ - delete ui; -} - -void OtherLogsPage::openedImpl() -{ - m_watcher->enable(); -} -void OtherLogsPage::closedImpl() -{ - m_watcher->disable(); -} - -void OtherLogsPage::populateSelectLogBox() -{ - ui->selectLogBox->clear(); - ui->selectLogBox->addItems(m_watcher->files()); - if (m_currentFile.isEmpty()) - { - setControlsEnabled(false); - ui->selectLogBox->setCurrentIndex(-1); - } - else - { - const int index = ui->selectLogBox->findText(m_currentFile); - if (index != -1) - { - ui->selectLogBox->setCurrentIndex(index); - setControlsEnabled(true); - } - else - { - setControlsEnabled(false); - } - } -} - -void OtherLogsPage::on_selectLogBox_currentIndexChanged(const int index) -{ - QString file; - if (index != -1) - { - file = ui->selectLogBox->itemText(index); - } - - if (file.isEmpty() || !QFile::exists(FS::PathCombine(m_path, file))) - { - m_currentFile = QString(); - ui->text->clear(); - setControlsEnabled(false); - } - else - { - m_currentFile = file; - on_btnReload_clicked(); - setControlsEnabled(true); - } -} - -void OtherLogsPage::on_btnReload_clicked() -{ - if(m_currentFile.isEmpty()) - { - setControlsEnabled(false); - return; - } - QFile file(FS::PathCombine(m_path, m_currentFile)); - if (!file.open(QFile::ReadOnly)) - { - setControlsEnabled(false); - ui->btnReload->setEnabled(true); // allow reload - m_currentFile = QString(); - QMessageBox::critical(this, tr("Error"), tr("Unable to open %1 for reading: %2") - .arg(m_currentFile, file.errorString())); - } - else - { - auto setPlainText = [&](const QString & text) - { - QString fontFamily = MMC->settings()->get("ConsoleFont").toString(); - bool conversionOk = false; - int fontSize = MMC->settings()->get("ConsoleFontSize").toInt(&conversionOk); - if(!conversionOk) - { - fontSize = 11; - } - QTextDocument *doc = ui->text->document(); - doc->setDefaultFont(QFont(fontFamily, fontSize)); - ui->text->setPlainText(text); - }; - auto showTooBig = [&]() - { - setPlainText( - tr("The file (%1) is too big. You may want to open it in a viewer optimized " - "for large files.").arg(file.fileName())); - }; - if(file.size() > (1024ll * 1024ll * 12ll)) - { - showTooBig(); - return; - } - QString content; - if(file.fileName().endsWith(".gz")) - { - QByteArray temp; - if(!GZip::unzip(file.readAll(), temp)) - { - setPlainText( - tr("The file (%1) is not readable.").arg(file.fileName())); - return; - } - content = QString::fromUtf8(temp); - } - else - { - content = QString::fromUtf8(file.readAll()); - } - if (content.size() >= 50000000ll) - { - showTooBig(); - return; - } - setPlainText(content); - } -} - -void OtherLogsPage::on_btnPaste_clicked() -{ - GuiUtil::uploadPaste(ui->text->toPlainText(), this); -} - -void OtherLogsPage::on_btnCopy_clicked() -{ - GuiUtil::setClipboardText(ui->text->toPlainText()); -} - -void OtherLogsPage::on_btnDelete_clicked() -{ - if(m_currentFile.isEmpty()) - { - setControlsEnabled(false); - return; - } - if (QMessageBox::question(this, tr("Delete"), - tr("Do you really want to delete %1?").arg(m_currentFile), - QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) - { - return; - } - QFile file(FS::PathCombine(m_path, m_currentFile)); - if (!file.remove()) - { - QMessageBox::critical(this, tr("Error"), tr("Unable to delete %1: %2") - .arg(m_currentFile, file.errorString())); - } -} - - - -void OtherLogsPage::on_btnClean_clicked() -{ - auto toDelete = m_watcher->files(); - if(toDelete.isEmpty()) - { - return; - } - QMessageBox *messageBox = new QMessageBox(this); - messageBox->setWindowTitle(tr("Clean up")); - if(toDelete.size() > 5) - { - messageBox->setText(tr("Do you really want to delete all log files?")); - messageBox->setDetailedText(toDelete.join('\n')); - } - else - { - messageBox->setText(tr("Do you really want to delete these files?\n%1").arg(toDelete.join('\n'))); - } - messageBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); - messageBox->setDefaultButton(QMessageBox::Ok); - messageBox->setTextInteractionFlags(Qt::TextSelectableByMouse); - messageBox->setIcon(QMessageBox::Question); - messageBox->setTextInteractionFlags(Qt::TextBrowserInteraction); - - if (messageBox->exec() != QMessageBox::Ok) - { - return; - } - QStringList failed; - for(auto item: toDelete) - { - QFile file(FS::PathCombine(m_path, item)); - if (!file.remove()) - { - failed.push_back(item); - } - } - if(!failed.empty()) - { - QMessageBox *messageBox = new QMessageBox(this); - messageBox->setWindowTitle(tr("Error")); - if(failed.size() > 5) - { - messageBox->setText(tr("Couldn't delete some files!")); - messageBox->setDetailedText(failed.join('\n')); - } - else - { - messageBox->setText(tr("Couldn't delete some files:\n%1").arg(failed.join('\n'))); - } - messageBox->setStandardButtons(QMessageBox::Ok); - messageBox->setDefaultButton(QMessageBox::Ok); - messageBox->setTextInteractionFlags(Qt::TextSelectableByMouse); - messageBox->setIcon(QMessageBox::Critical); - messageBox->setTextInteractionFlags(Qt::TextBrowserInteraction); - messageBox->exec(); - } -} - - -void OtherLogsPage::setControlsEnabled(const bool enabled) -{ - ui->btnReload->setEnabled(enabled); - ui->btnDelete->setEnabled(enabled); - ui->btnCopy->setEnabled(enabled); - ui->btnPaste->setEnabled(enabled); - ui->text->setEnabled(enabled); - ui->btnClean->setEnabled(enabled); -} - -// FIXME: HACK, use LogView instead? -static void findNext(QPlainTextEdit * _this, const QString& what, bool reverse) -{ - _this->find(what, reverse ? QTextDocument::FindFlag::FindBackward : QTextDocument::FindFlag(0)); -} - -void OtherLogsPage::on_findButton_clicked() -{ - auto modifiers = QApplication::keyboardModifiers(); - bool reverse = modifiers & Qt::ShiftModifier; - findNext(ui->text, ui->searchBar->text(), reverse); -} - -void OtherLogsPage::findNextActivated() -{ - findNext(ui->text, ui->searchBar->text(), false); -} - -void OtherLogsPage::findPreviousActivated() -{ - findNext(ui->text, ui->searchBar->text(), true); -} - -void OtherLogsPage::findActivated() -{ - // focus the search bar if it doesn't have focus - if (!ui->searchBar->hasFocus()) - { - ui->searchBar->setFocus(); - ui->searchBar->selectAll(); - } -} diff --git a/application/pages/instance/OtherLogsPage.h b/application/pages/instance/OtherLogsPage.h deleted file mode 100644 index 7f21c0fa..00000000 --- a/application/pages/instance/OtherLogsPage.h +++ /dev/null @@ -1,81 +0,0 @@ -/* 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. - */ - -#pragma once - -#include <QWidget> - -#include "pages/BasePage.h" -#include <MultiMC.h> -#include <pathmatcher/IPathMatcher.h> - -namespace Ui -{ -class OtherLogsPage; -} - -class RecursiveFileSystemWatcher; - -class OtherLogsPage : public QWidget, public BasePage -{ - Q_OBJECT - -public: - explicit OtherLogsPage(QString path, IPathMatcher::Ptr fileFilter, QWidget *parent = 0); - ~OtherLogsPage(); - - QString id() const override - { - return "logs"; - } - QString displayName() const override - { - return tr("Other logs"); - } - QIcon icon() const override - { - return MMC->getThemedIcon("log"); - } - QString helpPage() const override - { - return "Minecraft-Logs"; - } - void openedImpl() override; - void closedImpl() override; - -private slots: - void populateSelectLogBox(); - void on_selectLogBox_currentIndexChanged(const int index); - void on_btnReload_clicked(); - void on_btnPaste_clicked(); - void on_btnCopy_clicked(); - void on_btnDelete_clicked(); - void on_btnClean_clicked(); - - void on_findButton_clicked(); - void findActivated(); - void findNextActivated(); - void findPreviousActivated(); - -private: - void setControlsEnabled(const bool enabled); - -private: - Ui::OtherLogsPage *ui; - QString m_path; - QString m_currentFile; - IPathMatcher::Ptr m_fileFilter; - RecursiveFileSystemWatcher *m_watcher; -}; diff --git a/application/pages/instance/OtherLogsPage.ui b/application/pages/instance/OtherLogsPage.ui deleted file mode 100644 index 56ff3b62..00000000 --- a/application/pages/instance/OtherLogsPage.ui +++ /dev/null @@ -1,150 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>OtherLogsPage</class> - <widget class="QWidget" name="OtherLogsPage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>657</width> - <height>538</height> - </rect> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QTabWidget" name="tabWidget"> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="tab"> - <attribute name="title"> - <string notr="true">Tab 1</string> - </attribute> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="2" column="1"> - <widget class="QLineEdit" name="searchBar"/> - </item> - <item row="2" column="2"> - <widget class="QPushButton" name="findButton"> - <property name="text"> - <string>Find</string> - </property> - </widget> - </item> - <item row="1" column="0" colspan="4"> - <widget class="QPlainTextEdit" name="text"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="verticalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOn</enum> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="0" column="0" colspan="4"> - <layout class="QGridLayout" name="gridLayout"> - <item row="3" column="1"> - <widget class="QPushButton" name="btnCopy"> - <property name="toolTip"> - <string>Copy the whole log into the clipboard</string> - </property> - <property name="text"> - <string>&Copy</string> - </property> - </widget> - </item> - <item row="3" column="3"> - <widget class="QPushButton" name="btnDelete"> - <property name="toolTip"> - <string>Clear the log</string> - </property> - <property name="text"> - <string>Delete</string> - </property> - </widget> - </item> - <item row="3" column="2"> - <widget class="QPushButton" name="btnPaste"> - <property name="toolTip"> - <string>Upload the log to paste.ee - it will stay online for a month</string> - </property> - <property name="text"> - <string>Upload</string> - </property> - </widget> - </item> - <item row="3" column="4"> - <widget class="QPushButton" name="btnClean"> - <property name="toolTip"> - <string>Clear the log</string> - </property> - <property name="text"> - <string>Clean</string> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QPushButton" name="btnReload"> - <property name="text"> - <string>Reload</string> - </property> - </widget> - </item> - <item row="0" column="0" colspan="5"> - <widget class="QComboBox" name="selectLogBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - </layout> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Search:</string> - </property> - </widget> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>tabWidget</tabstop> - <tabstop>selectLogBox</tabstop> - <tabstop>btnReload</tabstop> - <tabstop>btnCopy</tabstop> - <tabstop>btnPaste</tabstop> - <tabstop>btnDelete</tabstop> - <tabstop>btnClean</tabstop> - <tabstop>text</tabstop> - <tabstop>searchBar</tabstop> - <tabstop>findButton</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/application/pages/instance/ResourcePackPage.h b/application/pages/instance/ResourcePackPage.h deleted file mode 100644 index 1486bf52..00000000 --- a/application/pages/instance/ResourcePackPage.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "ModFolderPage.h" -#include "ui_ModFolderPage.h" - -class ResourcePackPage : public ModFolderPage -{ - Q_OBJECT -public: - explicit ResourcePackPage(MinecraftInstance *instance, QWidget *parent = 0) - : ModFolderPage(instance, instance->resourcePackList(), "resourcepacks", - "resourcepacks", tr("Resource packs"), "Resource-packs", parent) - { - ui->actionView_configs->setVisible(false); - } - virtual ~ResourcePackPage() {} - - virtual bool shouldDisplay() const override - { - return !m_inst->traits().contains("no-texturepacks") && - !m_inst->traits().contains("texturepacks"); - } -}; diff --git a/application/pages/instance/ScreenshotsPage.cpp b/application/pages/instance/ScreenshotsPage.cpp deleted file mode 100644 index efa0f9f2..00000000 --- a/application/pages/instance/ScreenshotsPage.cpp +++ /dev/null @@ -1,422 +0,0 @@ -#include "ScreenshotsPage.h" -#include "ui_ScreenshotsPage.h" - -#include <QModelIndex> -#include <QMutableListIterator> -#include <QMap> -#include <QSet> -#include <QFileIconProvider> -#include <QFileSystemModel> -#include <QStyledItemDelegate> -#include <QLineEdit> -#include <QEvent> -#include <QPainter> -#include <QClipboard> -#include <QKeyEvent> -#include <QMenu> - -#include <MultiMC.h> - -#include "dialogs/ProgressDialog.h" -#include "dialogs/CustomMessageBox.h" -#include "net/NetJob.h" -#include "screenshots/ImgurUpload.h" -#include "screenshots/ImgurAlbumCreation.h" -#include "tasks/SequentialTask.h" - -#include "RWStorage.h" -#include <FileSystem.h> -#include <DesktopServices.h> - -typedef RWStorage<QString, QIcon> SharedIconCache; -typedef std::shared_ptr<SharedIconCache> SharedIconCachePtr; - -class ThumbnailingResult : public QObject -{ - Q_OBJECT -public slots: - inline void emitResultsReady(const QString &path) { emit resultsReady(path); } - inline void emitResultsFailed(const QString &path) { emit resultsFailed(path); } -signals: - void resultsReady(const QString &path); - void resultsFailed(const QString &path); -}; - -class ThumbnailRunnable : public QRunnable -{ -public: - ThumbnailRunnable(QString path, SharedIconCachePtr cache) - { - m_path = path; - m_cache = cache; - } - void run() - { - QFileInfo info(m_path); - if (info.isDir()) - return; - if ((info.suffix().compare("png", Qt::CaseInsensitive) != 0)) - return; - int tries = 5; - while (tries) - { - if (!m_cache->stale(m_path)) - return; - QImage image(m_path); - if (image.isNull()) - { - QThread::msleep(500); - tries--; - continue; - } - QImage small; - if (image.width() > image.height()) - small = image.scaledToWidth(512).scaledToWidth(256, Qt::SmoothTransformation); - else - small = image.scaledToHeight(512).scaledToHeight(256, Qt::SmoothTransformation); - QPoint offset((256 - small.width()) / 2, (256 - small.height()) / 2); - QImage square(QSize(256, 256), QImage::Format_ARGB32); - square.fill(Qt::transparent); - - QPainter painter(&square); - painter.drawImage(offset, small); - painter.end(); - - QIcon icon(QPixmap::fromImage(square)); - m_cache->add(m_path, icon); - m_resultEmitter.emitResultsReady(m_path); - return; - } - m_resultEmitter.emitResultsFailed(m_path); - } - QString m_path; - SharedIconCachePtr m_cache; - ThumbnailingResult m_resultEmitter; -}; - -// this is about as elegant and well written as a bag of bricks with scribbles done by insane -// asylum patients. -class FilterModel : public QIdentityProxyModel -{ - Q_OBJECT -public: - explicit FilterModel(QObject *parent = 0) : QIdentityProxyModel(parent) - { - m_thumbnailingPool.setMaxThreadCount(4); - m_thumbnailCache = std::make_shared<SharedIconCache>(); - m_thumbnailCache->add("placeholder", MMC->getThemedIcon("screenshot-placeholder")); - connect(&watcher, SIGNAL(fileChanged(QString)), SLOT(fileChanged(QString))); - // FIXME: the watched file set is not updated when files are removed - } - virtual ~FilterModel() { m_thumbnailingPool.waitForDone(500); } - virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const - { - auto model = sourceModel(); - if (!model) - return QVariant(); - if (role == Qt::DisplayRole || role == Qt::EditRole) - { - QVariant result = sourceModel()->data(mapToSource(proxyIndex), role); - return result.toString().remove(QRegExp("\\.png$")); - } - if (role == Qt::DecorationRole) - { - QVariant result = - sourceModel()->data(mapToSource(proxyIndex), QFileSystemModel::FilePathRole); - QString filePath = result.toString(); - QIcon temp; - if (!watched.contains(filePath)) - { - ((QFileSystemWatcher &)watcher).addPath(filePath); - ((QSet<QString> &)watched).insert(filePath); - } - if (m_thumbnailCache->get(filePath, temp)) - { - return temp; - } - if (!m_failed.contains(filePath)) - { - ((FilterModel *)this)->thumbnailImage(filePath); - } - return (m_thumbnailCache->get("placeholder")); - } - return sourceModel()->data(mapToSource(proxyIndex), role); - } - virtual bool setData(const QModelIndex &index, const QVariant &value, - int role = Qt::EditRole) - { - auto model = sourceModel(); - if (!model) - return false; - if (role != Qt::EditRole) - return false; - // FIXME: this is a workaround for a bug in QFileSystemModel, where it doesn't - // sort after renames - { - ((QFileSystemModel *)model)->setNameFilterDisables(true); - ((QFileSystemModel *)model)->setNameFilterDisables(false); - } - return model->setData(mapToSource(index), value.toString() + ".png", role); - } - -private: - void thumbnailImage(QString path) - { - auto runnable = new ThumbnailRunnable(path, m_thumbnailCache); - connect(&(runnable->m_resultEmitter), SIGNAL(resultsReady(QString)), - SLOT(thumbnailReady(QString))); - connect(&(runnable->m_resultEmitter), SIGNAL(resultsFailed(QString)), - SLOT(thumbnailFailed(QString))); - ((QThreadPool &)m_thumbnailingPool).start(runnable); - } -private slots: - void thumbnailReady(QString path) { emit layoutChanged(); } - void thumbnailFailed(QString path) { m_failed.insert(path); } - void fileChanged(QString filepath) - { - m_thumbnailCache->setStale(filepath); - thumbnailImage(filepath); - // reinsert the path... - watcher.removePath(filepath); - watcher.addPath(filepath); - } - -private: - SharedIconCachePtr m_thumbnailCache; - QThreadPool m_thumbnailingPool; - QSet<QString> m_failed; - QSet<QString> watched; - QFileSystemWatcher watcher; -}; - -class CenteredEditingDelegate : public QStyledItemDelegate -{ -public: - explicit CenteredEditingDelegate(QObject *parent = 0) : QStyledItemDelegate(parent) {} - virtual ~CenteredEditingDelegate() {} - virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, - const QModelIndex &index) const - { - auto widget = QStyledItemDelegate::createEditor(parent, option, index); - auto foo = dynamic_cast<QLineEdit *>(widget); - if (foo) - { - foo->setAlignment(Qt::AlignHCenter); - foo->setFrame(true); - foo->setMaximumWidth(192); - } - return widget; - } -}; - -ScreenshotsPage::ScreenshotsPage(QString path, QWidget *parent) - : QMainWindow(parent), ui(new Ui::ScreenshotsPage) -{ - m_model.reset(new QFileSystemModel()); - m_filterModel.reset(new FilterModel()); - m_filterModel->setSourceModel(m_model.get()); - m_model->setFilter(QDir::Files | QDir::Writable | QDir::Readable); - m_model->setReadOnly(false); - m_model->setNameFilters({"*.png"}); - m_model->setNameFilterDisables(false); - m_folder = path; - m_valid = FS::ensureFolderPathExists(m_folder); - - ui->setupUi(this); - ui->toolBar->insertSpacer(ui->actionView_Folder); - - ui->listView->setIconSize(QSize(128, 128)); - ui->listView->setGridSize(QSize(192, 160)); - ui->listView->setSpacing(9); - // ui->listView->setUniformItemSizes(true); - ui->listView->setLayoutMode(QListView::Batched); - ui->listView->setViewMode(QListView::IconMode); - ui->listView->setResizeMode(QListView::Adjust); - ui->listView->installEventFilter(this); - ui->listView->setEditTriggers(0); - ui->listView->setItemDelegate(new CenteredEditingDelegate(this)); - ui->listView->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->listView, &QListView::customContextMenuRequested, this, &ScreenshotsPage::ShowContextMenu); - connect(ui->listView, SIGNAL(activated(QModelIndex)), SLOT(onItemActivated(QModelIndex))); -} - -bool ScreenshotsPage::eventFilter(QObject *obj, QEvent *evt) -{ - if (obj != ui->listView) - return QWidget::eventFilter(obj, evt); - if (evt->type() != QEvent::KeyPress) - { - return QWidget::eventFilter(obj, evt); - } - QKeyEvent *keyEvent = static_cast<QKeyEvent *>(evt); - switch (keyEvent->key()) - { - case Qt::Key_Delete: - on_actionDelete_triggered(); - return true; - case Qt::Key_F2: - on_actionRename_triggered(); - return true; - default: - break; - } - return QWidget::eventFilter(obj, evt); -} - -ScreenshotsPage::~ScreenshotsPage() -{ - delete ui; -} - -void ScreenshotsPage::ShowContextMenu(const QPoint& pos) -{ - auto menu = ui->toolBar->createContextMenu(this, tr("Context menu")); - menu->exec(ui->listView->mapToGlobal(pos)); - delete menu; -} - -QMenu * ScreenshotsPage::createPopupMenu() -{ - QMenu* filteredMenu = QMainWindow::createPopupMenu(); - filteredMenu->removeAction( ui->toolBar->toggleViewAction() ); - return filteredMenu; -} - -void ScreenshotsPage::onItemActivated(QModelIndex index) -{ - if (!index.isValid()) - return; - auto info = m_model->fileInfo(index); - QString fileName = info.absoluteFilePath(); - DesktopServices::openFile(info.absoluteFilePath()); -} - -void ScreenshotsPage::on_actionView_Folder_triggered() -{ - DesktopServices::openDirectory(m_folder, true); -} - -void ScreenshotsPage::on_actionUpload_triggered() -{ - auto selection = ui->listView->selectionModel()->selectedRows(); - if (selection.isEmpty()) - return; - - QList<ScreenshotPtr> uploaded; - auto job = NetJobPtr(new NetJob("Screenshot Upload")); - if(selection.size() < 2) - { - auto item = selection.at(0); - auto info = m_model->fileInfo(item); - auto screenshot = std::make_shared<ScreenShot>(info); - job->addNetAction(ImgurUpload::make(screenshot)); - - m_uploadActive = true; - ProgressDialog dialog(this); - if(dialog.execWithTask(job.get()) != QDialog::Accepted) - { - CustomMessageBox::selectable(this, tr("Failed to upload screenshots!"), - tr("Unknown error"), QMessageBox::Warning)->exec(); - } - else - { - auto link = screenshot->m_url; - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(link); - CustomMessageBox::selectable( - this, - tr("Upload finished"), - tr("The <a href=\"%1\">link to the uploaded screenshot</a> has been placed in your clipboard.") - .arg(link), - QMessageBox::Information - )->exec(); - } - - m_uploadActive = false; - return; - } - - for (auto item : selection) - { - auto info = m_model->fileInfo(item); - auto screenshot = std::make_shared<ScreenShot>(info); - uploaded.push_back(screenshot); - job->addNetAction(ImgurUpload::make(screenshot)); - } - SequentialTask task; - auto albumTask = NetJobPtr(new NetJob("Imgur Album Creation")); - auto imgurAlbum = ImgurAlbumCreation::make(uploaded); - albumTask->addNetAction(imgurAlbum); - task.addTask(job.unwrap()); - task.addTask(albumTask.unwrap()); - m_uploadActive = true; - ProgressDialog prog(this); - if (prog.execWithTask(&task) != QDialog::Accepted) - { - CustomMessageBox::selectable(this, tr("Failed to upload screenshots!"), - tr("Unknown error"), QMessageBox::Warning)->exec(); - } - else - { - auto link = QString("https://imgur.com/a/%1").arg(imgurAlbum->id()); - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(link); - CustomMessageBox::selectable( - this, - tr("Upload finished"), - tr("The <a href=\"%1\">link to the uploaded album</a> has been placed in your clipboard.") .arg(link), - QMessageBox::Information - )->exec(); - } - m_uploadActive = false; -} - -void ScreenshotsPage::on_actionDelete_triggered() -{ - auto mbox = CustomMessageBox::selectable( - this, tr("Are you sure?"), tr("This will delete all selected screenshots."), - QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No); - std::unique_ptr<QMessageBox> box(mbox); - - if (box->exec() != QMessageBox::Yes) - return; - - auto selected = ui->listView->selectionModel()->selectedIndexes(); - for (auto item : selected) - { - m_model->remove(item); - } -} - -void ScreenshotsPage::on_actionRename_triggered() -{ - auto selection = ui->listView->selectionModel()->selectedIndexes(); - if (selection.isEmpty()) - return; - ui->listView->edit(selection[0]); - // TODO: mass renaming -} - -void ScreenshotsPage::openedImpl() -{ - if(!m_valid) - { - m_valid = FS::ensureFolderPathExists(m_folder); - } - if (m_valid) - { - QString path = QDir(m_folder).absolutePath(); - auto idx = m_model->setRootPath(path); - if(idx.isValid()) - { - ui->listView->setModel(m_filterModel.get()); - ui->listView->setRootIndex(m_filterModel->mapFromSource(idx)); - } - else - { - ui->listView->setModel(nullptr); - } - } -} - -#include "ScreenshotsPage.moc" diff --git a/application/pages/instance/ScreenshotsPage.h b/application/pages/instance/ScreenshotsPage.h deleted file mode 100644 index 03a809de..00000000 --- a/application/pages/instance/ScreenshotsPage.h +++ /dev/null @@ -1,89 +0,0 @@ -/* 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. - */ - -#pragma once - -#include <QMainWindow> - -#include "pages/BasePage.h" -#include <MultiMC.h> - -class QFileSystemModel; -class QIdentityProxyModel; -namespace Ui -{ -class ScreenshotsPage; -} - -struct ScreenShot; -class ScreenshotList; -class ImgurAlbumCreation; - -class ScreenshotsPage : public QMainWindow, public BasePage -{ - Q_OBJECT - -public: - explicit ScreenshotsPage(QString path, QWidget *parent = 0); - virtual ~ScreenshotsPage(); - - virtual void openedImpl() override; - - enum - { - NothingDone = 0x42 - }; - - virtual bool eventFilter(QObject *, QEvent *) override; - virtual QString displayName() const override - { - return tr("Screenshots"); - } - virtual QIcon icon() const override - { - return MMC->getThemedIcon("screenshots"); - } - virtual QString id() const override - { - return "screenshots"; - } - virtual QString helpPage() const override - { - return "Screenshots-management"; - } - virtual bool apply() override - { - return !m_uploadActive; - } - -protected: - QMenu * createPopupMenu() override; - -private slots: - void on_actionUpload_triggered(); - void on_actionDelete_triggered(); - void on_actionRename_triggered(); - void on_actionView_Folder_triggered(); - void onItemActivated(QModelIndex); - void ShowContextMenu(const QPoint &pos); - -private: - Ui::ScreenshotsPage *ui; - std::shared_ptr<QFileSystemModel> m_model; - std::shared_ptr<QIdentityProxyModel> m_filterModel; - QString m_folder; - bool m_valid = false; - bool m_uploadActive = false; -}; diff --git a/application/pages/instance/ScreenshotsPage.ui b/application/pages/instance/ScreenshotsPage.ui deleted file mode 100644 index f11f4cd4..00000000 --- a/application/pages/instance/ScreenshotsPage.ui +++ /dev/null @@ -1,87 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>ScreenshotsPage</class> - <widget class="QMainWindow" name="ScreenshotsPage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>800</width> - <height>600</height> - </rect> - </property> - <widget class="QWidget" name="centralwidget"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QListView" name="listView"> - <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectRows</enum> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="WideBar" name="toolBar"> - <property name="windowTitle"> - <string>Actions</string> - </property> - <property name="toolButtonStyle"> - <enum>Qt::ToolButtonTextOnly</enum> - </property> - <attribute name="toolBarArea"> - <enum>RightToolBarArea</enum> - </attribute> - <attribute name="toolBarBreak"> - <bool>false</bool> - </attribute> - <addaction name="actionUpload"/> - <addaction name="actionDelete"/> - <addaction name="actionRename"/> - <addaction name="actionView_Folder"/> - </widget> - <action name="actionUpload"> - <property name="text"> - <string>Upload</string> - </property> - </action> - <action name="actionDelete"> - <property name="text"> - <string>Delete</string> - </property> - </action> - <action name="actionRename"> - <property name="text"> - <string>Rename</string> - </property> - </action> - <action name="actionView_Folder"> - <property name="text"> - <string>View Folder</string> - </property> - </action> - </widget> - <customwidgets> - <customwidget> - <class>WideBar</class> - <extends>QToolBar</extends> - <header>widgets/WideBar.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> diff --git a/application/pages/instance/ServersPage.cpp b/application/pages/instance/ServersPage.cpp deleted file mode 100644 index d63c6e70..00000000 --- a/application/pages/instance/ServersPage.cpp +++ /dev/null @@ -1,768 +0,0 @@ -#include "ServersPage.h" -#include "ui_ServersPage.h" - -#include <FileSystem.h> -#include <sstream> -#include <io/stream_reader.h> -#include <tag_string.h> -#include <tag_primitive.h> -#include <tag_list.h> -#include <tag_compound.h> -#include <minecraft/MinecraftInstance.h> - -#include <QFileSystemWatcher> -#include <QMenu> - -static const int COLUMN_COUNT = 2; // 3 , TBD: latency and other nice things. - -struct Server -{ - // Types - enum class AcceptsTextures : int - { - ASK = 0, - ALWAYS = 1, - NEVER = 2 - }; - - // Methods - Server() - { - m_name = QObject::tr("Minecraft Server"); - } - Server(const QString & name, const QString & address) - { - m_name = name; - m_address = address; - } - Server(nbt::tag_compound& server) - { - std::string addressStr(server["ip"]); - m_address = QString::fromUtf8(addressStr.c_str()); - - std::string nameStr(server["name"]); - m_name = QString::fromUtf8(nameStr.c_str()); - - if(server["icon"]) - { - std::string base64str(server["icon"]); - m_icon = QByteArray::fromBase64(base64str.c_str()); - } - - if(server.has_key("acceptTextures", nbt::tag_type::Byte)) - { - bool value = server["acceptTextures"].as<nbt::tag_byte>().get(); - if(value) - { - m_acceptsTextures = AcceptsTextures::ALWAYS; - } - else - { - m_acceptsTextures = AcceptsTextures::NEVER; - } - } - } - - void serialize(nbt::tag_compound& server) - { - server.insert("name", m_name.trimmed().toUtf8().toStdString()); - server.insert("ip", m_address.trimmed().toUtf8().toStdString()); - if(m_icon.size()) - { - server.insert("icon", m_icon.toBase64().toStdString()); - } - if(m_acceptsTextures != AcceptsTextures::ASK) - { - server.insert("acceptTextures", nbt::tag_byte(m_acceptsTextures == AcceptsTextures::ALWAYS)); - } - } - - // Data - persistent and user changeable - QString m_name; - QString m_address; - AcceptsTextures m_acceptsTextures = AcceptsTextures::ASK; - - // Data - persistent and automatically updated - QByteArray m_icon; - - // Data - temporary - bool m_checked = false; - bool m_up = false; - QString m_motd; // https://mctools.org/motd-creator - int m_ping = 0; - int m_currentPlayers = 0; - int m_maxPlayers = 0; -}; - -static std::unique_ptr <nbt::tag_compound> parseServersDat(const QString& filename) -{ - try - { - QByteArray input = FS::read(filename); - std::istringstream foo(std::string(input.constData(), input.size())); - auto pair = nbt::io::read_compound(foo); - - if(pair.first != "") - return nullptr; - - if(pair.second == nullptr) - return nullptr; - - return std::move(pair.second); - } - catch (...) - { - return nullptr; - } -} - -static bool serializeServerDat(const QString& filename, nbt::tag_compound * levelInfo) -{ - try - { - if(!FS::ensureFilePathExists(filename)) - { - return false; - } - std::ostringstream s; - nbt::io::write_tag("", *levelInfo, s); - QByteArray val(s.str().data(), (int) s.str().size() ); - FS::write(filename, val); - return true; - } - catch (...) - { - return false; - } -} - -class ServersModel: public QAbstractListModel -{ - Q_OBJECT -public: - enum Roles - { - ServerPtrRole = Qt::UserRole, - }; - explicit ServersModel(const QString &path, QObject *parent = 0) - : QAbstractListModel(parent) - { - m_path = path; - m_watcher = new QFileSystemWatcher(this); - connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &ServersModel::fileChanged); - connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &ServersModel::dirChanged); - m_saveTimer.setSingleShot(true); - m_saveTimer.setInterval(5000); - connect(&m_saveTimer, &QTimer::timeout, this, &ServersModel::save_internal); - } - virtual ~ServersModel() {}; - - void observe() - { - if(m_observed) - { - return; - } - m_observed = true; - - if(!m_loaded) - { - load(); - } - - updateFSObserver(); - } - - void unobserve() - { - if(!m_observed) - { - return; - } - m_observed = false; - - updateFSObserver(); - } - - void lock() - { - if(m_locked) - { - return; - } - saveNow(); - - m_locked = true; - updateFSObserver(); - } - - void unlock() - { - if(!m_locked) - { - return; - } - m_locked = false; - - updateFSObserver(); - } - - int addEmptyRow(int position) - { - if(m_locked) - { - return -1; - } - if(position < 0 || position >= rowCount()) - { - position = rowCount(); - } - beginInsertRows(QModelIndex(), position, position); - m_servers.insert(position, Server()); - endInsertRows(); - scheduleSave(); - return position; - } - - bool removeRow(int row) - { - if(m_locked) - { - return false; - } - if(row < 0 || row >= rowCount()) - { - return false; - } - beginRemoveRows(QModelIndex(), row, row); - m_servers.removeAt(row); - endRemoveRows(); // does absolutely nothing, the selected server stays as the next line... - scheduleSave(); - return true; - } - - bool moveUp(int row) - { - if(m_locked) - { - return false; - } - if(row <= 0) - { - return false; - } - beginMoveRows(QModelIndex(), row, row, QModelIndex(), row - 1); - m_servers.swap(row-1, row); - endMoveRows(); - scheduleSave(); - return true; - } - - bool moveDown(int row) - { - if(m_locked) - { - return false; - } - int count = rowCount(); - if(row + 1 >= count) - { - return false; - } - beginMoveRows(QModelIndex(), row, row, QModelIndex(), row + 2); - m_servers.swap(row+1, row); - endMoveRows(); - scheduleSave(); - return true; - } - - QVariant headerData(int section, Qt::Orientation orientation, int role) const override - { - if (section < 0 || section >= COLUMN_COUNT) - return QVariant(); - - if(role == Qt::DisplayRole) - { - switch(section) - { - case 0: - return tr("Name"); - case 1: - return tr("Address"); - case 2: - return tr("Latency"); - } - } - - return QAbstractListModel::headerData(section, orientation, role); - } - - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override - { - if (!index.isValid()) - return QVariant(); - - int row = index.row(); - int column = index.column(); - if(column < 0 || column >= COLUMN_COUNT) - return QVariant(); - - if (row < 0 || row >= m_servers.size()) - return QVariant(); - - switch(column) - { - case 0: - switch (role) - { - case Qt::DecorationRole: - { - auto & bytes = m_servers[row].m_icon; - if(bytes.size()) - { - QPixmap px; - if(px.loadFromData(bytes)) - return QIcon(px); - } - return MMC->getThemedIcon("unknown_server"); - } - case Qt::DisplayRole: - return m_servers[row].m_name; - case ServerPtrRole: - return QVariant::fromValue<void *>((void *)&m_servers[row]); - default: - return QVariant(); - } - case 1: - switch (role) - { - case Qt::DisplayRole: - return m_servers[row].m_address; - default: - return QVariant(); - } - case 2: - switch (role) - { - case Qt::DisplayRole: - return m_servers[row].m_ping; - default: - return QVariant(); - } - default: - return QVariant(); - } - } - - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override - { - return m_servers.size(); - } - int columnCount(const QModelIndex & parent) const override - { - return COLUMN_COUNT; - } - - Server * at(int index) - { - if(index < 0 || index >= rowCount()) - { - return nullptr; - } - return &m_servers[index]; - } - - void setName(int row, const QString & name) - { - if(m_locked) - { - return; - } - auto server = at(row); - if(!server || server->m_name == name) - { - return; - } - server->m_name = name; - emit dataChanged(index(row, 0), index(row, COLUMN_COUNT - 1)); - scheduleSave(); - } - - void setAddress(int row, const QString & address) - { - if(m_locked) - { - return; - } - auto server = at(row); - if(!server || server->m_address == address) - { - return; - } - server->m_address = address; - emit dataChanged(index(row, 0), index(row, COLUMN_COUNT - 1)); - scheduleSave(); - } - - void setAcceptsTextures(int row, Server::AcceptsTextures textures) - { - if(m_locked) - { - return; - } - auto server = at(row); - if(!server || server->m_acceptsTextures == textures) - { - return; - } - server->m_acceptsTextures = textures; - emit dataChanged(index(row, 0), index(row, COLUMN_COUNT - 1)); - scheduleSave(); - } - - void load() - { - cancelSave(); - beginResetModel(); - QList<Server> servers; - auto serversDat = parseServersDat(serversPath()); - if(serversDat) - { - auto &serversList = serversDat->at("servers").as<nbt::tag_list>(); - for(auto iter = serversList.begin(); iter != serversList.end(); iter++) - { - auto & serverTag = (*iter).as<nbt::tag_compound>(); - Server s(serverTag); - servers.append(s); - } - } - m_servers.swap(servers); - m_loaded = true; - endResetModel(); - } - - void saveNow() - { - if(saveIsScheduled()) - { - save_internal(); - } - } - - -public slots: - void dirChanged(const QString& path) - { - qDebug() << "Changed:" << path; - load(); - } - void fileChanged(const QString& path) - { - qDebug() << "Changed:" << path; - } - -private slots: - void save_internal() - { - cancelSave(); - QString path = serversPath(); - qDebug() << "Server list about to be saved to" << path; - - nbt::tag_compound out; - nbt::tag_list list; - for(auto & server: m_servers) - { - nbt::tag_compound serverNbt; - server.serialize(serverNbt); - list.push_back(std::move(serverNbt)); - } - out.insert("servers", nbt::value(std::move(list))); - - if(!serializeServerDat(path, &out)) - { - qDebug() << "Failed to save server list:" << path << "Will try again."; - scheduleSave(); - } - } - -private: - void scheduleSave() - { - if(!m_loaded) - { - qDebug() << "Server list should never save if it didn't successfully load, path:" << m_path; - return; - } - if(!m_dirty) - { - m_dirty = true; - qDebug() << "Server list save is scheduled for" << m_path; - } - m_saveTimer.start(); - } - - void cancelSave() - { - m_dirty = false; - m_saveTimer.stop(); - } - - bool saveIsScheduled() const - { - return m_dirty; - } - - void updateFSObserver() - { - bool observingFS = m_watcher->directories().contains(m_path); - if(m_observed && m_locked) - { - if(!observingFS) - { - qWarning() << "Will watch" << m_path; - if(!m_watcher->addPath(m_path)) - { - qWarning() << "Failed to start watching" << m_path; - } - } - } - else - { - if(observingFS) - { - qWarning() << "Will stop watching" << m_path; - if(!m_watcher->removePath(m_path)) - { - qWarning() << "Failed to stop watching" << m_path; - } - } - } - } - - QString serversPath() - { - QFileInfo foo(FS::PathCombine(m_path, "servers.dat")); - return foo.filePath(); - } - -private: - bool m_loaded = false; - bool m_locked = false; - bool m_observed = false; - bool m_dirty = false; - QString m_path; - QList<Server> m_servers; - QFileSystemWatcher *m_watcher = nullptr; - QTimer m_saveTimer; -}; - -ServersPage::ServersPage(InstancePtr inst, QWidget* parent) - : QMainWindow(parent), ui(new Ui::ServersPage) -{ - ui->setupUi(this); - m_inst = inst; - m_model = new ServersModel(inst->gameRoot(), this); - ui->serversView->setIconSize(QSize(64,64)); - ui->serversView->setModel(m_model); - ui->serversView->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->serversView, &QTreeView::customContextMenuRequested, this, &ServersPage::ShowContextMenu); - - auto head = ui->serversView->header(); - if(head->count()) - { - head->setSectionResizeMode(0, QHeaderView::Stretch); - for(int i = 1; i < head->count(); i++) - { - head->setSectionResizeMode(i, QHeaderView::ResizeToContents); - } - } - - auto selectionModel = ui->serversView->selectionModel(); - connect(selectionModel, &QItemSelectionModel::currentChanged, this, &ServersPage::currentChanged); - connect(m_inst.get(), &MinecraftInstance::runningStatusChanged, this, &ServersPage::on_RunningState_changed); - connect(ui->nameLine, &QLineEdit::textEdited, this, &ServersPage::nameEdited); - connect(ui->addressLine, &QLineEdit::textEdited, this, &ServersPage::addressEdited); - connect(ui->resourceComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(resourceIndexChanged(int))); - connect(m_model, &QAbstractItemModel::rowsRemoved, this, &ServersPage::rowsRemoved); - - m_locked = m_inst->isRunning(); - if(m_locked) - { - m_model->lock(); - } - - updateState(); -} - -ServersPage::~ServersPage() -{ - m_model->saveNow(); - delete ui; -} - -void ServersPage::ShowContextMenu(const QPoint& pos) -{ - auto menu = ui->toolBar->createContextMenu(this, tr("Context menu")); - menu->exec(ui->serversView->mapToGlobal(pos)); - delete menu; -} - -QMenu * ServersPage::createPopupMenu() -{ - QMenu* filteredMenu = QMainWindow::createPopupMenu(); - filteredMenu->removeAction( ui->toolBar->toggleViewAction() ); - return filteredMenu; -} - -void ServersPage::on_RunningState_changed(bool running) -{ - if(m_locked == running) - { - return; - } - m_locked = running; - if(m_locked) - { - m_model->lock(); - } - else - { - m_model->unlock(); - } - updateState(); -} - -void ServersPage::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) -{ - int nextServer = -1; - if (!current.isValid()) - { - nextServer = -1; - } - else - { - nextServer = current.row(); - } - currentServer = nextServer; - updateState(); -} - -// WARNING: this is here because currentChanged is not accurate when removing rows. the current item needs to be fixed up after removal. -void ServersPage::rowsRemoved(const QModelIndex& parent, int first, int last) -{ - if(currentServer < first) - { - // current was before the removal - return; - } - else if(currentServer >= first && currentServer <= last) - { - // current got removed... - return; - } - else - { - // current was past the removal - int count = last - first + 1; - currentServer -= count; - } -} - -void ServersPage::nameEdited(const QString& name) -{ - m_model->setName(currentServer, name); -} - -void ServersPage::addressEdited(const QString& address) -{ - m_model->setAddress(currentServer, address); -} - -void ServersPage::resourceIndexChanged(int index) -{ - auto acceptsTextures = Server::AcceptsTextures(index); - m_model->setAcceptsTextures(currentServer, acceptsTextures); -} - -void ServersPage::updateState() -{ - auto server = m_model->at(currentServer); - - bool serverEditEnabled = server && !m_locked; - ui->addressLine->setEnabled(serverEditEnabled); - ui->nameLine->setEnabled(serverEditEnabled); - ui->resourceComboBox->setEnabled(serverEditEnabled); - ui->actionMove_Down->setEnabled(serverEditEnabled); - ui->actionMove_Up->setEnabled(serverEditEnabled); - ui->actionRemove->setEnabled(serverEditEnabled); - ui->actionJoin->setEnabled(serverEditEnabled); - - if(server) - { - ui->addressLine->setText(server->m_address); - ui->nameLine->setText(server->m_name); - ui->resourceComboBox->setCurrentIndex(int(server->m_acceptsTextures)); - } - else - { - ui->addressLine->setText(QString()); - ui->nameLine->setText(QString()); - ui->resourceComboBox->setCurrentIndex(0); - } - - ui->actionAdd->setDisabled(m_locked); -} - -void ServersPage::openedImpl() -{ - m_model->observe(); -} - -void ServersPage::closedImpl() -{ - m_model->unobserve(); -} - -void ServersPage::on_actionAdd_triggered() -{ - int position = m_model->addEmptyRow(currentServer + 1); - if(position < 0) - { - return; - } - // select the new row - ui->serversView->selectionModel()->setCurrentIndex( - m_model->index(position), - QItemSelectionModel::SelectCurrent | QItemSelectionModel::Clear | QItemSelectionModel::Rows - ); - currentServer = position; -} - -void ServersPage::on_actionRemove_triggered() -{ - m_model->removeRow(currentServer); -} - -void ServersPage::on_actionMove_Up_triggered() -{ - if(m_model->moveUp(currentServer)) - { - currentServer --; - } -} - -void ServersPage::on_actionMove_Down_triggered() -{ - if(m_model->moveDown(currentServer)) - { - currentServer ++; - } -} - -void ServersPage::on_actionJoin_triggered() -{ - const auto &address = m_model->at(currentServer)->m_address; - MMC->launch(m_inst, true, nullptr, std::make_shared<MinecraftServerTarget>(MinecraftServerTarget::parse(address))); -} - -#include "ServersPage.moc" diff --git a/application/pages/instance/ServersPage.h b/application/pages/instance/ServersPage.h deleted file mode 100644 index 8c5b7eb8..00000000 --- a/application/pages/instance/ServersPage.h +++ /dev/null @@ -1,94 +0,0 @@ -/* 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. - */ - -#pragma once - -#include <QMainWindow> -#include <QString> - -#include "pages/BasePage.h" -#include <MultiMC.h> - -namespace Ui -{ -class ServersPage; -} - -struct Server; -class ServersModel; -class MinecraftInstance; - -class ServersPage : public QMainWindow, public BasePage -{ - Q_OBJECT - -public: - explicit ServersPage(InstancePtr inst, QWidget *parent = 0); - virtual ~ServersPage(); - - void openedImpl() override; - void closedImpl() override; - - virtual QString displayName() const override - { - return tr("Servers"); - } - virtual QIcon icon() const override - { - return MMC->getThemedIcon("unknown_server"); - } - virtual QString id() const override - { - return "servers"; - } - virtual QString helpPage() const override - { - return "Servers-management"; - } - -protected: - QMenu * createPopupMenu() override; - -private: - void updateState(); - void scheduleSave(); - bool saveIsScheduled() const; - -private slots: - void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); - void rowsRemoved(const QModelIndex &parent, int first, int last); - - void on_actionAdd_triggered(); - void on_actionRemove_triggered(); - void on_actionMove_Up_triggered(); - void on_actionMove_Down_triggered(); - void on_actionJoin_triggered(); - - void on_RunningState_changed(bool running); - - void nameEdited(const QString & name); - void addressEdited(const QString & address); - void resourceIndexChanged(int index);\ - - void ShowContextMenu(const QPoint &pos); - -private: // data - int currentServer = -1; - bool m_locked = true; - Ui::ServersPage *ui = nullptr; - ServersModel * m_model = nullptr; - InstancePtr m_inst = nullptr; -}; - diff --git a/application/pages/instance/ServersPage.ui b/application/pages/instance/ServersPage.ui deleted file mode 100644 index d89b7cba..00000000 --- a/application/pages/instance/ServersPage.ui +++ /dev/null @@ -1,194 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>ServersPage</class> - <widget class="QMainWindow" name="ServersPage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>1318</width> - <height>879</height> - </rect> - </property> - <widget class="QWidget" name="centralwidget"> - <layout class="QVBoxLayout" name="verticalLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QTreeView" name="serversView"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="acceptDrops"> - <bool>true</bool> - </property> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::SingleSelection</enum> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectRows</enum> - </property> - <property name="iconSize"> - <size> - <width>64</width> - <height>64</height> - </size> - </property> - <property name="rootIsDecorated"> - <bool>false</bool> - </property> - <attribute name="headerStretchLastSection"> - <bool>false</bool> - </attribute> - </widget> - </item> - <item> - <layout class="QGridLayout" name="gridLayout_2"> - <property name="leftMargin"> - <number>6</number> - </property> - <property name="rightMargin"> - <number>6</number> - </property> - <item row="0" column="0"> - <widget class="QLabel" name="nameLabel"> - <property name="text"> - <string>&Name</string> - </property> - <property name="buddy"> - <cstring>nameLine</cstring> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="nameLine"/> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="addressLabel"> - <property name="text"> - <string>Address</string> - </property> - <property name="buddy"> - <cstring>addressLine</cstring> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="addressLine"/> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="resourcesLabel"> - <property name="text"> - <string>Reso&urces</string> - </property> - <property name="buddy"> - <cstring>resourceComboBox</cstring> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QComboBox" name="resourceComboBox"> - <item> - <property name="text"> - <string>Ask to download</string> - </property> - </item> - <item> - <property name="text"> - <string>Always download</string> - </property> - </item> - <item> - <property name="text"> - <string>Never download</string> - </property> - </item> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <widget class="WideBar" name="toolBar"> - <property name="windowTitle"> - <string>Actions</string> - </property> - <property name="allowedAreas"> - <set>Qt::LeftToolBarArea|Qt::RightToolBarArea</set> - </property> - <property name="toolButtonStyle"> - <enum>Qt::ToolButtonTextOnly</enum> - </property> - <property name="floatable"> - <bool>false</bool> - </property> - <attribute name="toolBarArea"> - <enum>RightToolBarArea</enum> - </attribute> - <attribute name="toolBarBreak"> - <bool>false</bool> - </attribute> - <addaction name="actionAdd"/> - <addaction name="actionRemove"/> - <addaction name="actionMove_Up"/> - <addaction name="actionMove_Down"/> - <addaction name="actionJoin"/> - </widget> - <action name="actionAdd"> - <property name="text"> - <string>Add</string> - </property> - </action> - <action name="actionRemove"> - <property name="text"> - <string>Remove</string> - </property> - </action> - <action name="actionMove_Up"> - <property name="text"> - <string>Move Up</string> - </property> - </action> - <action name="actionMove_Down"> - <property name="text"> - <string>Move Down</string> - </property> - </action> - <action name="actionJoin"> - <property name="text"> - <string>Join</string> - </property> - </action> - </widget> - <customwidgets> - <customwidget> - <class>WideBar</class> - <extends>QToolBar</extends> - <header>widgets/WideBar.h</header> - </customwidget> - </customwidgets> - <tabstops> - <tabstop>serversView</tabstop> - <tabstop>nameLine</tabstop> - <tabstop>addressLine</tabstop> - <tabstop>resourceComboBox</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/application/pages/instance/TexturePackPage.h b/application/pages/instance/TexturePackPage.h deleted file mode 100644 index 3f04997d..00000000 --- a/application/pages/instance/TexturePackPage.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "ModFolderPage.h" -#include "ui_ModFolderPage.h" - -class TexturePackPage : public ModFolderPage -{ - Q_OBJECT -public: - explicit TexturePackPage(MinecraftInstance *instance, QWidget *parent = 0) - : ModFolderPage(instance, instance->texturePackList(), "texturepacks", "resourcepacks", - tr("Texture packs"), "Texture-packs", parent) - { - ui->actionView_configs->setVisible(false); - } - virtual ~TexturePackPage() {} - - virtual bool shouldDisplay() const override - { - return m_inst->traits().contains("texturepacks"); - } -}; diff --git a/application/pages/instance/VersionPage.cpp b/application/pages/instance/VersionPage.cpp deleted file mode 100644 index a98bfb7d..00000000 --- a/application/pages/instance/VersionPage.cpp +++ /dev/null @@ -1,642 +0,0 @@ -/* 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 "MultiMC.h" - -#include <QMessageBox> -#include <QLabel> -#include <QEvent> -#include <QKeyEvent> -#include <QMenu> - -#include "VersionPage.h" -#include "ui_VersionPage.h" - -#include "dialogs/CustomMessageBox.h" -#include "dialogs/VersionSelectDialog.h" -#include "dialogs/NewComponentDialog.h" - -#include "dialogs/ProgressDialog.h" -#include <GuiUtil.h> - -#include <QAbstractItemModel> -#include <QMessageBox> -#include <QListView> -#include <QString> -#include <QUrl> - -#include "minecraft/PackProfile.h" -#include "minecraft/auth/MojangAccountList.h" -#include "minecraft/mod/Mod.h" -#include "icons/IconList.h" -#include "Exception.h" -#include "Version.h" -#include "DesktopServices.h" - -#include <meta/Index.h> -#include <meta/VersionList.h> - -class IconProxy : public QIdentityProxyModel -{ - Q_OBJECT -public: - - IconProxy(QWidget *parentWidget) : QIdentityProxyModel(parentWidget) - { - connect(parentWidget, &QObject::destroyed, this, &IconProxy::widgetGone); - m_parentWidget = parentWidget; - } - - virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const override - { - QVariant var = QIdentityProxyModel::data(proxyIndex, role); - int column = proxyIndex.column(); - if(column == 0 && role == Qt::DecorationRole && m_parentWidget) - { - if(!var.isNull()) - { - auto string = var.toString(); - if(string == "warning") - { - return MMC->getThemedIcon("status-yellow"); - } - else if(string == "error") - { - return MMC->getThemedIcon("status-bad"); - } - } - return MMC->getThemedIcon("status-good"); - } - return var; - } -private slots: - void widgetGone() - { - m_parentWidget = nullptr; - } - -private: - QWidget *m_parentWidget = nullptr; -}; - -QIcon VersionPage::icon() const -{ - return MMC->icons()->getIcon(m_inst->iconKey()); -} -bool VersionPage::shouldDisplay() const -{ - return true; -} - -QMenu * VersionPage::createPopupMenu() -{ - QMenu* filteredMenu = QMainWindow::createPopupMenu(); - filteredMenu->removeAction( ui->toolBar->toggleViewAction() ); - return filteredMenu; -} - -VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent) - : QMainWindow(parent), ui(new Ui::VersionPage), m_inst(inst) -{ - ui->setupUi(this); - - ui->toolBar->insertSpacer(ui->actionReload); - - m_profile = m_inst->getPackProfile(); - - reloadPackProfile(); - - auto proxy = new IconProxy(ui->packageView); - proxy->setSourceModel(m_profile.get()); - - m_filterModel = new QSortFilterProxyModel(); - m_filterModel->setDynamicSortFilter(true); - m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive); - m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive); - m_filterModel->setSourceModel(proxy); - m_filterModel->setFilterKeyColumn(-1); - - ui->packageView->setModel(m_filterModel); - ui->packageView->installEventFilter(this); - ui->packageView->setSelectionMode(QAbstractItemView::SingleSelection); - ui->packageView->setContextMenuPolicy(Qt::CustomContextMenu); - - connect(ui->packageView->selectionModel(), &QItemSelectionModel::currentChanged, this, &VersionPage::versionCurrent); - auto smodel = ui->packageView->selectionModel(); - connect(smodel, &QItemSelectionModel::currentChanged, this, &VersionPage::packageCurrent); - - connect(m_profile.get(), &PackProfile::minecraftChanged, this, &VersionPage::updateVersionControls); - controlsEnabled = !m_inst->isRunning(); - updateVersionControls(); - preselect(0); - connect(m_inst, &BaseInstance::runningStatusChanged, this, &VersionPage::updateRunningStatus); - connect(ui->packageView, &ModListView::customContextMenuRequested, this, &VersionPage::showContextMenu); - connect(ui->filterEdit, &QLineEdit::textChanged, this, &VersionPage::onFilterTextChanged); -} - -VersionPage::~VersionPage() -{ - delete ui; -} - -void VersionPage::showContextMenu(const QPoint& pos) -{ - auto menu = ui->toolBar->createContextMenu(this, tr("Context menu")); - menu->exec(ui->packageView->mapToGlobal(pos)); - delete menu; -} - -void VersionPage::packageCurrent(const QModelIndex ¤t, const QModelIndex &previous) -{ - if (!current.isValid()) - { - ui->frame->clear(); - return; - } - int row = current.row(); - auto patch = m_profile->getComponent(row); - auto severity = patch->getProblemSeverity(); - switch(severity) - { - case ProblemSeverity::Warning: - ui->frame->setModText(tr("%1 possibly has issues.").arg(patch->getName())); - break; - case ProblemSeverity::Error: - ui->frame->setModText(tr("%1 has issues!").arg(patch->getName())); - break; - default: - case ProblemSeverity::None: - ui->frame->clear(); - return; - } - - auto &problems = patch->getProblems(); - QString problemOut; - for (auto &problem: problems) - { - if(problem.m_severity == ProblemSeverity::Error) - { - problemOut += tr("Error: "); - } - else if(problem.m_severity == ProblemSeverity::Warning) - { - problemOut += tr("Warning: "); - } - problemOut += problem.m_description; - problemOut += "\n"; - } - ui->frame->setModDescription(problemOut); -} - -void VersionPage::updateRunningStatus(bool running) -{ - if(controlsEnabled == running) { - controlsEnabled = !running; - updateVersionControls(); - } -} - -void VersionPage::updateVersionControls() -{ - // FIXME: this is a dirty hack - auto minecraftVersion = Version(m_profile->getComponentVersion("net.minecraft")); - - bool supportsFabric = minecraftVersion >= Version("1.14"); - ui->actionInstall_Fabric->setEnabled(controlsEnabled && supportsFabric); - - bool supportsForge = minecraftVersion <= Version("1.16.5"); - ui->actionInstall_Forge->setEnabled(controlsEnabled && supportsForge); - - bool supportsLiteLoader = minecraftVersion <= Version("1.12.2"); - ui->actionInstall_LiteLoader->setEnabled(controlsEnabled && supportsLiteLoader); - - updateButtons(); -} - -void VersionPage::updateButtons(int row) -{ - if(row == -1) - row = currentRow(); - auto patch = m_profile->getComponent(row); - ui->actionRemove->setEnabled(controlsEnabled && patch && patch->isRemovable()); - ui->actionMove_down->setEnabled(controlsEnabled && patch && patch->isMoveable()); - ui->actionMove_up->setEnabled(controlsEnabled && patch && patch->isMoveable()); - ui->actionChange_version->setEnabled(controlsEnabled && patch && patch->isVersionChangeable()); - ui->actionEdit->setEnabled(controlsEnabled && patch && patch->isCustom()); - ui->actionCustomize->setEnabled(controlsEnabled && patch && patch->isCustomizable()); - ui->actionRevert->setEnabled(controlsEnabled && patch && patch->isRevertible()); - ui->actionDownload_All->setEnabled(controlsEnabled); - ui->actionAdd_Empty->setEnabled(controlsEnabled); - ui->actionReload->setEnabled(controlsEnabled); - ui->actionInstall_mods->setEnabled(controlsEnabled); - ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled); - ui->actionAdd_to_Minecraft_jar->setEnabled(controlsEnabled); -} - -bool VersionPage::reloadPackProfile() -{ - try - { - m_profile->reload(Net::Mode::Online); - return true; - } - catch (const Exception &e) - { - QMessageBox::critical(this, tr("Error"), e.cause()); - return false; - } - catch (...) - { - QMessageBox::critical( - this, tr("Error"), - tr("Couldn't load the instance profile.")); - return false; - } -} - -void VersionPage::on_actionReload_triggered() -{ - reloadPackProfile(); - m_container->refreshContainer(); -} - -void VersionPage::on_actionRemove_triggered() -{ - if (ui->packageView->currentIndex().isValid()) - { - // FIXME: use actual model, not reloading. - if (!m_profile->remove(ui->packageView->currentIndex().row())) - { - QMessageBox::critical(this, tr("Error"), tr("Couldn't remove file")); - } - } - updateButtons(); - reloadPackProfile(); - m_container->refreshContainer(); -} - -void VersionPage::on_actionInstall_mods_triggered() -{ - if(m_container) - { - m_container->selectPage("mods"); - } -} - -void VersionPage::on_actionAdd_to_Minecraft_jar_triggered() -{ - auto list = GuiUtil::BrowseForFiles("jarmod", tr("Select jar mods"), tr("Minecraft.jar mods (*.zip *.jar)"), MMC->settings()->get("CentralModsDir").toString(), this->parentWidget()); - if(!list.empty()) - { - m_profile->installJarMods(list); - } - updateButtons(); -} - -void VersionPage::on_actionReplace_Minecraft_jar_triggered() -{ - auto jarPath = GuiUtil::BrowseForFile("jar", tr("Select jar"), tr("Minecraft.jar replacement (*.jar)"), MMC->settings()->get("CentralModsDir").toString(), this->parentWidget()); - if(!jarPath.isEmpty()) - { - m_profile->installCustomJar(jarPath); - } - updateButtons(); -} - -void VersionPage::on_actionMove_up_triggered() -{ - try - { - m_profile->move(currentRow(), PackProfile::MoveUp); - } - catch (const Exception &e) - { - QMessageBox::critical(this, tr("Error"), e.cause()); - } - updateButtons(); -} - -void VersionPage::on_actionMove_down_triggered() -{ - try - { - m_profile->move(currentRow(), PackProfile::MoveDown); - } - catch (const Exception &e) - { - QMessageBox::critical(this, tr("Error"), e.cause()); - } - updateButtons(); -} - -void VersionPage::on_actionChange_version_triggered() -{ - auto versionRow = currentRow(); - if(versionRow == -1) - { - return; - } - auto patch = m_profile->getComponent(versionRow); - auto name = patch->getName(); - auto list = patch->getVersionList(); - if(!list) - { - return; - } - auto uid = list->uid(); - // FIXME: this is a horrible HACK. Get version filtering information from the actual metadata... - if(uid == "net.minecraftforge") - { - on_actionInstall_Forge_triggered(); - return; - } - else if (uid == "com.mumfrey.liteloader") - { - on_actionInstall_LiteLoader_triggered(); - return; - } - VersionSelectDialog vselect(list.get(), tr("Change %1 version").arg(name), this); - if (uid == "net.fabricmc.intermediary") - { - vselect.setEmptyString(tr("No intermediary mappings versions are currently available.")); - vselect.setEmptyErrorString(tr("Couldn't load or download the intermediary mappings version lists!")); - vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); - } - auto currentVersion = patch->getVersion(); - if(!currentVersion.isEmpty()) - { - vselect.setCurrentVersion(currentVersion); - } - if (!vselect.exec() || !vselect.selectedVersion()) - return; - - qDebug() << "Change" << uid << "to" << vselect.selectedVersion()->descriptor(); - bool important = false; - if(uid == "net.minecraft") - { - important = true; - } - m_profile->setComponentVersion(uid, vselect.selectedVersion()->descriptor(), important); - m_profile->resolve(Net::Mode::Online); - m_container->refreshContainer(); -} - -void VersionPage::on_actionDownload_All_triggered() -{ - if (!MMC->accounts()->anyAccountIsValid()) - { - CustomMessageBox::selectable( - this, tr("Error"), - tr("MultiMC cannot download Minecraft or update instances unless you have at least " - "one account added.\nPlease add your Mojang or Minecraft account."), - QMessageBox::Warning)->show(); - return; - } - - auto updateTask = m_inst->createUpdateTask(Net::Mode::Online); - if (!updateTask) - { - return; - } - ProgressDialog tDialog(this); - connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString))); - // FIXME: unused return value - tDialog.execWithTask(updateTask.get()); - updateButtons(); - m_container->refreshContainer(); -} - -void VersionPage::on_actionInstall_Forge_triggered() -{ - auto vlist = ENV.metadataIndex()->get("net.minecraftforge"); - if(!vlist) - { - return; - } - VersionSelectDialog vselect(vlist.get(), tr("Select Forge version"), this); - vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") + m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyErrorString(tr("Couldn't load or download the Forge version lists!")); - - auto currentVersion = m_profile->getComponentVersion("net.minecraftforge"); - if(!currentVersion.isEmpty()) - { - vselect.setCurrentVersion(currentVersion); - } - - if (vselect.exec() && vselect.selectedVersion()) - { - auto vsn = vselect.selectedVersion(); - m_profile->setComponentVersion("net.minecraftforge", vsn->descriptor()); - m_profile->resolve(Net::Mode::Online); - // m_profile->installVersion(); - preselect(m_profile->rowCount(QModelIndex())-1); - m_container->refreshContainer(); - } -} - -void VersionPage::on_actionInstall_Fabric_triggered() -{ - auto vlist = ENV.metadataIndex()->get("net.fabricmc.fabric-loader"); - if(!vlist) - { - return; - } - VersionSelectDialog vselect(vlist.get(), tr("Select Fabric Loader version"), this); - vselect.setEmptyString(tr("No Fabric Loader versions are currently available.")); - vselect.setEmptyErrorString(tr("Couldn't load or download the Fabric Loader version lists!")); - - auto currentVersion = m_profile->getComponentVersion("net.fabricmc.fabric-loader"); - if(!currentVersion.isEmpty()) - { - vselect.setCurrentVersion(currentVersion); - } - - if (vselect.exec() && vselect.selectedVersion()) - { - auto vsn = vselect.selectedVersion(); - m_profile->setComponentVersion("net.fabricmc.fabric-loader", vsn->descriptor()); - m_profile->resolve(Net::Mode::Online); - preselect(m_profile->rowCount(QModelIndex())-1); - m_container->refreshContainer(); - } -} - -void VersionPage::on_actionAdd_Empty_triggered() -{ - NewComponentDialog compdialog(QString(), QString(), this); - QStringList blacklist; - for(int i = 0; i < m_profile->rowCount(); i++) - { - auto comp = m_profile->getComponent(i); - blacklist.push_back(comp->getID()); - } - compdialog.setBlacklist(blacklist); - if (compdialog.exec()) - { - qDebug() << "name:" << compdialog.name(); - qDebug() << "uid:" << compdialog.uid(); - m_profile->installEmpty(compdialog.uid(), compdialog.name()); - } -} - -void VersionPage::on_actionInstall_LiteLoader_triggered() -{ - auto vlist = ENV.metadataIndex()->get("com.mumfrey.liteloader"); - if(!vlist) - { - return; - } - VersionSelectDialog vselect(vlist.get(), tr("Select LiteLoader version"), this); - vselect.setExactFilter(BaseVersionList::ParentVersionRole, m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") + m_profile->getComponentVersion("net.minecraft")); - vselect.setEmptyErrorString(tr("Couldn't load or download the LiteLoader version lists!")); - - auto currentVersion = m_profile->getComponentVersion("com.mumfrey.liteloader"); - if(!currentVersion.isEmpty()) - { - vselect.setCurrentVersion(currentVersion); - } - - if (vselect.exec() && vselect.selectedVersion()) - { - auto vsn = vselect.selectedVersion(); - m_profile->setComponentVersion("com.mumfrey.liteloader", vsn->descriptor()); - m_profile->resolve(Net::Mode::Online); - // m_profile->installVersion(vselect.selectedVersion()); - preselect(m_profile->rowCount(QModelIndex())-1); - m_container->refreshContainer(); - } -} - -void VersionPage::on_actionLibrariesFolder_triggered() -{ - DesktopServices::openDirectory(m_inst->getLocalLibraryPath(), true); -} - -void VersionPage::on_actionMinecraftFolder_triggered() -{ - DesktopServices::openDirectory(m_inst->gameRoot(), true); -} - -void VersionPage::versionCurrent(const QModelIndex ¤t, const QModelIndex &previous) -{ - currentIdx = current.row(); - updateButtons(currentIdx); -} - -void VersionPage::preselect(int row) -{ - if(row < 0) - { - row = 0; - } - if(row >= m_profile->rowCount(QModelIndex())) - { - row = m_profile->rowCount(QModelIndex()) - 1; - } - if(row < 0) - { - return; - } - auto model_index = m_profile->index(row); - ui->packageView->selectionModel()->select(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); - updateButtons(row); -} - -void VersionPage::onGameUpdateError(QString error) -{ - CustomMessageBox::selectable(this, tr("Error updating instance"), error, QMessageBox::Warning)->show(); -} - -Component * VersionPage::current() -{ - auto row = currentRow(); - if(row < 0) - { - return nullptr; - } - return m_profile->getComponent(row); -} - -int VersionPage::currentRow() -{ - if (ui->packageView->selectionModel()->selectedRows().isEmpty()) - { - return -1; - } - return ui->packageView->selectionModel()->selectedRows().first().row(); -} - -void VersionPage::on_actionCustomize_triggered() -{ - auto version = currentRow(); - if(version == -1) - { - return; - } - auto patch = m_profile->getComponent(version); - if(!patch->getVersionFile()) - { - // TODO: wait for the update task to finish here... - return; - } - if(!m_profile->customize(version)) - { - // TODO: some error box here - } - updateButtons(); - preselect(currentIdx); -} - -void VersionPage::on_actionEdit_triggered() -{ - auto version = current(); - if(!version) - { - return; - } - auto filename = version->getFilename(); - if(!QFileInfo::exists(filename)) - { - qWarning() << "file" << filename << "can't be opened for editing, doesn't exist!"; - return; - } - MMC->openJsonEditor(filename); -} - -void VersionPage::on_actionRevert_triggered() -{ - auto version = currentRow(); - if(version == -1) - { - return; - } - if(!m_profile->revertToBase(version)) - { - // TODO: some error box here - } - updateButtons(); - preselect(currentIdx); - m_container->refreshContainer(); -} - -void VersionPage::onFilterTextChanged(const QString &newContents) -{ - m_filterModel->setFilterFixedString(newContents); -} - -#include "VersionPage.moc" - diff --git a/application/pages/instance/VersionPage.h b/application/pages/instance/VersionPage.h deleted file mode 100644 index b5b4a6f5..00000000 --- a/application/pages/instance/VersionPage.h +++ /dev/null @@ -1,104 +0,0 @@ -/* 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. - */ - -#pragma once - -#include <QMainWindow> - -#include "minecraft/MinecraftInstance.h" -#include "minecraft/PackProfile.h" -#include "pages/BasePage.h" - -namespace Ui -{ -class VersionPage; -} - -class VersionPage : public QMainWindow, public BasePage -{ - Q_OBJECT - -public: - explicit VersionPage(MinecraftInstance *inst, QWidget *parent = 0); - virtual ~VersionPage(); - virtual QString displayName() const override - { - return tr("Version"); - } - virtual QIcon icon() const override; - virtual QString id() const override - { - return "version"; - } - virtual QString helpPage() const override - { - return "Instance-Version"; - } - virtual bool shouldDisplay() const override; - -private slots: - void on_actionChange_version_triggered(); - void on_actionInstall_Forge_triggered(); - void on_actionInstall_Fabric_triggered(); - void on_actionAdd_Empty_triggered(); - void on_actionInstall_LiteLoader_triggered(); - void on_actionReload_triggered(); - void on_actionRemove_triggered(); - void on_actionMove_up_triggered(); - void on_actionMove_down_triggered(); - void on_actionAdd_to_Minecraft_jar_triggered(); - void on_actionReplace_Minecraft_jar_triggered(); - void on_actionRevert_triggered(); - void on_actionEdit_triggered(); - void on_actionInstall_mods_triggered(); - void on_actionCustomize_triggered(); - void on_actionDownload_All_triggered(); - - void on_actionMinecraftFolder_triggered(); - void on_actionLibrariesFolder_triggered(); - - void updateVersionControls(); - -private: - Component * current(); - int currentRow(); - void updateButtons(int row = -1); - void preselect(int row = 0); - int doUpdate(); - -protected: - QMenu * createPopupMenu() override; - - /// FIXME: this shouldn't be necessary! - bool reloadPackProfile(); - -private: - Ui::VersionPage *ui; - QSortFilterProxyModel *m_filterModel; - std::shared_ptr<PackProfile> m_profile; - MinecraftInstance *m_inst; - int currentIdx = 0; - bool controlsEnabled = false; - -public slots: - void versionCurrent(const QModelIndex ¤t, const QModelIndex &previous); - -private slots: - void updateRunningStatus(bool running); - void onGameUpdateError(QString error); - void packageCurrent(const QModelIndex ¤t, const QModelIndex &previous); - void showContextMenu(const QPoint &pos); - void onFilterTextChanged(const QString & newContents); -}; diff --git a/application/pages/instance/VersionPage.ui b/application/pages/instance/VersionPage.ui deleted file mode 100644 index 84d06e2e..00000000 --- a/application/pages/instance/VersionPage.ui +++ /dev/null @@ -1,285 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>VersionPage</class> - <widget class="QMainWindow" name="VersionPage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>961</width> - <height>1091</height> - </rect> - </property> - <widget class="QWidget" name="centralwidget"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="ModListView" name="packageView"> - <property name="verticalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOn</enum> - </property> - <property name="horizontalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOff</enum> - </property> - <property name="sortingEnabled"> - <bool>false</bool> - </property> - <property name="headerHidden"> - <bool>false</bool> - </property> - <attribute name="headerVisible"> - <bool>true</bool> - </attribute> - </widget> - </item> - <item> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="1"> - <widget class="QLineEdit" name="filterEdit"> - <property name="clearButtonEnabled"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="filterLabel"> - <property name="text"> - <string>Filter:</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="MCModInfoFrame" name="frame"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <widget class="WideBar" name="toolBar"> - <property name="windowTitle"> - <string>Actions</string> - </property> - <property name="allowedAreas"> - <set>Qt::LeftToolBarArea|Qt::RightToolBarArea</set> - </property> - <property name="toolButtonStyle"> - <enum>Qt::ToolButtonTextOnly</enum> - </property> - <property name="floatable"> - <bool>false</bool> - </property> - <attribute name="toolBarArea"> - <enum>RightToolBarArea</enum> - </attribute> - <attribute name="toolBarBreak"> - <bool>false</bool> - </attribute> - <addaction name="actionChange_version"/> - <addaction name="actionMove_up"/> - <addaction name="actionMove_down"/> - <addaction name="actionRemove"/> - <addaction name="separator"/> - <addaction name="actionCustomize"/> - <addaction name="actionEdit"/> - <addaction name="actionRevert"/> - <addaction name="separator"/> - <addaction name="actionInstall_Forge"/> - <addaction name="actionInstall_Fabric"/> - <addaction name="actionInstall_LiteLoader"/> - <addaction name="actionInstall_mods"/> - <addaction name="separator"/> - <addaction name="actionAdd_to_Minecraft_jar"/> - <addaction name="actionReplace_Minecraft_jar"/> - <addaction name="actionAdd_Empty"/> - <addaction name="separator"/> - <addaction name="actionMinecraftFolder"/> - <addaction name="actionLibrariesFolder"/> - <addaction name="separator"/> - <addaction name="actionReload"/> - <addaction name="actionDownload_All"/> - </widget> - <action name="actionChange_version"> - <property name="text"> - <string>Change version</string> - </property> - <property name="toolTip"> - <string>Change version of the selected package.</string> - </property> - </action> - <action name="actionMove_up"> - <property name="text"> - <string>Move up</string> - </property> - <property name="toolTip"> - <string>Make the selected package apply sooner.</string> - </property> - </action> - <action name="actionMove_down"> - <property name="text"> - <string>Move down</string> - </property> - <property name="toolTip"> - <string>Make the selected package apply later.</string> - </property> - </action> - <action name="actionRemove"> - <property name="text"> - <string>Remove</string> - </property> - <property name="toolTip"> - <string>Remove selected package from the instance.</string> - </property> - </action> - <action name="actionCustomize"> - <property name="text"> - <string>Customize</string> - </property> - <property name="toolTip"> - <string>Customize selected package.</string> - </property> - </action> - <action name="actionEdit"> - <property name="text"> - <string>Edit</string> - </property> - <property name="toolTip"> - <string>Edit selected package.</string> - </property> - </action> - <action name="actionRevert"> - <property name="text"> - <string>Revert</string> - </property> - <property name="toolTip"> - <string>Revert the selected package to default.</string> - </property> - </action> - <action name="actionInstall_Forge"> - <property name="text"> - <string>Install Forge</string> - </property> - <property name="toolTip"> - <string>Install the Minecraft Forge package.</string> - </property> - </action> - <action name="actionInstall_Fabric"> - <property name="text"> - <string>Install Fabric</string> - </property> - <property name="toolTip"> - <string>Install the Fabric Loader package.</string> - </property> - </action> - <action name="actionInstall_LiteLoader"> - <property name="text"> - <string>Install LiteLoader</string> - </property> - <property name="toolTip"> - <string>Install the LiteLoader package.</string> - </property> - </action> - <action name="actionInstall_mods"> - <property name="text"> - <string>Install mods</string> - </property> - <property name="toolTip"> - <string>Install normal mods.</string> - </property> - </action> - <action name="actionAdd_to_Minecraft_jar"> - <property name="text"> - <string>Add to Minecraft.jar</string> - </property> - <property name="toolTip"> - <string>Add a mod into the Minecraft jar file.</string> - </property> - </action> - <action name="actionReplace_Minecraft_jar"> - <property name="text"> - <string>Replace Minecraft.jar</string> - </property> - </action> - <action name="actionAdd_Empty"> - <property name="text"> - <string>Add Empty</string> - </property> - <property name="toolTip"> - <string>Add an empty custom package.</string> - </property> - </action> - <action name="actionReload"> - <property name="text"> - <string>Reload</string> - </property> - <property name="toolTip"> - <string>Reload all packages.</string> - </property> - </action> - <action name="actionDownload_All"> - <property name="text"> - <string>Download All</string> - </property> - <property name="toolTip"> - <string>Download the files needed to launch the instance now.</string> - </property> - </action> - <action name="actionMinecraftFolder"> - <property name="text"> - <string>Open .minecraft</string> - </property> - <property name="toolTip"> - <string>Open the instance's .minecraft folder.</string> - </property> - </action> - <action name="actionLibrariesFolder"> - <property name="text"> - <string>Open libraries</string> - </property> - <property name="toolTip"> - <string>Open the instance's local libraries folder.</string> - </property> - </action> - </widget> - <customwidgets> - <customwidget> - <class>ModListView</class> - <extends>QTreeView</extends> - <header>widgets/ModListView.h</header> - </customwidget> - <customwidget> - <class>MCModInfoFrame</class> - <extends>QFrame</extends> - <header>widgets/MCModInfoFrame.h</header> - <container>1</container> - </customwidget> - <customwidget> - <class>WideBar</class> - <extends>QToolBar</extends> - <header>widgets/WideBar.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> diff --git a/application/pages/instance/WorldListPage.cpp b/application/pages/instance/WorldListPage.cpp deleted file mode 100644 index 119cff3e..00000000 --- a/application/pages/instance/WorldListPage.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* Copyright 2015-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 "WorldListPage.h" -#include "ui_WorldListPage.h" -#include "minecraft/WorldList.h" -#include <DesktopServices.h> -#include <QEvent> -#include <QMenu> -#include <QKeyEvent> -#include <QClipboard> -#include <QMessageBox> -#include <QTreeView> -#include <QInputDialog> -#include <tools/MCEditTool.h> - -#include "MultiMC.h" -#include <GuiUtil.h> -#include <QProcess> -#include <FileSystem.h> - -class WorldListProxyModel : public QSortFilterProxyModel -{ - Q_OBJECT - -public: - WorldListProxyModel(QObject *parent) : QSortFilterProxyModel(parent) {} - - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const - { - QModelIndex sourceIndex = mapToSource(index); - - if (index.column() == 0 && role == Qt::DecorationRole) - { - WorldList *worlds = qobject_cast<WorldList *>(sourceModel()); - auto iconFile = worlds->data(sourceIndex, WorldList::IconFileRole).toString(); - if(iconFile.isNull()) { - // NOTE: Minecraft uses the same placeholder for servers AND worlds - return MMC->getThemedIcon("unknown_server"); - } - return QIcon(iconFile); - } - - return sourceIndex.data(role); - } -}; - - -WorldListPage::WorldListPage(BaseInstance *inst, std::shared_ptr<WorldList> worlds, QWidget *parent) - : QMainWindow(parent), m_inst(inst), ui(new Ui::WorldListPage), m_worlds(worlds) -{ - ui->setupUi(this); - - ui->toolBar->insertSpacer(ui->actionRefresh); - - WorldListProxyModel * proxy = new WorldListProxyModel(this); - proxy->setSortCaseSensitivity(Qt::CaseInsensitive); - proxy->setSourceModel(m_worlds.get()); - ui->worldTreeView->setSortingEnabled(true); - ui->worldTreeView->setModel(proxy); - ui->worldTreeView->installEventFilter(this); - ui->worldTreeView->setContextMenuPolicy(Qt::CustomContextMenu); - ui->worldTreeView->setIconSize(QSize(64,64)); - connect(ui->worldTreeView, &QTreeView::customContextMenuRequested, this, &WorldListPage::ShowContextMenu); - - auto head = ui->worldTreeView->header(); - head->setSectionResizeMode(0, QHeaderView::Stretch); - head->setSectionResizeMode(1, QHeaderView::ResizeToContents); - - connect(ui->worldTreeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &WorldListPage::worldChanged); - worldChanged(QModelIndex(), QModelIndex()); -} - -void WorldListPage::openedImpl() -{ - m_worlds->startWatching(); -} - -void WorldListPage::closedImpl() -{ - m_worlds->stopWatching(); -} - -WorldListPage::~WorldListPage() -{ - m_worlds->stopWatching(); - delete ui; -} - -void WorldListPage::ShowContextMenu(const QPoint& pos) -{ - auto menu = ui->toolBar->createContextMenu(this, tr("Context menu")); - menu->exec(ui->worldTreeView->mapToGlobal(pos)); - delete menu; -} - -QMenu * WorldListPage::createPopupMenu() -{ - QMenu* filteredMenu = QMainWindow::createPopupMenu(); - filteredMenu->removeAction( ui->toolBar->toggleViewAction() ); - return filteredMenu; -} - -bool WorldListPage::shouldDisplay() const -{ - return true; -} - -bool WorldListPage::worldListFilter(QKeyEvent *keyEvent) -{ - switch (keyEvent->key()) - { - case Qt::Key_Delete: - on_actionRemove_triggered(); - return true; - default: - break; - } - return QWidget::eventFilter(ui->worldTreeView, keyEvent); -} - -bool WorldListPage::eventFilter(QObject *obj, QEvent *ev) -{ - if (ev->type() != QEvent::KeyPress) - { - return QWidget::eventFilter(obj, ev); - } - QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev); - if (obj == ui->worldTreeView) - return worldListFilter(keyEvent); - return QWidget::eventFilter(obj, ev); -} - -void WorldListPage::on_actionRemove_triggered() -{ - auto proxiedIndex = getSelectedWorld(); - - if(!proxiedIndex.isValid()) - return; - - auto result = QMessageBox::question(this, - tr("Are you sure?"), - tr("This will remove the selected world permenantly.\n" - "The world will be gone forever (A LONG TIME).\n" - "\n" - "Do you want to continue?")); - if(result != QMessageBox::Yes) - { - return; - } - m_worlds->stopWatching(); - m_worlds->deleteWorld(proxiedIndex.row()); - m_worlds->startWatching(); -} - -void WorldListPage::on_actionView_Folder_triggered() -{ - DesktopServices::openDirectory(m_worlds->dir().absolutePath(), true); -} - -void WorldListPage::on_actionDatapacks_triggered() -{ - QModelIndex index = getSelectedWorld(); - - if (!index.isValid()) - { - return; - } - - if(!worldSafetyNagQuestion()) - return; - - auto fullPath = m_worlds->data(index, WorldList::FolderRole).toString(); - - DesktopServices::openDirectory(FS::PathCombine(fullPath, "datapacks"), true); -} - - -void WorldListPage::on_actionReset_Icon_triggered() -{ - auto proxiedIndex = getSelectedWorld(); - - if(!proxiedIndex.isValid()) - return; - - if(m_worlds->resetIcon(proxiedIndex.row())) { - ui->actionReset_Icon->setEnabled(false); - } -} - - -QModelIndex WorldListPage::getSelectedWorld() -{ - auto index = ui->worldTreeView->selectionModel()->currentIndex(); - - auto proxy = (QSortFilterProxyModel *) ui->worldTreeView->model(); - return proxy->mapToSource(index); -} - -void WorldListPage::on_actionCopy_Seed_triggered() -{ - QModelIndex index = getSelectedWorld(); - - if (!index.isValid()) - { - return; - } - int64_t seed = m_worlds->data(index, WorldList::SeedRole).toLongLong(); - MMC->clipboard()->setText(QString::number(seed)); -} - -void WorldListPage::on_actionMCEdit_triggered() -{ - if(m_mceditStarting) - return; - - auto mcedit = MMC->mcedit(); - - const QString mceditPath = mcedit->path(); - - QModelIndex index = getSelectedWorld(); - - if (!index.isValid()) - { - return; - } - - if(!worldSafetyNagQuestion()) - return; - - auto fullPath = m_worlds->data(index, WorldList::FolderRole).toString(); - - auto program = mcedit->getProgramPath(); - if(program.size()) - { -#ifdef Q_OS_WIN32 - if(!QProcess::startDetached(program, {fullPath}, mceditPath)) - { - mceditError(); - } -#else - m_mceditProcess.reset(new LoggedProcess()); - m_mceditProcess->setDetachable(true); - connect(m_mceditProcess.get(), &LoggedProcess::stateChanged, this, &WorldListPage::mceditState); - m_mceditProcess->start(program, {fullPath}); - m_mceditProcess->setWorkingDirectory(mceditPath); - m_mceditStarting = true; -#endif - } - else - { - QMessageBox::warning( - this->parentWidget(), - tr("No MCEdit found or set up!"), - tr("You do not have MCEdit set up or it was moved.\nYou can set it up in the global settings.") - ); - } -} - -void WorldListPage::mceditError() -{ - QMessageBox::warning( - this->parentWidget(), - tr("MCEdit failed to start!"), - tr("MCEdit failed to start.\nIt may be necessary to reinstall it.") - ); -} - -void WorldListPage::mceditState(LoggedProcess::State state) -{ - bool failed = false; - switch(state) - { - case LoggedProcess::NotRunning: - case LoggedProcess::Starting: - return; - case LoggedProcess::FailedToStart: - case LoggedProcess::Crashed: - case LoggedProcess::Aborted: - { - failed = true; - } - case LoggedProcess::Running: - case LoggedProcess::Finished: - { - m_mceditStarting = false; - break; - } - } - if(failed) - { - mceditError(); - } -} - -void WorldListPage::worldChanged(const QModelIndex ¤t, const QModelIndex &previous) -{ - QModelIndex index = getSelectedWorld(); - bool enable = index.isValid(); - ui->actionCopy_Seed->setEnabled(enable); - ui->actionMCEdit->setEnabled(enable); - ui->actionRemove->setEnabled(enable); - ui->actionCopy->setEnabled(enable); - ui->actionRename->setEnabled(enable); - ui->actionDatapacks->setEnabled(enable); - bool hasIcon = !index.data(WorldList::IconFileRole).isNull(); - ui->actionReset_Icon->setEnabled(enable && hasIcon); -} - -void WorldListPage::on_actionAdd_triggered() -{ - auto list = GuiUtil::BrowseForFiles( - displayName(), - tr("Select a Minecraft world zip"), - tr("Minecraft World Zip File (*.zip)"), QString(), this->parentWidget()); - if (!list.empty()) - { - m_worlds->stopWatching(); - for (auto filename : list) - { - m_worlds->installWorld(QFileInfo(filename)); - } - m_worlds->startWatching(); - } -} - -bool WorldListPage::isWorldSafe(QModelIndex) -{ - return !m_inst->isRunning(); -} - -bool WorldListPage::worldSafetyNagQuestion() -{ - if(!isWorldSafe(getSelectedWorld())) - { - auto result = QMessageBox::question(this, tr("Copy World"), tr("Changing a world while Minecraft is running is potentially unsafe.\nDo you wish to proceed?")); - if(result == QMessageBox::No) - { - return false; - } - } - return true; -} - - -void WorldListPage::on_actionCopy_triggered() -{ - QModelIndex index = getSelectedWorld(); - if (!index.isValid()) - { - return; - } - - if(!worldSafetyNagQuestion()) - return; - - auto worldVariant = m_worlds->data(index, WorldList::ObjectRole); - auto world = (World *) worldVariant.value<void *>(); - bool ok = false; - QString name = QInputDialog::getText(this, tr("World name"), tr("Enter a new name for the copy."), QLineEdit::Normal, world->name(), &ok); - - if (ok && name.length() > 0) - { - world->install(m_worlds->dir().absolutePath(), name); - } -} - -void WorldListPage::on_actionRename_triggered() -{ - QModelIndex index = getSelectedWorld(); - if (!index.isValid()) - { - return; - } - - if(!worldSafetyNagQuestion()) - return; - - auto worldVariant = m_worlds->data(index, WorldList::ObjectRole); - auto world = (World *) worldVariant.value<void *>(); - - bool ok = false; - QString name = QInputDialog::getText(this, tr("World name"), tr("Enter a new world name."), QLineEdit::Normal, world->name(), &ok); - - if (ok && name.length() > 0) - { - world->rename(name); - } -} - -void WorldListPage::on_actionRefresh_triggered() -{ - m_worlds->update(); -} - -#include "WorldListPage.moc" diff --git a/application/pages/instance/WorldListPage.h b/application/pages/instance/WorldListPage.h deleted file mode 100644 index 4fc9aa09..00000000 --- a/application/pages/instance/WorldListPage.h +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright 2015-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. - */ - -#pragma once - -#include <QMainWindow> - -#include "minecraft/MinecraftInstance.h" -#include "pages/BasePage.h" -#include <MultiMC.h> -#include <LoggedProcess.h> - -class WorldList; -namespace Ui -{ -class WorldListPage; -} - -class WorldListPage : public QMainWindow, public BasePage -{ - Q_OBJECT - -public: - explicit WorldListPage( - BaseInstance *inst, - std::shared_ptr<WorldList> worlds, - QWidget *parent = 0 - ); - virtual ~WorldListPage(); - - virtual QString displayName() const override - { - return tr("Worlds"); - } - virtual QIcon icon() const override - { - return MMC->getThemedIcon("worlds"); - } - virtual QString id() const override - { - return "worlds"; - } - virtual QString helpPage() const override - { - return "Worlds"; - } - virtual bool shouldDisplay() const override; - - virtual void openedImpl() override; - virtual void closedImpl() override; - -protected: - bool eventFilter(QObject *obj, QEvent *ev) override; - bool worldListFilter(QKeyEvent *ev); - QMenu * createPopupMenu() override; - -protected: - BaseInstance *m_inst; - -private: - QModelIndex getSelectedWorld(); - bool isWorldSafe(QModelIndex index); - bool worldSafetyNagQuestion(); - void mceditError(); - -private: - Ui::WorldListPage *ui; - std::shared_ptr<WorldList> m_worlds; - unique_qobject_ptr<LoggedProcess> m_mceditProcess; - bool m_mceditStarting = false; - -private slots: - void on_actionCopy_Seed_triggered(); - void on_actionMCEdit_triggered(); - void on_actionRemove_triggered(); - void on_actionAdd_triggered(); - void on_actionCopy_triggered(); - void on_actionRename_triggered(); - void on_actionRefresh_triggered(); - void on_actionView_Folder_triggered(); - void on_actionDatapacks_triggered(); - void on_actionReset_Icon_triggered(); - void worldChanged(const QModelIndex ¤t, const QModelIndex &previous); - void mceditState(LoggedProcess::State state); - - void ShowContextMenu(const QPoint &pos); -}; diff --git a/application/pages/instance/WorldListPage.ui b/application/pages/instance/WorldListPage.ui deleted file mode 100644 index ed078d94..00000000 --- a/application/pages/instance/WorldListPage.ui +++ /dev/null @@ -1,161 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>WorldListPage</class> - <widget class="QMainWindow" name="WorldListPage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>800</width> - <height>600</height> - </rect> - </property> - <widget class="QWidget" name="centralwidget"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QTreeView" name="worldTreeView"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="acceptDrops"> - <bool>true</bool> - </property> - <property name="dragDropMode"> - <enum>QAbstractItemView::DragDrop</enum> - </property> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="rootIsDecorated"> - <bool>false</bool> - </property> - <property name="itemsExpandable"> - <bool>false</bool> - </property> - <property name="sortingEnabled"> - <bool>true</bool> - </property> - <property name="allColumnsShowFocus"> - <bool>true</bool> - </property> - <attribute name="headerStretchLastSection"> - <bool>false</bool> - </attribute> - </widget> - </item> - </layout> - </widget> - <widget class="WideBar" name="toolBar"> - <property name="windowTitle"> - <string>Actions</string> - </property> - <property name="allowedAreas"> - <set>Qt::LeftToolBarArea|Qt::RightToolBarArea</set> - </property> - <property name="toolButtonStyle"> - <enum>Qt::ToolButtonTextOnly</enum> - </property> - <property name="floatable"> - <bool>false</bool> - </property> - <attribute name="toolBarArea"> - <enum>RightToolBarArea</enum> - </attribute> - <attribute name="toolBarBreak"> - <bool>false</bool> - </attribute> - <addaction name="actionAdd"/> - <addaction name="separator"/> - <addaction name="actionRename"/> - <addaction name="actionCopy"/> - <addaction name="actionRemove"/> - <addaction name="actionMCEdit"/> - <addaction name="actionDatapacks"/> - <addaction name="actionReset_Icon"/> - <addaction name="separator"/> - <addaction name="actionCopy_Seed"/> - <addaction name="actionRefresh"/> - <addaction name="actionView_Folder"/> - </widget> - <action name="actionAdd"> - <property name="text"> - <string>Add</string> - </property> - </action> - <action name="actionRename"> - <property name="text"> - <string>Rename</string> - </property> - </action> - <action name="actionCopy"> - <property name="text"> - <string>Copy</string> - </property> - </action> - <action name="actionRemove"> - <property name="text"> - <string>Remove</string> - </property> - </action> - <action name="actionMCEdit"> - <property name="text"> - <string>MCEdit</string> - </property> - </action> - <action name="actionCopy_Seed"> - <property name="text"> - <string>Copy Seed</string> - </property> - </action> - <action name="actionRefresh"> - <property name="text"> - <string>Refresh</string> - </property> - </action> - <action name="actionView_Folder"> - <property name="text"> - <string>View Folder</string> - </property> - </action> - <action name="actionReset_Icon"> - <property name="text"> - <string>Reset Icon</string> - </property> - <property name="toolTip"> - <string>Remove world icon to make the game re-generate it on next load.</string> - </property> - </action> - <action name="actionDatapacks"> - <property name="text"> - <string>Datapacks</string> - </property> - <property name="toolTip"> - <string>Manage datapacks inside the world.</string> - </property> - </action> - </widget> - <customwidgets> - <customwidget> - <class>WideBar</class> - <extends>QToolBar</extends> - <header>widgets/WideBar.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> |