refactor: remove old updater
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
This commit is contained in:
		@@ -39,6 +39,7 @@
 | 
			
		||||
#include <QClipboard>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QFileDialog>
 | 
			
		||||
#include <QStandardPaths>
 | 
			
		||||
 | 
			
		||||
#include "ui/dialogs/ProgressDialog.h"
 | 
			
		||||
#include "ui/dialogs/CustomMessageBox.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -83,8 +83,7 @@
 | 
			
		||||
#include <net/Download.h>
 | 
			
		||||
#include <news/NewsChecker.h>
 | 
			
		||||
#include <tools/BaseProfiler.h>
 | 
			
		||||
#include <updater/DownloadTask.h>
 | 
			
		||||
#include <updater/UpdateChecker.h>
 | 
			
		||||
#include <updater/ExternalUpdater.h>
 | 
			
		||||
#include <DesktopServices.h>
 | 
			
		||||
#include "InstanceWindow.h"
 | 
			
		||||
#include "InstancePageProvider.h"
 | 
			
		||||
@@ -99,16 +98,13 @@
 | 
			
		||||
#include "ui/dialogs/NewsDialog.h"
 | 
			
		||||
#include "ui/dialogs/ProgressDialog.h"
 | 
			
		||||
#include "ui/dialogs/AboutDialog.h"
 | 
			
		||||
#include "ui/dialogs/VersionSelectDialog.h"
 | 
			
		||||
#include "ui/dialogs/CustomMessageBox.h"
 | 
			
		||||
#include "ui/dialogs/IconPickerDialog.h"
 | 
			
		||||
#include "ui/dialogs/CopyInstanceDialog.h"
 | 
			
		||||
#include "ui/dialogs/UpdateDialog.h"
 | 
			
		||||
#include "ui/dialogs/EditAccountDialog.h"
 | 
			
		||||
#include "ui/dialogs/ExportInstanceDialog.h"
 | 
			
		||||
#include "ui/themes/ITheme.h"
 | 
			
		||||
 | 
			
		||||
#include "UpdateController.h"
 | 
			
		||||
#include "KonamiCode.h"
 | 
			
		||||
 | 
			
		||||
#include "InstanceImportTask.h"
 | 
			
		||||
@@ -1039,9 +1035,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
 | 
			
		||||
        updateNewsLabel();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if(BuildConfig.UPDATER_ENABLED)
 | 
			
		||||
    {
 | 
			
		||||
    if (BuildConfig.UPDATER_ENABLED) {
 | 
			
		||||
        bool updatesAllowed = APPLICATION->updatesAreAllowed();
 | 
			
		||||
        updatesAllowedChanged(updatesAllowed);
 | 
			
		||||
 | 
			
		||||
@@ -1049,21 +1043,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
 | 
			
		||||
        connect(ui->actionCheckUpdate.operator->(), &QAction::triggered, this, &MainWindow::checkForUpdates);
 | 
			
		||||
 | 
			
		||||
        // set up the updater object.
 | 
			
		||||
        auto updater = APPLICATION->updateChecker();
 | 
			
		||||
        connect(updater.get(), &UpdateChecker::updateAvailable, this, &MainWindow::updateAvailable);
 | 
			
		||||
        connect(updater.get(), &UpdateChecker::noUpdateFound, this, &MainWindow::updateNotAvailable);
 | 
			
		||||
        // if automatic update checks are allowed, start one.
 | 
			
		||||
        if (APPLICATION->settings()->get("AutoUpdate").toBool() && updatesAllowed)
 | 
			
		||||
        {
 | 
			
		||||
            updater->checkForUpdate(APPLICATION->settings()->get("UpdateChannel").toString(), false);
 | 
			
		||||
        }
 | 
			
		||||
        auto updater = APPLICATION->updater();
 | 
			
		||||
 | 
			
		||||
        if (APPLICATION->updateChecker()->getExternalUpdater())
 | 
			
		||||
        {
 | 
			
		||||
            connect(APPLICATION->updateChecker()->getExternalUpdater(),
 | 
			
		||||
                    &ExternalUpdater::canCheckForUpdatesChanged,
 | 
			
		||||
                    this,
 | 
			
		||||
                    &MainWindow::updatesAllowedChanged);
 | 
			
		||||
        if (updater) {
 | 
			
		||||
            connect(updater.get(), &ExternalUpdater::canCheckForUpdatesChanged, this, &MainWindow::updatesAllowedChanged);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1541,32 +1524,6 @@ void MainWindow::updateNewsLabel()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::updateAvailable(GoUpdate::Status status)
 | 
			
		||||
{
 | 
			
		||||
    if(!APPLICATION->updatesAreAllowed())
 | 
			
		||||
    {
 | 
			
		||||
        updateNotAvailable();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    UpdateDialog dlg(true, this);
 | 
			
		||||
    UpdateAction action = (UpdateAction)dlg.exec();
 | 
			
		||||
    switch (action)
 | 
			
		||||
    {
 | 
			
		||||
    case UPDATE_LATER:
 | 
			
		||||
        qDebug() << "Update will be installed later.";
 | 
			
		||||
        break;
 | 
			
		||||
    case UPDATE_NOW:
 | 
			
		||||
        downloadUpdates(status);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::updateNotAvailable()
 | 
			
		||||
{
 | 
			
		||||
    UpdateDialog dlg(false, this);
 | 
			
		||||
    dlg.exec();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QList<int> stringToIntList(const QString &string)
 | 
			
		||||
{
 | 
			
		||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
 | 
			
		||||
@@ -1591,40 +1548,6 @@ QString intListToString(const QList<int> &list)
 | 
			
		||||
    return slist.join(',');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::downloadUpdates(GoUpdate::Status status)
 | 
			
		||||
{
 | 
			
		||||
    if(!APPLICATION->updatesAreAllowed())
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    qDebug() << "Downloading updates.";
 | 
			
		||||
    ProgressDialog updateDlg(this);
 | 
			
		||||
    status.rootPath = APPLICATION->root();
 | 
			
		||||
 | 
			
		||||
    auto dlPath = FS::PathCombine(APPLICATION->root(), "update", "XXXXXX");
 | 
			
		||||
    if (!FS::ensureFilePathExists(dlPath))
 | 
			
		||||
    {
 | 
			
		||||
        CustomMessageBox::selectable(this, tr("Error"), tr("Couldn't create folder for update downloads:\n%1").arg(dlPath), QMessageBox::Warning)->show();
 | 
			
		||||
    }
 | 
			
		||||
    GoUpdate::DownloadTask updateTask(APPLICATION->network(), status, dlPath, &updateDlg);
 | 
			
		||||
    // If the task succeeds, install the updates.
 | 
			
		||||
    if (updateDlg.execWithTask(&updateTask))
 | 
			
		||||
    {
 | 
			
		||||
        /**
 | 
			
		||||
         * NOTE: This disables launching instances until the update either succeeds (and this process exits)
 | 
			
		||||
         * or the update fails (and the control leaves this scope).
 | 
			
		||||
         */
 | 
			
		||||
        APPLICATION->updateIsRunning(true);
 | 
			
		||||
        UpdateController update(this, APPLICATION->root(), updateTask.updateFilesDir(), updateTask.operations());
 | 
			
		||||
        update.installUpdates();
 | 
			
		||||
        APPLICATION->updateIsRunning(false);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        CustomMessageBox::selectable(this, tr("Error"), updateTask.failReason(), QMessageBox::Warning)->show();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::onCatToggled(bool state)
 | 
			
		||||
{
 | 
			
		||||
    setCatBackground(state);
 | 
			
		||||
@@ -1941,8 +1864,7 @@ void MainWindow::checkForUpdates()
 | 
			
		||||
{
 | 
			
		||||
    if(BuildConfig.UPDATER_ENABLED)
 | 
			
		||||
    {
 | 
			
		||||
        auto updater = APPLICATION->updateChecker();
 | 
			
		||||
        updater->checkForUpdate(APPLICATION->settings()->get("UpdateChannel").toString(), true);
 | 
			
		||||
        APPLICATION->triggerUpdateCheck();
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,6 @@
 | 
			
		||||
#include "BaseInstance.h"
 | 
			
		||||
#include "minecraft/auth/MinecraftAccount.h"
 | 
			
		||||
#include "net/NetJob.h"
 | 
			
		||||
#include "updater/GoUpdate.h"
 | 
			
		||||
 | 
			
		||||
class LaunchController;
 | 
			
		||||
class NewsChecker;
 | 
			
		||||
@@ -188,10 +187,6 @@ private slots:
 | 
			
		||||
 | 
			
		||||
    void startTask(Task *task);
 | 
			
		||||
 | 
			
		||||
    void updateAvailable(GoUpdate::Status status);
 | 
			
		||||
 | 
			
		||||
    void updateNotAvailable();
 | 
			
		||||
 | 
			
		||||
    void defaultAccountChanged();
 | 
			
		||||
 | 
			
		||||
    void changeActiveAccount();
 | 
			
		||||
@@ -200,10 +195,6 @@ private slots:
 | 
			
		||||
 | 
			
		||||
    void updateNewsLabel();
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
     * Runs the DownloadTask and installs updates.
 | 
			
		||||
     */
 | 
			
		||||
    void downloadUpdates(GoUpdate::Status status);
 | 
			
		||||
 | 
			
		||||
    void konamiTriggered();
 | 
			
		||||
 | 
			
		||||
@@ -252,4 +243,3 @@ private:
 | 
			
		||||
    // managed by the application object
 | 
			
		||||
    Task *m_versionLoadTask = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,18 @@
 | 
			
		||||
#include "BlockedModsDialog.h"
 | 
			
		||||
#include <QDesktopServices>
 | 
			
		||||
#include <QDialogButtonBox>
 | 
			
		||||
#include <QPushButton>
 | 
			
		||||
#include "Application.h"
 | 
			
		||||
#include "ui_BlockedModsDialog.h"
 | 
			
		||||
 | 
			
		||||
#include "Application.h"
 | 
			
		||||
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QDesktopServices>
 | 
			
		||||
#include <QDialogButtonBox>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QDirIterator>
 | 
			
		||||
#include <QDragEnterEvent>
 | 
			
		||||
#include <QFileDialog>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
#include <QMimeData>
 | 
			
		||||
#include <QPushButton>
 | 
			
		||||
#include <QStandardPaths>
 | 
			
		||||
 | 
			
		||||
BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList<BlockedMod>& mods)
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,7 @@
 | 
			
		||||
#include <QSortFilterProxyModel>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QSaveFile>
 | 
			
		||||
#include <QStack>
 | 
			
		||||
#include "StringUtils.h"
 | 
			
		||||
#include "SeparatorPrefixTree.h"
 | 
			
		||||
#include "Application.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,217 +0,0 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-3.0-only
 | 
			
		||||
/*
 | 
			
		||||
 *  PolyMC - Minecraft Launcher
 | 
			
		||||
 *  Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 *  it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *  the Free Software Foundation, version 3.
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *  You should have received a copy of the GNU General Public License
 | 
			
		||||
 *  along with this program.  If not, see <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 "UpdateDialog.h"
 | 
			
		||||
#include "ui_UpdateDialog.h"
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include "Application.h"
 | 
			
		||||
#include <settings/SettingsObject.h>
 | 
			
		||||
#include <Json.h>
 | 
			
		||||
 | 
			
		||||
#include "BuildConfig.h"
 | 
			
		||||
#include "HoeDown.h"
 | 
			
		||||
 | 
			
		||||
UpdateDialog::UpdateDialog(bool hasUpdate, QWidget *parent) : QDialog(parent), ui(new Ui::UpdateDialog)
 | 
			
		||||
{
 | 
			
		||||
    ui->setupUi(this);
 | 
			
		||||
    auto channel = APPLICATION->settings()->get("UpdateChannel").toString();
 | 
			
		||||
    if(hasUpdate)
 | 
			
		||||
    {
 | 
			
		||||
        ui->label->setText(tr("A new %1 update is available!").arg(channel));
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ui->label->setText(tr("No %1 updates found. You are running the latest version.").arg(channel));
 | 
			
		||||
        ui->btnUpdateNow->setHidden(true);
 | 
			
		||||
        ui->btnUpdateLater->setText(tr("Close"));
 | 
			
		||||
    }
 | 
			
		||||
    ui->changelogBrowser->setHtml(tr("<center><h1>Loading changelog...</h1></center>"));
 | 
			
		||||
    loadChangelog();
 | 
			
		||||
    restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("UpdateDialogGeometry").toByteArray()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UpdateDialog::~UpdateDialog()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UpdateDialog::loadChangelog()
 | 
			
		||||
{
 | 
			
		||||
    auto channel = APPLICATION->settings()->get("UpdateChannel").toString();
 | 
			
		||||
    dljob = new NetJob("Changelog", APPLICATION->network());
 | 
			
		||||
    QString url;
 | 
			
		||||
    if(channel == "stable")
 | 
			
		||||
    {
 | 
			
		||||
        url = QString("https://raw.githubusercontent.com/PrismLauncher/PrismLauncher/%1/changelog.md").arg(channel);
 | 
			
		||||
        m_changelogType = CHANGELOG_MARKDOWN;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        url = QString("https://api.github.com/repos/PrismLauncher/PrismLauncher/compare/%1...%2").arg(BuildConfig.GIT_COMMIT, channel);
 | 
			
		||||
        m_changelogType = CHANGELOG_COMMITS;
 | 
			
		||||
    }
 | 
			
		||||
    dljob->addNetAction(Net::Download::makeByteArray(QUrl(url), &changelogData));
 | 
			
		||||
    connect(dljob.get(), &NetJob::succeeded, this, &UpdateDialog::changelogLoaded);
 | 
			
		||||
    connect(dljob.get(), &NetJob::failed, this, &UpdateDialog::changelogFailed);
 | 
			
		||||
    dljob->start();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString reprocessMarkdown(QByteArray markdown)
 | 
			
		||||
{
 | 
			
		||||
    HoeDown hoedown;
 | 
			
		||||
    QString output = hoedown.process(markdown);
 | 
			
		||||
 | 
			
		||||
    // HACK: easier than customizing hoedown
 | 
			
		||||
    output.replace(QRegularExpression("GH-([0-9]+)"), "<a href=\"https://github.com/PrismLauncher/PrismLauncher/issues/\\1\">GH-\\1</a>");
 | 
			
		||||
    qDebug() << output;
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString reprocessCommits(QByteArray json)
 | 
			
		||||
{
 | 
			
		||||
    auto channel = APPLICATION->settings()->get("UpdateChannel").toString();
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        QString result;
 | 
			
		||||
        auto document = Json::requireDocument(json);
 | 
			
		||||
        auto rootobject = Json::requireObject(document);
 | 
			
		||||
        auto status = Json::requireString(rootobject, "status");
 | 
			
		||||
        auto diff_url = Json::requireString(rootobject, "html_url");
 | 
			
		||||
 | 
			
		||||
        auto print_commits = [&]()
 | 
			
		||||
        {
 | 
			
		||||
            result += "<table cellspacing=0 cellpadding=2 style='border-width: 1px; border-style: solid'>";
 | 
			
		||||
            auto commitarray = Json::requireArray(rootobject, "commits");
 | 
			
		||||
            for(int i = commitarray.size() - 1; i >= 0; i--)
 | 
			
		||||
            {
 | 
			
		||||
                const auto & commitval = commitarray[i];
 | 
			
		||||
                auto commitobj = Json::requireObject(commitval);
 | 
			
		||||
                auto parents_info = Json::ensureArray(commitobj, "parents");
 | 
			
		||||
                // NOTE: this ignores merge commits, because they have more than one parent
 | 
			
		||||
                if(parents_info.size() > 1)
 | 
			
		||||
                {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                auto commit_url = Json::requireString(commitobj, "html_url");
 | 
			
		||||
                auto commit_info = Json::requireObject(commitobj, "commit");
 | 
			
		||||
                auto commit_message = Json::requireString(commit_info, "message");
 | 
			
		||||
                auto lines = commit_message.split('\n');
 | 
			
		||||
                QRegularExpression regexp("(?<prefix>(GH-(?<issuenr>[0-9]+))|(NOISSUE)|(SCRATCH))? *(?<rest>.*) *");
 | 
			
		||||
                auto match = regexp.match(lines.takeFirst(), 0, QRegularExpression::NormalMatch);
 | 
			
		||||
                auto issuenr = match.captured("issuenr");
 | 
			
		||||
                auto prefix = match.captured("prefix");
 | 
			
		||||
                auto rest = match.captured("rest");
 | 
			
		||||
                result += "<tr><td>";
 | 
			
		||||
                if(issuenr.length())
 | 
			
		||||
                {
 | 
			
		||||
                    result += QString("<a href=\"https://github.com/PrismLauncher/PrismLauncher/issues/%1\">GH-%2</a>").arg(issuenr, issuenr);
 | 
			
		||||
                }
 | 
			
		||||
                else if(prefix.length())
 | 
			
		||||
                {
 | 
			
		||||
                    result += QString("<a href=\"%1\">%2</a>").arg(commit_url, prefix);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    result += QString("<a href=\"%1\">NOISSUE</a>").arg(commit_url);
 | 
			
		||||
                }
 | 
			
		||||
                result += "</td>";
 | 
			
		||||
                lines.prepend(rest);
 | 
			
		||||
                result += "<td><p>" + lines.join("<br />") + "</p></td></tr>";
 | 
			
		||||
            }
 | 
			
		||||
            result += "</table>";
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        if(status == "identical")
 | 
			
		||||
        {
 | 
			
		||||
            return QObject::tr("<p>There are no code changes between your current version and latest %1.</p>").arg(channel);
 | 
			
		||||
        }
 | 
			
		||||
        else if(status == "ahead")
 | 
			
		||||
        {
 | 
			
		||||
            result += QObject::tr("<p>Following commits were added since last update:</p>");
 | 
			
		||||
            print_commits();
 | 
			
		||||
        }
 | 
			
		||||
        else if(status == "diverged")
 | 
			
		||||
        {
 | 
			
		||||
            auto commit_ahead = Json::requireInteger(rootobject, "ahead_by");
 | 
			
		||||
            auto commit_behind = Json::requireInteger(rootobject, "behind_by");
 | 
			
		||||
            result += QObject::tr("<p>The update removes %1 commits and adds the following %2:</p>").arg(commit_behind).arg(commit_ahead);
 | 
			
		||||
            print_commits();
 | 
			
		||||
        }
 | 
			
		||||
        result += QObject::tr("<p>You can <a href=\"%1\">look at the changes on github</a>.</p>").arg(diff_url);
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
    catch (const JSONValidationError &e)
 | 
			
		||||
    {
 | 
			
		||||
        qWarning() << "Got an unparseable commit log from github:" << e.what();
 | 
			
		||||
        qDebug() << json;
 | 
			
		||||
    }
 | 
			
		||||
    return QString();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UpdateDialog::changelogLoaded()
 | 
			
		||||
{
 | 
			
		||||
    QString result;
 | 
			
		||||
    switch(m_changelogType)
 | 
			
		||||
    {
 | 
			
		||||
        case CHANGELOG_COMMITS:
 | 
			
		||||
            result = reprocessCommits(changelogData);
 | 
			
		||||
            break;
 | 
			
		||||
        case CHANGELOG_MARKDOWN:
 | 
			
		||||
            result = reprocessMarkdown(changelogData);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    changelogData.clear();
 | 
			
		||||
    ui->changelogBrowser->setHtml(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UpdateDialog::changelogFailed(QString reason)
 | 
			
		||||
{
 | 
			
		||||
    ui->changelogBrowser->setHtml(tr("<p align=\"center\" <span style=\"font-size:22pt;\">Failed to fetch changelog... Error: %1</span></p>").arg(reason));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UpdateDialog::on_btnUpdateLater_clicked()
 | 
			
		||||
{
 | 
			
		||||
    reject();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UpdateDialog::on_btnUpdateNow_clicked()
 | 
			
		||||
{
 | 
			
		||||
    done(UPDATE_NOW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UpdateDialog::closeEvent(QCloseEvent* evt)
 | 
			
		||||
{
 | 
			
		||||
    APPLICATION->settings()->set("UpdateDialogGeometry", saveGeometry().toBase64());
 | 
			
		||||
    QDialog::closeEvent(evt);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,67 +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 <QDialog>
 | 
			
		||||
#include "net/NetJob.h"
 | 
			
		||||
 | 
			
		||||
namespace Ui
 | 
			
		||||
{
 | 
			
		||||
class UpdateDialog;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum UpdateAction
 | 
			
		||||
{
 | 
			
		||||
    UPDATE_LATER = QDialog::Rejected,
 | 
			
		||||
    UPDATE_NOW = QDialog::Accepted,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum ChangelogType
 | 
			
		||||
{
 | 
			
		||||
    CHANGELOG_MARKDOWN,
 | 
			
		||||
    CHANGELOG_COMMITS
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class UpdateDialog : public QDialog
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit UpdateDialog(bool hasUpdate = true, QWidget *parent = 0);
 | 
			
		||||
    ~UpdateDialog();
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
    void on_btnUpdateNow_clicked();
 | 
			
		||||
    void on_btnUpdateLater_clicked();
 | 
			
		||||
 | 
			
		||||
    /// Starts loading the changelog
 | 
			
		||||
    void loadChangelog();
 | 
			
		||||
 | 
			
		||||
    /// Slot for when the chengelog loads successfully.
 | 
			
		||||
    void changelogLoaded();
 | 
			
		||||
 | 
			
		||||
    /// Slot for when the chengelog fails to load...
 | 
			
		||||
    void changelogFailed(QString reason);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void closeEvent(QCloseEvent * ) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Ui::UpdateDialog *ui;
 | 
			
		||||
    QByteArray changelogData;
 | 
			
		||||
    NetJob::Ptr dljob;
 | 
			
		||||
    ChangelogType m_changelogType = CHANGELOG_MARKDOWN;
 | 
			
		||||
};
 | 
			
		||||
@@ -1,91 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<ui version="4.0">
 | 
			
		||||
 <class>UpdateDialog</class>
 | 
			
		||||
 <widget class="QDialog" name="UpdateDialog">
 | 
			
		||||
  <property name="geometry">
 | 
			
		||||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>657</width>
 | 
			
		||||
    <height>673</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
   <string>Launcher Update</string>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowIcon">
 | 
			
		||||
   <iconset>
 | 
			
		||||
    <normaloff>:/icons/toolbar/checkupdate</normaloff>:/icons/toolbar/checkupdate</iconset>
 | 
			
		||||
  </property>
 | 
			
		||||
  <layout class="QVBoxLayout" name="verticalLayout">
 | 
			
		||||
   <item>
 | 
			
		||||
    <layout class="QHBoxLayout" name="horizontalLayout_2">
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QLabel" name="label">
 | 
			
		||||
       <property name="font">
 | 
			
		||||
        <font>
 | 
			
		||||
         <pointsize>14</pointsize>
 | 
			
		||||
        </font>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string/>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="alignment">
 | 
			
		||||
        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="buddy">
 | 
			
		||||
        <cstring>changelogBrowser</cstring>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
    </layout>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QTextBrowser" name="changelogBrowser">
 | 
			
		||||
     <property name="openExternalLinks">
 | 
			
		||||
      <bool>true</bool>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <layout class="QGridLayout" name="gridLayout">
 | 
			
		||||
     <item row="0" column="0">
 | 
			
		||||
      <widget class="QPushButton" name="btnUpdateNow">
 | 
			
		||||
       <property name="sizePolicy">
 | 
			
		||||
        <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
 | 
			
		||||
         <horstretch>0</horstretch>
 | 
			
		||||
         <verstretch>0</verstretch>
 | 
			
		||||
        </sizepolicy>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>Update now</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item row="0" column="1">
 | 
			
		||||
      <widget class="QPushButton" name="btnUpdateLater">
 | 
			
		||||
       <property name="sizePolicy">
 | 
			
		||||
        <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
 | 
			
		||||
         <horstretch>0</horstretch>
 | 
			
		||||
         <verstretch>0</verstretch>
 | 
			
		||||
        </sizepolicy>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>Don't update yet</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
    </layout>
 | 
			
		||||
   </item>
 | 
			
		||||
  </layout>
 | 
			
		||||
 </widget>
 | 
			
		||||
 <tabstops>
 | 
			
		||||
  <tabstop>changelogBrowser</tabstop>
 | 
			
		||||
  <tabstop>btnUpdateNow</tabstop>
 | 
			
		||||
  <tabstop>btnUpdateLater</tabstop>
 | 
			
		||||
 </tabstops>
 | 
			
		||||
 <resources>
 | 
			
		||||
  <include location="../../resources/multimc/multimc.qrc"/>
 | 
			
		||||
 </resources>
 | 
			
		||||
 <connections/>
 | 
			
		||||
</ui>
 | 
			
		||||
@@ -44,14 +44,13 @@
 | 
			
		||||
#include <QTextCharFormat>
 | 
			
		||||
#include <QMenuBar>
 | 
			
		||||
 | 
			
		||||
#include "updater/UpdateChecker.h"
 | 
			
		||||
 | 
			
		||||
#include "settings/SettingsObject.h"
 | 
			
		||||
#include <FileSystem.h>
 | 
			
		||||
#include "Application.h"
 | 
			
		||||
#include "BuildConfig.h"
 | 
			
		||||
#include "DesktopServices.h"
 | 
			
		||||
#include "ui/themes/ITheme.h"
 | 
			
		||||
#include "updater/ExternalUpdater.h"
 | 
			
		||||
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QProcess>
 | 
			
		||||
@@ -80,30 +79,8 @@ LauncherPage::LauncherPage(QWidget *parent) : QWidget(parent), ui(new Ui::Launch
 | 
			
		||||
    m_languageModel = APPLICATION->translations();
 | 
			
		||||
    loadSettings();
 | 
			
		||||
 | 
			
		||||
    if(BuildConfig.UPDATER_ENABLED)
 | 
			
		||||
    {
 | 
			
		||||
        QObject::connect(APPLICATION->updateChecker().get(), &UpdateChecker::channelListLoaded, this, &LauncherPage::refreshUpdateChannelList);
 | 
			
		||||
    ui->updateSettingsBox->setHidden(!APPLICATION->updater());
 | 
			
		||||
 | 
			
		||||
        if (APPLICATION->updateChecker()->hasChannels())
 | 
			
		||||
        {
 | 
			
		||||
            refreshUpdateChannelList();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            APPLICATION->updateChecker()->updateChanList(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (APPLICATION->updateChecker()->getExternalUpdater())
 | 
			
		||||
        {
 | 
			
		||||
            ui->updateChannelComboBox->setVisible(false);
 | 
			
		||||
            ui->updateChannelDescLabel->setVisible(false);
 | 
			
		||||
            ui->updateChannelLabel->setVisible(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ui->updateSettingsBox->setHidden(true);
 | 
			
		||||
    }
 | 
			
		||||
    connect(ui->fontSizeBox, SIGNAL(valueChanged(int)), SLOT(refreshFontPreview()));
 | 
			
		||||
    connect(ui->consoleFont, SIGNAL(currentFontChanged(QFont)), SLOT(refreshFontPreview()));
 | 
			
		||||
}
 | 
			
		||||
@@ -198,94 +175,16 @@ void LauncherPage::on_metadataDisableBtn_clicked()
 | 
			
		||||
    ui->metadataWarningLabel->setHidden(!ui->metadataDisableBtn->isChecked());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LauncherPage::refreshUpdateChannelList()
 | 
			
		||||
{
 | 
			
		||||
    // Stop listening for selection changes. It's going to change a lot while we update it and
 | 
			
		||||
    // we don't need to update the
 | 
			
		||||
    // description label constantly.
 | 
			
		||||
    QObject::disconnect(ui->updateChannelComboBox, SIGNAL(currentIndexChanged(int)), this,
 | 
			
		||||
                        SLOT(updateChannelSelectionChanged(int)));
 | 
			
		||||
 | 
			
		||||
    QList<UpdateChecker::ChannelListEntry> channelList = APPLICATION->updateChecker()->getChannelList();
 | 
			
		||||
    ui->updateChannelComboBox->clear();
 | 
			
		||||
    int selection = -1;
 | 
			
		||||
    for (int i = 0; i < channelList.count(); i++)
 | 
			
		||||
    {
 | 
			
		||||
        UpdateChecker::ChannelListEntry entry = channelList.at(i);
 | 
			
		||||
 | 
			
		||||
        // When it comes to selection, we'll rely on the indexes of a channel entry being the
 | 
			
		||||
        // same in the
 | 
			
		||||
        // combo box as it is in the update checker's channel list.
 | 
			
		||||
        // This probably isn't very safe, but the channel list doesn't change often enough (or
 | 
			
		||||
        // at all) for
 | 
			
		||||
        // this to be a big deal. Hope it doesn't break...
 | 
			
		||||
        ui->updateChannelComboBox->addItem(entry.name);
 | 
			
		||||
 | 
			
		||||
        // If the update channel we just added was the selected one, set the current index in
 | 
			
		||||
        // the combo box to it.
 | 
			
		||||
        if (entry.id == m_currentUpdateChannel)
 | 
			
		||||
        {
 | 
			
		||||
            qDebug() << "Selected index" << i << "channel id" << m_currentUpdateChannel;
 | 
			
		||||
            selection = i;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ui->updateChannelComboBox->setCurrentIndex(selection);
 | 
			
		||||
 | 
			
		||||
    // Start listening for selection changes again and update the description label.
 | 
			
		||||
    QObject::connect(ui->updateChannelComboBox, SIGNAL(currentIndexChanged(int)), this,
 | 
			
		||||
                     SLOT(updateChannelSelectionChanged(int)));
 | 
			
		||||
    refreshUpdateChannelDesc();
 | 
			
		||||
 | 
			
		||||
    // Now that we've updated the channel list, we can enable the combo box.
 | 
			
		||||
    // It starts off disabled so that if the channel list hasn't been loaded, it will be
 | 
			
		||||
    // disabled.
 | 
			
		||||
    ui->updateChannelComboBox->setEnabled(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LauncherPage::updateChannelSelectionChanged(int index)
 | 
			
		||||
{
 | 
			
		||||
    refreshUpdateChannelDesc();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LauncherPage::refreshUpdateChannelDesc()
 | 
			
		||||
{
 | 
			
		||||
    // Get the channel list.
 | 
			
		||||
    QList<UpdateChecker::ChannelListEntry> channelList = APPLICATION->updateChecker()->getChannelList();
 | 
			
		||||
    int selectedIndex = ui->updateChannelComboBox->currentIndex();
 | 
			
		||||
    if (selectedIndex < 0)
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (selectedIndex < channelList.count())
 | 
			
		||||
    {
 | 
			
		||||
        // Find the channel list entry with the given index.
 | 
			
		||||
        UpdateChecker::ChannelListEntry selected = channelList.at(selectedIndex);
 | 
			
		||||
 | 
			
		||||
        // Set the description text.
 | 
			
		||||
        ui->updateChannelDescLabel->setText(selected.description);
 | 
			
		||||
 | 
			
		||||
        // Set the currently selected channel ID.
 | 
			
		||||
        m_currentUpdateChannel = selected.id;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LauncherPage::applySettings()
 | 
			
		||||
{
 | 
			
		||||
    auto s = APPLICATION->settings();
 | 
			
		||||
 | 
			
		||||
    // Updates
 | 
			
		||||
    if (BuildConfig.UPDATER_ENABLED && APPLICATION->updateChecker()->getExternalUpdater())
 | 
			
		||||
    if (APPLICATION->updater())
 | 
			
		||||
    {
 | 
			
		||||
        APPLICATION->updateChecker()->getExternalUpdater()->setAutomaticallyChecksForUpdates(
 | 
			
		||||
                ui->autoUpdateCheckBox->isChecked());
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked());
 | 
			
		||||
        APPLICATION->updater()->setAutomaticallyChecksForUpdates(ui->autoUpdateCheckBox->isChecked());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s->set("UpdateChannel", m_currentUpdateChannel);
 | 
			
		||||
    auto original = s->get("IconTheme").toString();
 | 
			
		||||
    //FIXME: make generic
 | 
			
		||||
    switch (ui->themeComboBox->currentIndex())
 | 
			
		||||
@@ -390,17 +289,11 @@ void LauncherPage::loadSettings()
 | 
			
		||||
{
 | 
			
		||||
    auto s = APPLICATION->settings();
 | 
			
		||||
    // Updates
 | 
			
		||||
    if (BuildConfig.UPDATER_ENABLED && APPLICATION->updateChecker()->getExternalUpdater())
 | 
			
		||||
    if (APPLICATION->updater())
 | 
			
		||||
    {
 | 
			
		||||
        ui->autoUpdateCheckBox->setChecked(
 | 
			
		||||
                APPLICATION->updateChecker()->getExternalUpdater()->getAutomaticallyChecksForUpdates());
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ui->autoUpdateCheckBox->setChecked(s->get("AutoUpdate").toBool());
 | 
			
		||||
        ui->autoUpdateCheckBox->setChecked(APPLICATION->updater()->getAutomaticallyChecksForUpdates());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_currentUpdateChannel = s->get("UpdateChannel").toString();
 | 
			
		||||
    //FIXME: make generic
 | 
			
		||||
    auto theme = s->get("IconTheme").toString();
 | 
			
		||||
    QStringList iconThemeOptions{"pe_colored", 
 | 
			
		||||
 
 | 
			
		||||
@@ -90,23 +90,11 @@ slots:
 | 
			
		||||
    void on_iconsDirBrowseBtn_clicked();
 | 
			
		||||
    void on_metadataDisableBtn_clicked();
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
     * Updates the list of update channels in the combo box.
 | 
			
		||||
     */
 | 
			
		||||
    void refreshUpdateChannelList();
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
     * Updates the channel description label.
 | 
			
		||||
     */
 | 
			
		||||
    void refreshUpdateChannelDesc();
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
     * Updates the font preview
 | 
			
		||||
     */
 | 
			
		||||
    void refreshFontPreview();
 | 
			
		||||
 | 
			
		||||
    void updateChannelSelectionChanged(int index);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Ui::LauncherPage *ui;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -58,33 +58,6 @@
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item>
 | 
			
		||||
           <widget class="QLabel" name="updateChannelLabel">
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Up&date Channel:</string>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="buddy">
 | 
			
		||||
             <cstring>updateChannelComboBox</cstring>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item>
 | 
			
		||||
           <widget class="QComboBox" name="updateChannelComboBox">
 | 
			
		||||
            <property name="enabled">
 | 
			
		||||
             <bool>false</bool>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item>
 | 
			
		||||
           <widget class="QLabel" name="updateChannelDescLabel">
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>No channel selected.</string>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="wordWrap">
 | 
			
		||||
             <bool>true</bool>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
         </layout>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
@@ -573,7 +546,6 @@
 | 
			
		||||
 <tabstops>
 | 
			
		||||
  <tabstop>tabWidget</tabstop>
 | 
			
		||||
  <tabstop>autoUpdateCheckBox</tabstop>
 | 
			
		||||
  <tabstop>updateChannelComboBox</tabstop>
 | 
			
		||||
  <tabstop>instDirTextBox</tabstop>
 | 
			
		||||
  <tabstop>instDirBrowseBtn</tabstop>
 | 
			
		||||
  <tabstop>modsDirTextBox</tabstop>
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@
 | 
			
		||||
 | 
			
		||||
#include "Application.h"
 | 
			
		||||
 | 
			
		||||
#include <QIcon>
 | 
			
		||||
#include <QIdentityProxyModel>
 | 
			
		||||
#include <QScrollBar>
 | 
			
		||||
#include <QShortcut>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,7 @@
 | 
			
		||||
 | 
			
		||||
class QFileSystemModel;
 | 
			
		||||
class QIdentityProxyModel;
 | 
			
		||||
class QItemSelection;
 | 
			
		||||
namespace Ui
 | 
			
		||||
{
 | 
			
		||||
class ScreenshotsPage;
 | 
			
		||||
 
 | 
			
		||||
@@ -48,6 +48,7 @@
 | 
			
		||||
 | 
			
		||||
#include <QFileSystemWatcher>
 | 
			
		||||
#include <QMenu>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
 | 
			
		||||
static const int COLUMN_COUNT = 2; // 3 , TBD: latency and other nice things.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -43,9 +43,9 @@
 | 
			
		||||
#include <QKeyEvent>
 | 
			
		||||
#include <QClipboard>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
#include <QSortFilterProxyModel>
 | 
			
		||||
#include <QTreeView>
 | 
			
		||||
#include <QInputDialog>
 | 
			
		||||
#include <QProcess>
 | 
			
		||||
#include <Qt>
 | 
			
		||||
 | 
			
		||||
#include "tools/MCEditTool.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,8 @@
 | 
			
		||||
 | 
			
		||||
#include "ListModel.h"
 | 
			
		||||
#include "Application.h"
 | 
			
		||||
#include "net/HttpMetaCache.h"
 | 
			
		||||
#include "net/NetJob.h"
 | 
			
		||||
 | 
			
		||||
#include "StringUtils.h"
 | 
			
		||||
#include <Version.h>
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,7 @@
 | 
			
		||||
#include <QAbstractListModel>
 | 
			
		||||
 | 
			
		||||
#include "modplatform/modrinth/ModrinthPackManifest.h"
 | 
			
		||||
#include "net/NetJob.h"
 | 
			
		||||
#include "ui/pages/modplatform/modrinth/ModrinthPage.h"
 | 
			
		||||
 | 
			
		||||
class ModPage;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user