diff options
| author | Mehmet Samet Duman <yongdohyun@projecttick.org> | 2026-04-02 18:45:07 +0300 |
|---|---|---|
| committer | Mehmet Samet Duman <yongdohyun@projecttick.org> | 2026-04-02 18:45:07 +0300 |
| commit | 31b9a8949ed0a288143e23bf739f2eb64fdc63be (patch) | |
| tree | 8a984fa143c38fccad461a77792d6864f3e82cd3 /meshmc/launcher/ui/pages/instance/VersionPage.cpp | |
| parent | 934382c8a1ce738589dee9ee0f14e1cec812770e (diff) | |
| parent | fad6a1066616b69d7f5fef01178efdf014c59537 (diff) | |
| download | Project-Tick-31b9a8949ed0a288143e23bf739f2eb64fdc63be.tar.gz Project-Tick-31b9a8949ed0a288143e23bf739f2eb64fdc63be.zip | |
Add 'meshmc/' from commit 'fad6a1066616b69d7f5fef01178efdf014c59537'
git-subtree-dir: meshmc
git-subtree-mainline: 934382c8a1ce738589dee9ee0f14e1cec812770e
git-subtree-split: fad6a1066616b69d7f5fef01178efdf014c59537
Diffstat (limited to 'meshmc/launcher/ui/pages/instance/VersionPage.cpp')
| -rw-r--r-- | meshmc/launcher/ui/pages/instance/VersionPage.cpp | 809 |
1 files changed, 809 insertions, 0 deletions
diff --git a/meshmc/launcher/ui/pages/instance/VersionPage.cpp b/meshmc/launcher/ui/pages/instance/VersionPage.cpp new file mode 100644 index 0000000000..5ad383b79c --- /dev/null +++ b/meshmc/launcher/ui/pages/instance/VersionPage.cpp @@ -0,0 +1,809 @@ +/* SPDX-FileCopyrightText: 2026 Project Tick + * SPDX-FileContributor: Project Tick + * SPDX-License-Identifier: GPL-3.0-or-later + * + * MeshMC - A Custom Launcher for Minecraft + * Copyright (C) 2026 Project Tick + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Application.h" + +#include <QMessageBox> +#include <QLabel> +#include <QEvent> +#include <QKeyEvent> +#include <QMenu> +#include <QAbstractItemModel> +#include <QMessageBox> +#include <QListView> +#include <QString> +#include <QUrl> + +#include "VersionPage.h" +#include "ui_VersionPage.h" + +#include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/VersionSelectDialog.h" +#include "ui/dialogs/NewComponentDialog.h" +#include "ui/dialogs/ProgressDialog.h" + +#include "ui/GuiUtil.h" + +#include "minecraft/PackProfile.h" +#include "minecraft/auth/AccountList.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 APPLICATION->getThemedIcon("status-yellow"); + } else if (string == "error") { + return APPLICATION->getThemedIcon("status-bad"); + } + } + return APPLICATION->getThemedIcon("status-good"); + } + return var; + } + private slots: + void widgetGone() + { + m_parentWidget = nullptr; + } + + private: + QWidget* m_parentWidget = nullptr; +}; + +QIcon VersionPage::icon() const +{ + return APPLICATION->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& current, + 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 supportsNeoForge = minecraftVersion >= Version("1.20.1"); + ui->actionInstall_NeoForge->setEnabled(controlsEnabled && supportsNeoForge); + + bool supportsQuilt = minecraftVersion >= Version("1.14"); + ui->actionInstall_Quilt->setEnabled(controlsEnabled && supportsQuilt); + + 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)"), + APPLICATION->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)"), + APPLICATION->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 == "net.neoforged") { + on_actionInstall_NeoForge_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 (!APPLICATION->accounts()->anyAccountIsValid()) { + CustomMessageBox::selectable( + this, tr("Error"), + tr("MeshMC 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() +{ + // Forge conflicts with Fabric, NeoForge, and Quilt + if (!m_profile->getComponentVersion("net.fabricmc.fabric-loader") + .isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("Forge is incompatible with Fabric Loader. " + "Please remove Fabric Loader first.")); + return; + } + if (!m_profile->getComponentVersion("net.neoforged").isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("Forge is incompatible with NeoForge. Please " + "remove NeoForge first.")); + return; + } + if (!m_profile->getComponentVersion("org.quiltmc.quilt-loader").isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("Forge is incompatible with Quilt Loader. " + "Please remove Quilt Loader first.")); + return; + } + + auto vlist = APPLICATION->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() +{ + // Fabric conflicts with Forge, NeoForge, and Quilt + if (!m_profile->getComponentVersion("net.minecraftforge").isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("Fabric Loader is incompatible with Forge. " + "Please remove Forge first.")); + return; + } + if (!m_profile->getComponentVersion("net.neoforged").isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("Fabric Loader is incompatible with NeoForge. " + "Please remove NeoForge first.")); + return; + } + if (!m_profile->getComponentVersion("org.quiltmc.quilt-loader").isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("Fabric Loader is incompatible with Quilt " + "Loader. Please remove Quilt Loader first.")); + return; + } + + auto vlist = + APPLICATION->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_actionInstall_NeoForge_triggered() +{ + // NeoForge conflicts with Forge, Fabric, and Quilt + if (!m_profile->getComponentVersion("net.minecraftforge").isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("NeoForge is incompatible with Forge. Please " + "remove Forge first.")); + return; + } + if (!m_profile->getComponentVersion("net.fabricmc.fabric-loader") + .isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("NeoForge is incompatible with Fabric Loader. " + "Please remove Fabric Loader first.")); + return; + } + if (!m_profile->getComponentVersion("org.quiltmc.quilt-loader").isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("NeoForge is incompatible with Quilt Loader. " + "Please remove Quilt Loader first.")); + return; + } + + auto vlist = APPLICATION->metadataIndex()->get("net.neoforged"); + if (!vlist) { + return; + } + VersionSelectDialog vselect(vlist.get(), tr("Select NeoForge version"), + this); + vselect.setExactFilter(BaseVersionList::ParentVersionRole, + m_profile->getComponentVersion("net.minecraft")); + vselect.setEmptyString( + tr("No NeoForge versions are currently available for Minecraft ") + + m_profile->getComponentVersion("net.minecraft")); + vselect.setEmptyErrorString( + tr("Couldn't load or download the NeoForge version lists!")); + + auto currentVersion = m_profile->getComponentVersion("net.neoforged"); + if (!currentVersion.isEmpty()) { + vselect.setCurrentVersion(currentVersion); + } + + if (vselect.exec() && vselect.selectedVersion()) { + auto vsn = vselect.selectedVersion(); + m_profile->setComponentVersion("net.neoforged", vsn->descriptor()); + m_profile->resolve(Net::Mode::Online); + preselect(m_profile->rowCount(QModelIndex()) - 1); + m_container->refreshContainer(); + } +} + +void VersionPage::on_actionInstall_Quilt_triggered() +{ + // Quilt conflicts with Forge, Fabric, and NeoForge + if (!m_profile->getComponentVersion("net.minecraftforge").isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("Quilt Loader is incompatible with Forge. " + "Please remove Forge first.")); + return; + } + if (!m_profile->getComponentVersion("net.fabricmc.fabric-loader") + .isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("Quilt Loader is incompatible with Fabric " + "Loader. Please remove Fabric Loader first.")); + return; + } + if (!m_profile->getComponentVersion("net.neoforged").isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("Quilt Loader is incompatible with NeoForge. " + "Please remove NeoForge first.")); + return; + } + + auto vlist = APPLICATION->metadataIndex()->get("org.quiltmc.quilt-loader"); + if (!vlist) { + return; + } + VersionSelectDialog vselect(vlist.get(), tr("Select Quilt Loader version"), + this); + vselect.setEmptyString( + tr("No Quilt Loader versions are currently available.")); + vselect.setEmptyErrorString( + tr("Couldn't load or download the Quilt Loader version lists!")); + + auto currentVersion = + m_profile->getComponentVersion("org.quiltmc.quilt-loader"); + if (!currentVersion.isEmpty()) { + vselect.setCurrentVersion(currentVersion); + } + + if (vselect.exec() && vselect.selectedVersion()) { + auto vsn = vselect.selectedVersion(); + m_profile->setComponentVersion("org.quiltmc.quilt-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 = APPLICATION->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& current, + 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; + } + APPLICATION->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" |
