From e8ee4497f77a571b305a48b70f84c8729b800859 Mon Sep 17 00:00:00 2001 From: chmodsayshello Date: Sun, 25 Dec 2022 23:39:38 +0100 Subject: store logs in sperate directory Signed-off-by: chmodsayshello --- launcher/Application.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/Application.cpp b/launcher/Application.cpp index ff34a168..f68e8792 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -394,7 +394,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // init the logger { - static const QString logBase = BuildConfig.LAUNCHER_NAME + "-%0.log"; + static const QString logBase = "logs/"+BuildConfig.LAUNCHER_NAME + "-%0.log"; + QDir logDir = QDir(dataPath); + if(!logDir.exists("logs")) { + logDir.mkpath("logs"); //this can fail, but there is no need to throw an error *yet*, since it also triggers the error message below! + } auto moveFile = [](const QString &oldName, const QString &newName) { QFile::remove(newName); @@ -415,11 +419,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) QString( "The launcher couldn't create a log file - the data folder is not writable.\n" "\n" - "Make sure you have write permissions to the data folder.\n" + "Make sure you have write permissions to the logs folder.\n" "(%1)\n" "\n" "The launcher cannot continue until you fix this problem." - ).arg(dataPath) + ).arg(dataPath+"/logs") ); return; } @@ -1666,6 +1670,7 @@ bool Application::handleDataMigration(const QString& currentData, matcher->add(std::make_shared(configFile)); matcher->add(std::make_shared( BuildConfig.LAUNCHER_CONFIGFILE)); // it's possible that we already used that directory before + matcher->add(std::make_shared("logs/")); matcher->add(std::make_shared("accounts.json")); matcher->add(std::make_shared("accounts/")); matcher->add(std::make_shared("assets/")); -- cgit From a80b820e9491624429c75a049140ebe738b6d604 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 1 Mar 2023 19:38:27 +0000 Subject: UI for mrpack export (broken) Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 3 ++ launcher/ui/MainWindow.cpp | 16 ++++++- launcher/ui/MainWindow.h | 5 +- launcher/ui/MainWindow.ui | 23 +++++++-- launcher/ui/dialogs/ExportMrPackDialog.cpp | 31 ++++++++++++ launcher/ui/dialogs/ExportMrPackDialog.h | 38 +++++++++++++++ launcher/ui/dialogs/ExportMrPackDialog.ui | 77 ++++++++++++++++++++++++++++++ 7 files changed, 187 insertions(+), 6 deletions(-) create mode 100644 launcher/ui/dialogs/ExportMrPackDialog.cpp create mode 100644 launcher/ui/dialogs/ExportMrPackDialog.h create mode 100644 launcher/ui/dialogs/ExportMrPackDialog.ui (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 202e633c..0b27ff85 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -851,6 +851,8 @@ SET(LAUNCHER_SOURCES ui/dialogs/EditAccountDialog.h ui/dialogs/ExportInstanceDialog.cpp ui/dialogs/ExportInstanceDialog.h + ui/dialogs/ExportMrPackDialog.cpp + ui/dialogs/ExportMrPackDialog.h ui/dialogs/IconPickerDialog.cpp ui/dialogs/IconPickerDialog.h ui/dialogs/ImportResourceDialog.cpp @@ -995,6 +997,7 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/ProfileSelectDialog.ui ui/dialogs/SkinUploadDialog.ui ui/dialogs/ExportInstanceDialog.ui + ui/dialogs/ExportMrPackDialog.ui ui/dialogs/IconPickerDialog.ui ui/dialogs/ImportResourceDialog.ui ui/dialogs/MSALoginDialog.ui diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 8490b292..ff7a12c2 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -2,7 +2,7 @@ /* * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -107,6 +107,7 @@ #include "ui/dialogs/CopyInstanceDialog.h" #include "ui/dialogs/EditAccountDialog.h" #include "ui/dialogs/ExportInstanceDialog.h" +#include "ui/dialogs/ExportMrPackDialog.h" #include "ui/dialogs/ImportResourceDialog.h" #include "ui/themes/ITheme.h" #include "ui/themes/ThemeManager.h" @@ -397,6 +398,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi // removing this looks stupid view->setFocus(); + ui->actionExportInstance->setMenu(ui->exportInstanceMenu); + retranslateUi(); } @@ -1345,7 +1348,7 @@ void MainWindow::on_actionDeleteInstance_triggered() APPLICATION->instances()->deleteInstance(id); } -void MainWindow::on_actionExportInstance_triggered() +void MainWindow::on_actionExportInstanceZip_triggered() { if (m_selectedInstance) { @@ -1354,6 +1357,15 @@ void MainWindow::on_actionExportInstance_triggered() } } +void MainWindow::on_actionExportInstanceMrPack_triggered() +{ + if (m_selectedInstance) + { + ExportMrPackDialog dlg(m_selectedInstance, this); + dlg.exec(); + } +} + void MainWindow::on_actionRenameInstance_triggered() { if (m_selectedInstance) diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 3a42c34e..35b4792d 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -2,6 +2,7 @@ /* * PolyMC - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -151,7 +152,9 @@ private slots: void deleteGroup(); void undoTrashInstance(); - void on_actionExportInstance_triggered(); + inline void on_actionExportInstance_triggered() { on_actionExportInstanceZip_triggered(); } + void on_actionExportInstanceZip_triggered(); + void on_actionExportInstanceMrPack_triggered(); void on_actionRenameInstance_triggered(); diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index 2b6a10b1..2ede882d 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -459,10 +459,27 @@ E&xport... - Export the selected instance as a zip file. + Export the selected instance to supported formats. - - Ctrl+E + + + + + + + + Prism Launcher (zip) + + + Export the instance as a ZIP. + + + + + Modrinth (mrpack) + + + Export to a Modrinth modpack. diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp new file mode 100644 index 00000000..eb53a61f --- /dev/null +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ExportMrPackDialog.h" +#include "ui_ExportMrPackDialog.h" + +ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) + : QDialog(parent), instance(instance), ui(new Ui::ExportMrPackDialog) +{ + ui->setupUi(this); +} + +ExportMrPackDialog::~ExportMrPackDialog() +{ + delete ui; +} diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportMrPackDialog.h new file mode 100644 index 00000000..78322a8f --- /dev/null +++ b/launcher/ui/dialogs/ExportMrPackDialog.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include "BaseInstance.h" + +namespace Ui { +class ExportMrPackDialog; +} + +class ExportMrPackDialog : public QDialog { + Q_OBJECT + + public: + explicit ExportMrPackDialog(InstancePtr instance, QWidget* parent = nullptr); + ~ExportMrPackDialog(); + + private: + InstancePtr instance; + Ui::ExportMrPackDialog* ui; +}; diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportMrPackDialog.ui new file mode 100644 index 00000000..2b553987 --- /dev/null +++ b/launcher/ui/dialogs/ExportMrPackDialog.ui @@ -0,0 +1,77 @@ + + + ExportMrPackDialog + + + + 0 + 0 + 650 + 413 + + + + Export Modrinth Pack + + + + + + Information + + + + + + Summary + + + + + + + + + + Name + + + + + + + Version + + + + + + + + + + + + + + + + Files + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + -- cgit From 8b897ac714f5317c6544c0fa6058495544301391 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 1 Mar 2023 20:45:07 +0000 Subject: Fix menu being set as central widget Signed-off-by: TheKodeToad --- launcher/ui/MainWindow.ui | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index 2ede882d..4a89bc10 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -150,6 +150,10 @@ + + + + @@ -462,25 +466,15 @@ Export the selected instance to supported formats. - - - - Prism Launcher (zip) - - Export the instance as a ZIP. - Modrinth (mrpack) - - Export to a Modrinth modpack. - -- cgit From 0fadb5a2be5f8136a4a5f52f7e5602698b53f09e Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 1 Mar 2023 21:11:04 +0000 Subject: Add *basic* interaction Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 10 +++++++ launcher/ui/dialogs/ExportMrPackDialog.h | 2 ++ launcher/ui/dialogs/ExportMrPackDialog.ui | 47 +++++++++++++++++++++++++++--- 3 files changed, 55 insertions(+), 4 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index eb53a61f..735a6245 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -23,6 +23,16 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) : QDialog(parent), instance(instance), ui(new Ui::ExportMrPackDialog) { ui->setupUi(this); + ui->name->setText(instance->name()); +} + +void ExportMrPackDialog::done(int result) { + if (result != Accepted) { + QDialog::done(result); + return; + } + QDialog::done(result); + } ExportMrPackDialog::~ExportMrPackDialog() diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportMrPackDialog.h index 78322a8f..31ab86ff 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.h +++ b/launcher/ui/dialogs/ExportMrPackDialog.h @@ -32,6 +32,8 @@ class ExportMrPackDialog : public QDialog { explicit ExportMrPackDialog(InstancePtr instance, QWidget* parent = nullptr); ~ExportMrPackDialog(); + void done(int result) override; + private: InstancePtr instance; Ui::ExportMrPackDialog* ui; diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportMrPackDialog.ui index 2b553987..37c87158 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.ui +++ b/launcher/ui/dialogs/ExportMrPackDialog.ui @@ -28,7 +28,7 @@ - + @@ -45,10 +45,10 @@ - + - + @@ -72,6 +72,45 @@ + + name + version + summary + treeView + - + + + buttonBox + accepted() + ExportMrPackDialog + accept() + + + 324 + 390 + + + 324 + 206 + + + + + buttonBox + rejected() + ExportMrPackDialog + reject() + + + 324 + 390 + + + 324 + 206 + + + + -- cgit From 46cc325f7cc9810abe6e152484a51fed92b1bb52 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 2 Mar 2023 11:25:36 +0000 Subject: Add file tree Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 1 + launcher/PackIgnoreProxy.cpp | 266 ++++++++++++++++++++++++ launcher/PackIgnoreProxy.h | 71 +++++++ launcher/ui/dialogs/ExportInstanceDialog.cpp | 294 +-------------------------- launcher/ui/dialogs/ExportInstanceDialog.h | 2 +- launcher/ui/dialogs/ExportMrPackDialog.cpp | 19 +- launcher/ui/dialogs/ExportMrPackDialog.h | 2 + launcher/ui/dialogs/ExportMrPackDialog.ui | 25 ++- 8 files changed, 379 insertions(+), 301 deletions(-) create mode 100644 launcher/PackIgnoreProxy.cpp create mode 100644 launcher/PackIgnoreProxy.h (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 0b27ff85..2664ba66 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -664,6 +664,7 @@ SET(LAUNCHER_SOURCES # FIXME: maybe find a better home for this. SkinUtils.cpp SkinUtils.h + PackIgnoreProxy.cpp # GUI - setup wizard ui/setupwizard/SetupWizard.h diff --git a/launcher/PackIgnoreProxy.cpp b/launcher/PackIgnoreProxy.cpp new file mode 100644 index 00000000..bd0a82a4 --- /dev/null +++ b/launcher/PackIgnoreProxy.cpp @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PackIgnoreProxy.h" + +#include +#include +#include +#include +#include "FileSystem.h" +#include "SeparatorPrefixTree.h" +#include "StringUtils.h" + +PackIgnoreProxy::PackIgnoreProxy(QString root, QObject* parent) : QSortFilterProxyModel(parent), root(root) {} +// NOTE: Sadly, we have to do sorting ourselves. +bool PackIgnoreProxy::lessThan(const QModelIndex& left, const QModelIndex& right) const +{ + QFileSystemModel* fsm = qobject_cast(sourceModel()); + if (!fsm) { + return QSortFilterProxyModel::lessThan(left, right); + } + bool asc = sortOrder() == Qt::AscendingOrder ? true : false; + + QFileInfo leftFileInfo = fsm->fileInfo(left); + QFileInfo rightFileInfo = fsm->fileInfo(right); + + if (!leftFileInfo.isDir() && rightFileInfo.isDir()) { + return !asc; + } + if (leftFileInfo.isDir() && !rightFileInfo.isDir()) { + return asc; + } + + // sort and proxy model breaks the original model... + if (sortColumn() == 0) { + return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), Qt::CaseInsensitive) < 0; + } + if (sortColumn() == 1) { + auto leftSize = leftFileInfo.size(); + auto rightSize = rightFileInfo.size(); + if ((leftSize == rightSize) || (leftFileInfo.isDir() && rightFileInfo.isDir())) { + return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), Qt::CaseInsensitive) < 0 ? asc : !asc; + } + return leftSize < rightSize; + } + return QSortFilterProxyModel::lessThan(left, right); +} + +Qt::ItemFlags PackIgnoreProxy::flags(const QModelIndex& index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + + auto sourceIndex = mapToSource(index); + Qt::ItemFlags flags = sourceIndex.flags(); + if (index.column() == 0) { + flags |= Qt::ItemIsUserCheckable; + if (sourceIndex.model()->hasChildren(sourceIndex)) { + flags |= Qt::ItemIsAutoTristate; + } + } + + return flags; +} + +QVariant PackIgnoreProxy::data(const QModelIndex& index, int role) const +{ + QModelIndex sourceIndex = mapToSource(index); + + if (index.column() == 0 && role == Qt::CheckStateRole) { + QFileSystemModel* fsm = qobject_cast(sourceModel()); + auto blockedPath = relPath(fsm->filePath(sourceIndex)); + auto cover = blocked.cover(blockedPath); + if (!cover.isNull()) { + return QVariant(Qt::Unchecked); + } else if (blocked.exists(blockedPath)) { + return QVariant(Qt::PartiallyChecked); + } else { + return QVariant(Qt::Checked); + } + } + + return sourceIndex.data(role); +} + +bool PackIgnoreProxy::setData(const QModelIndex& index, const QVariant& value, int role) +{ + if (index.column() == 0 && role == Qt::CheckStateRole) { + Qt::CheckState state = static_cast(value.toInt()); + return setFilterState(index, state); + } + + QModelIndex sourceIndex = mapToSource(index); + return QSortFilterProxyModel::sourceModel()->setData(sourceIndex, value, role); +} + +QString PackIgnoreProxy::relPath(const QString& path) const +{ + QString prefix = QDir().absoluteFilePath(root); + prefix += '/'; + if (!path.startsWith(prefix)) { + return QString(); + } + return path.mid(prefix.size()); +} + +bool PackIgnoreProxy::setFilterState(QModelIndex index, Qt::CheckState state) +{ + QFileSystemModel* fsm = qobject_cast(sourceModel()); + + if (!fsm) { + return false; + } + + QModelIndex sourceIndex = mapToSource(index); + auto blockedPath = relPath(fsm->filePath(sourceIndex)); + bool changed = false; + if (state == Qt::Unchecked) { + // blocking a path + auto& node = blocked.insert(blockedPath); + // get rid of all blocked nodes below + node.clear(); + changed = true; + } else if (state == Qt::Checked || state == Qt::PartiallyChecked) { + if (!blocked.remove(blockedPath)) { + auto cover = blocked.cover(blockedPath); + qDebug() << "Blocked by cover" << cover; + // uncover + blocked.remove(cover); + // block all contents, except for any cover + QModelIndex rootIndex = fsm->index(FS::PathCombine(root, cover)); + QModelIndex doing = rootIndex; + int row = 0; + QStack todo; + while (1) { + auto node = fsm->index(row, 0, doing); + if (!node.isValid()) { + if (!todo.size()) { + break; + } else { + doing = todo.pop(); + row = 0; + continue; + } + } + auto relpath = relPath(fsm->filePath(node)); + if (blockedPath.startsWith(relpath)) // cover found? + { + // continue processing cover later + todo.push(node); + } else { + // or just block this one. + blocked.insert(relpath); + } + row++; + } + } + changed = true; + } + if (changed) { + // update the thing + emit dataChanged(index, index, { Qt::CheckStateRole }); + // update everything above index + QModelIndex up = index.parent(); + while (1) { + if (!up.isValid()) + break; + emit dataChanged(up, up, { Qt::CheckStateRole }); + up = up.parent(); + } + // and everything below the index + QModelIndex doing = index; + int row = 0; + QStack todo; + while (1) { + auto node = this->index(row, 0, doing); + if (!node.isValid()) { + if (!todo.size()) { + break; + } else { + doing = todo.pop(); + row = 0; + continue; + } + } + emit dataChanged(node, node, { Qt::CheckStateRole }); + todo.push(node); + row++; + } + // siblings and unrelated nodes are ignored + } + return true; +} + +bool PackIgnoreProxy::shouldExpand(QModelIndex index) +{ + QModelIndex sourceIndex = mapToSource(index); + QFileSystemModel* fsm = qobject_cast(sourceModel()); + if (!fsm) { + return false; + } + auto blockedPath = relPath(fsm->filePath(sourceIndex)); + auto found = blocked.find(blockedPath); + if (found) { + return !found->leaf(); + } + return false; +} + +void PackIgnoreProxy::setBlockedPaths(QStringList paths) +{ + beginResetModel(); + blocked.clear(); + blocked.insert(paths); + endResetModel(); +} + +const SeparatorPrefixTree<'/'>& PackIgnoreProxy::blockedPaths() const +{ + return blocked; +} + +bool PackIgnoreProxy::filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const +{ + Q_UNUSED(source_parent) + + // adjust the columns you want to filter out here + // return false for those that will be hidden + if (source_column == 2 || source_column == 3) + return false; + + return true; +} \ No newline at end of file diff --git a/launcher/PackIgnoreProxy.h b/launcher/PackIgnoreProxy.h new file mode 100644 index 00000000..aec42b41 --- /dev/null +++ b/launcher/PackIgnoreProxy.h @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include "SeparatorPrefixTree.h" + +class PackIgnoreProxy : public QSortFilterProxyModel { + Q_OBJECT + + public: + PackIgnoreProxy(QString root, QObject* parent); + // NOTE: Sadly, we have to do sorting ourselves. + bool lessThan(const QModelIndex& left, const QModelIndex& right) const; + + virtual Qt::ItemFlags flags(const QModelIndex& index) const; + + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); + + QString relPath(const QString& path) const; + + bool setFilterState(QModelIndex index, Qt::CheckState state); + + bool shouldExpand(QModelIndex index); + + void setBlockedPaths(QStringList paths); + + const SeparatorPrefixTree<'/'>& blockedPaths() const; + + protected: + bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const; + + private: + const QString root; + SeparatorPrefixTree<'/'> blocked; +}; \ No newline at end of file diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index f13e36e8..2c706b8a 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -51,294 +51,15 @@ #include #include -class PackIgnoreProxy : public QSortFilterProxyModel -{ - Q_OBJECT - -public: - PackIgnoreProxy(InstancePtr instance, QObject *parent) : QSortFilterProxyModel(parent) - { - m_instance = instance; - } - // NOTE: Sadly, we have to do sorting ourselves. - bool lessThan(const QModelIndex &left, const QModelIndex &right) const - { - QFileSystemModel *fsm = qobject_cast(sourceModel()); - if (!fsm) - { - return QSortFilterProxyModel::lessThan(left, right); - } - bool asc = sortOrder() == Qt::AscendingOrder ? true : false; - - QFileInfo leftFileInfo = fsm->fileInfo(left); - QFileInfo rightFileInfo = fsm->fileInfo(right); - - if (!leftFileInfo.isDir() && rightFileInfo.isDir()) - { - return !asc; - } - if (leftFileInfo.isDir() && !rightFileInfo.isDir()) - { - return asc; - } - - // sort and proxy model breaks the original model... - if (sortColumn() == 0) - { - return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), - Qt::CaseInsensitive) < 0; - } - if (sortColumn() == 1) - { - auto leftSize = leftFileInfo.size(); - auto rightSize = rightFileInfo.size(); - if ((leftSize == rightSize) || (leftFileInfo.isDir() && rightFileInfo.isDir())) - { - return StringUtils::naturalCompare(leftFileInfo.fileName(), - rightFileInfo.fileName(), - Qt::CaseInsensitive) < 0 - ? asc - : !asc; - } - return leftSize < rightSize; - } - return QSortFilterProxyModel::lessThan(left, right); - } - - virtual Qt::ItemFlags flags(const QModelIndex &index) const - { - if (!index.isValid()) - return Qt::NoItemFlags; - - auto sourceIndex = mapToSource(index); - Qt::ItemFlags flags = sourceIndex.flags(); - if (index.column() == 0) - { - flags |= Qt::ItemIsUserCheckable; - if (sourceIndex.model()->hasChildren(sourceIndex)) - { - flags |= Qt::ItemIsAutoTristate; - } - } - - return flags; - } - - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const - { - QModelIndex sourceIndex = mapToSource(index); - - if (index.column() == 0 && role == Qt::CheckStateRole) - { - QFileSystemModel *fsm = qobject_cast(sourceModel()); - auto blockedPath = relPath(fsm->filePath(sourceIndex)); - auto cover = blocked.cover(blockedPath); - if (!cover.isNull()) - { - return QVariant(Qt::Unchecked); - } - else if (blocked.exists(blockedPath)) - { - return QVariant(Qt::PartiallyChecked); - } - else - { - return QVariant(Qt::Checked); - } - } - - return sourceIndex.data(role); - } - - virtual bool setData(const QModelIndex &index, const QVariant &value, - int role = Qt::EditRole) - { - if (index.column() == 0 && role == Qt::CheckStateRole) - { - Qt::CheckState state = static_cast(value.toInt()); - return setFilterState(index, state); - } - - QModelIndex sourceIndex = mapToSource(index); - return QSortFilterProxyModel::sourceModel()->setData(sourceIndex, value, role); - } - - QString relPath(const QString &path) const - { - QString prefix = QDir().absoluteFilePath(m_instance->instanceRoot()); - prefix += '/'; - if (!path.startsWith(prefix)) - { - return QString(); - } - return path.mid(prefix.size()); - } - - bool setFilterState(QModelIndex index, Qt::CheckState state) - { - QFileSystemModel *fsm = qobject_cast(sourceModel()); - - if (!fsm) - { - return false; - } - - QModelIndex sourceIndex = mapToSource(index); - auto blockedPath = relPath(fsm->filePath(sourceIndex)); - bool changed = false; - if (state == Qt::Unchecked) - { - // blocking a path - auto &node = blocked.insert(blockedPath); - // get rid of all blocked nodes below - node.clear(); - changed = true; - } - else if (state == Qt::Checked || state == Qt::PartiallyChecked) - { - if (!blocked.remove(blockedPath)) - { - auto cover = blocked.cover(blockedPath); - qDebug() << "Blocked by cover" << cover; - // uncover - blocked.remove(cover); - // block all contents, except for any cover - QModelIndex rootIndex = - fsm->index(FS::PathCombine(m_instance->instanceRoot(), cover)); - QModelIndex doing = rootIndex; - int row = 0; - QStack todo; - while (1) - { - auto node = fsm->index(row, 0, doing); - if (!node.isValid()) - { - if (!todo.size()) - { - break; - } - else - { - doing = todo.pop(); - row = 0; - continue; - } - } - auto relpath = relPath(fsm->filePath(node)); - if (blockedPath.startsWith(relpath)) // cover found? - { - // continue processing cover later - todo.push(node); - } - else - { - // or just block this one. - blocked.insert(relpath); - } - row++; - } - } - changed = true; - } - if (changed) - { - // update the thing - emit dataChanged(index, index, {Qt::CheckStateRole}); - // update everything above index - QModelIndex up = index.parent(); - while (1) - { - if (!up.isValid()) - break; - emit dataChanged(up, up, {Qt::CheckStateRole}); - up = up.parent(); - } - // and everything below the index - QModelIndex doing = index; - int row = 0; - QStack todo; - while (1) - { - auto node = this->index(row, 0, doing); - if (!node.isValid()) - { - if (!todo.size()) - { - break; - } - else - { - doing = todo.pop(); - row = 0; - continue; - } - } - emit dataChanged(node, node, {Qt::CheckStateRole}); - todo.push(node); - row++; - } - // siblings and unrelated nodes are ignored - } - return true; - } - - bool shouldExpand(QModelIndex index) - { - QModelIndex sourceIndex = mapToSource(index); - QFileSystemModel *fsm = qobject_cast(sourceModel()); - if (!fsm) - { - return false; - } - auto blockedPath = relPath(fsm->filePath(sourceIndex)); - auto found = blocked.find(blockedPath); - if(found) - { - return !found->leaf(); - } - return false; - } - - void setBlockedPaths(QStringList paths) - { - beginResetModel(); - blocked.clear(); - blocked.insert(paths); - endResetModel(); - } - - const SeparatorPrefixTree<'/'> & blockedPaths() const - { - return blocked; - } - -protected: - bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const - { - Q_UNUSED(source_parent) - - // adjust the columns you want to filter out here - // return false for those that will be hidden - if (source_column == 2 || source_column == 3) - return false; - - return true; - } - -private: - InstancePtr m_instance; - SeparatorPrefixTree<'/'> blocked; -}; - ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget *parent) : QDialog(parent), ui(new Ui::ExportInstanceDialog), m_instance(instance) { ui->setupUi(this); auto model = new QFileSystemModel(this); - proxyModel = new PackIgnoreProxy(m_instance, this); + auto root = instance->instanceRoot(); + proxyModel = new PackIgnoreProxy(root, this); loadPackIgnore(); proxyModel->setSourceModel(model); - auto root = instance->instanceRoot(); ui->treeView->setModel(proxyModel); ui->treeView->setRootIndex(proxyModel->mapFromSource(model->index(root))); ui->treeView->sortByColumn(0, Qt::AscendingOrder); @@ -407,17 +128,6 @@ bool ExportInstanceDialog::doExport() { return false; } - if (QFile::exists(output)) - { - int ret = - QMessageBox::question(this, tr("Overwrite?"), - tr("This file already exists. Do you want to overwrite it?"), - QMessageBox::No, QMessageBox::Yes); - if (ret == QMessageBox::No) - { - return false; - } - } SaveIcon(m_instance); diff --git a/launcher/ui/dialogs/ExportInstanceDialog.h b/launcher/ui/dialogs/ExportInstanceDialog.h index dea02d1b..b1b8f911 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.h +++ b/launcher/ui/dialogs/ExportInstanceDialog.h @@ -18,9 +18,9 @@ #include #include #include +#include "PackIgnoreProxy.h" class BaseInstance; -class PackIgnoreProxy; typedef std::shared_ptr InstancePtr; namespace Ui diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 735a6245..1a839061 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -17,6 +17,7 @@ */ #include "ExportMrPackDialog.h" +#include #include "ui_ExportMrPackDialog.h" ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) @@ -24,15 +25,29 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) { ui->setupUi(this); ui->name->setText(instance->name()); + + auto model = new QFileSystemModel(this); + // use the game root - everything outside cannot be exported + QString root = instance->gameRoot(); + proxy = new PackIgnoreProxy(root, this); + proxy->setSourceModel(model); + ui->treeView->setModel(proxy); + ui->treeView->setRootIndex(proxy->mapFromSource(model->index(root))); + ui->treeView->sortByColumn(0, Qt::AscendingOrder); + model->setFilter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); + model->setRootPath(root); + auto headerView = ui->treeView->header(); + headerView->setSectionResizeMode(QHeaderView::ResizeToContents); + headerView->setSectionResizeMode(0, QHeaderView::Stretch); } -void ExportMrPackDialog::done(int result) { +void ExportMrPackDialog::done(int result) +{ if (result != Accepted) { QDialog::done(result); return; } QDialog::done(result); - } ExportMrPackDialog::~ExportMrPackDialog() diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportMrPackDialog.h index 31ab86ff..454c25eb 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.h +++ b/launcher/ui/dialogs/ExportMrPackDialog.h @@ -20,6 +20,7 @@ #include #include "BaseInstance.h" +#include "PackIgnoreProxy.h" namespace Ui { class ExportMrPackDialog; @@ -37,4 +38,5 @@ class ExportMrPackDialog : public QDialog { private: InstancePtr instance; Ui::ExportMrPackDialog* ui; + PackIgnoreProxy* proxy; }; diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportMrPackDialog.ui index 37c87158..8e6d61ff 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.ui +++ b/launcher/ui/dialogs/ExportMrPackDialog.ui @@ -15,13 +15,13 @@ - + Information - + Summary @@ -31,14 +31,14 @@ - + Name - + Version @@ -54,14 +54,27 @@ - + Files - + + + true + + + QAbstractItemView::ExtendedSelection + + + true + + + false + + -- cgit From a5dd6b6cd7050b4861a50a417d939c6a49d5cc33 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 2 Mar 2023 16:40:49 +0000 Subject: Export without file urls Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ExportInstanceDialog.cpp | 2 +- launcher/ui/dialogs/ExportMrPackDialog.cpp | 93 +++++++++++++++++++++++++--- launcher/ui/dialogs/ExportMrPackDialog.h | 3 + 3 files changed, 90 insertions(+), 8 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index 2c706b8a..f310a689 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -123,7 +123,7 @@ bool ExportInstanceDialog::doExport() const QString output = QFileDialog::getSaveFileName( this, tr("Export %1").arg(m_instance->name()), - FS::PathCombine(QDir::homePath(), name + ".zip"), "Zip (*.zip)", nullptr, QFileDialog::DontConfirmOverwrite); + FS::PathCombine(QDir::homePath(), name + ".zip"), "Zip (*.zip)", nullptr); if (output.isEmpty()) { return false; diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 1a839061..9015407d 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -17,9 +17,17 @@ */ #include "ExportMrPackDialog.h" -#include +#include +#include "FileSystem.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/PackProfile.h" #include "ui_ExportMrPackDialog.h" +#include +#include +#include +#include "MMCZip.h" + ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) : QDialog(parent), instance(instance), ui(new Ui::ExportMrPackDialog) { @@ -41,16 +49,87 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) headerView->setSectionResizeMode(0, QHeaderView::Stretch); } +ExportMrPackDialog::~ExportMrPackDialog() +{ + delete ui; +} + void ExportMrPackDialog::done(int result) { - if (result != Accepted) { - QDialog::done(result); - return; - } + if (result == Accepted) + runExport(); + QDialog::done(result); } -ExportMrPackDialog::~ExportMrPackDialog() +void ExportMrPackDialog::runExport() { - delete ui; + const QString filename = FS::RemoveInvalidFilenameChars(ui->name->text()); + const QString output = + QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), FS::PathCombine(QDir::homePath(), filename + ".mrpack"), + "Modrinth modpack (*.mrpack *.zip)", nullptr); + + if (output.isEmpty()) + return; + + QFileInfoList files; + if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, + [this](const QString& path) { return proxy->blockedPaths().covers(path); })) { + QMessageBox::warning(this, tr("Unable to export modpack"), tr("Could not collect list of files")); + return; + } + + QuaZip zip(output); + if (!zip.open(QuaZip::mdCreate)) { + QFile::remove(output); + QMessageBox::warning(this, tr("Unable to export modpack"), tr("Could not create file")); + return; + } + + QuaZipFile indexFile(&zip); + indexFile.setFileName("modrinth.index.json"); + if (!indexFile.open(QuaZipFile::NewOnly)) { + QFile::remove(output); + QMessageBox::warning(this, tr("Unable to export modpack"), tr("Could not create index")); + return; + } + indexFile.write(generateIndex()); + indexFile.close(); + + // should exist + QDir dotMinecraft(instance->gameRoot()); + + for (const QFileInfo& file : files) + if (!JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + dotMinecraft.relativeFilePath(file.absoluteFilePath()))) + QMessageBox::warning(this, tr("Unable to export modpack"), tr("Could not compress %1").arg(file.absoluteFilePath())); + + zip.close(); + + if (zip.getZipError() != 0) { + QFile::remove(output); + QMessageBox::warning(this, tr("Unable to export modpack"), tr("A zip error occured")); + return; + } } + +QByteArray ExportMrPackDialog::generateIndex() +{ + QJsonObject obj; + obj["formatVersion"] = 1; + obj["game"] = "minecraft"; + obj["name"] = ui->name->text(); + obj["versionId"] = ui->version->text(); + obj["summary"] = ui->summary->text(); + + MinecraftInstance* mc = dynamic_cast(instance.get()); + if (mc) { + auto profile = mc->getPackProfile(); + auto minecraft = profile->getComponent("net.minecraft"); + + QJsonObject dependencies; + dependencies["minecraft"] = minecraft->m_version; + obj["dependencies"] = dependencies; + } + + return QJsonDocument(obj).toJson(); +} \ No newline at end of file diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportMrPackDialog.h index 454c25eb..0cf4eb7f 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.h +++ b/launcher/ui/dialogs/ExportMrPackDialog.h @@ -39,4 +39,7 @@ class ExportMrPackDialog : public QDialog { InstancePtr instance; Ui::ExportMrPackDialog* ui; PackIgnoreProxy* proxy; + + void runExport(); + QByteArray generateIndex(); }; -- cgit From 9ec32b2561eac4ae50db88467d9afae57dd78614 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 2 Mar 2023 17:36:28 +0000 Subject: Fix QuaZipFile usage Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 9015407d..96c7a201 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -86,15 +86,15 @@ void ExportMrPackDialog::runExport() return; } - QuaZipFile indexFile(&zip); - indexFile.setFileName("modrinth.index.json"); - if (!indexFile.open(QuaZipFile::NewOnly)) { - QFile::remove(output); - QMessageBox::warning(this, tr("Unable to export modpack"), tr("Could not create index")); - return; + { + QuaZipFile indexFile(&zip); + if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) { + QFile::remove(output); + QMessageBox::warning(this, tr("Unable to export modpack"), tr("Could not create index")); + return; + } + indexFile.write(generateIndex()); } - indexFile.write(generateIndex()); - indexFile.close(); // should exist QDir dotMinecraft(instance->gameRoot()); -- cgit From 88ef02474f9c696318eb1c9e0213a7900f60f67e Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 2 Mar 2023 17:36:39 +0000 Subject: Minify index JSON Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 96c7a201..14518783 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -131,5 +131,5 @@ QByteArray ExportMrPackDialog::generateIndex() obj["dependencies"] = dependencies; } - return QJsonDocument(obj).toJson(); + return QJsonDocument(obj).toJson(QJsonDocument::Compact); } \ No newline at end of file -- cgit From 6505b0c065b32e13f392061ccb184d288329a058 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 2 Mar 2023 19:48:41 +0000 Subject: Move logic to task Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 2 + .../modrinth/ModrinthPackExportTask.cpp | 110 +++++++++++++++++++++ .../modplatform/modrinth/ModrinthPackExportTask.h | 44 +++++++++ launcher/ui/dialogs/ExportMrPackDialog.cpp | 72 ++------------ launcher/ui/dialogs/ExportMrPackDialog.h | 3 +- 5 files changed, 166 insertions(+), 65 deletions(-) create mode 100644 launcher/modplatform/modrinth/ModrinthPackExportTask.cpp create mode 100644 launcher/modplatform/modrinth/ModrinthPackExportTask.h (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 2664ba66..f3af2ebf 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -522,6 +522,8 @@ set(MODRINTH_SOURCES modplatform/modrinth/ModrinthCheckUpdate.h modplatform/modrinth/ModrinthInstanceCreationTask.cpp modplatform/modrinth/ModrinthInstanceCreationTask.h + modplatform/modrinth/ModrinthPackExportTask.cpp + modplatform/modrinth/ModrinthPackExportTask.h ) set(MODPACKSCH_SOURCES diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp new file mode 100644 index 00000000..029b47a5 --- /dev/null +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ModrinthPackExportTask.h" +#include +#include +#include "MMCZip.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/PackProfile.h" + +ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, + const QString& version, + const QString& summary, + InstancePtr instance, + const QString& output, + MMCZip::FilterFunction filter) + : name(name), version(version), summary(summary), instance(instance), output(output), filter(filter) +{} + +void ModrinthPackExportTask::executeTask() +{ + QFileInfoList files; + if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) { + emitFailed(tr("Could not collect list of files")); + return; + } + + setStatus("Adding files..."); + + QuaZip zip(output); + if (!zip.open(QuaZip::mdCreate)) { + QFile::remove(output); + emitFailed(tr("Could not create file")); + return; + } + + { + QuaZipFile indexFile(&zip); + if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) { + QFile::remove(output); + + emitFailed(tr("Could not create index")); + return; + } + indexFile.write(generateIndex()); + } + + // should exist + QDir dotMinecraft(instance->gameRoot()); + + { + size_t i = 0; + for (const QFileInfo& file : files) { + setProgress(i, files.length()); + if (!JlCompress::compressFile(&zip, file.absoluteFilePath(), + "overrides/" + dotMinecraft.relativeFilePath(file.absoluteFilePath()))) { + emitFailed(tr("Could not compress %1").arg(file.absoluteFilePath())); + return; + } + i++; + } + } + + zip.close(); + + if (zip.getZipError() != 0) { + QFile::remove(output); + emitFailed(tr("A zip error occured")); + return; + } + + emitSucceeded(); +} + +QByteArray ModrinthPackExportTask::generateIndex() +{ + QJsonObject obj; + obj["formatVersion"] = 1; + obj["game"] = "minecraft"; + obj["name"] = name; + obj["versionId"] = version; + obj["summary"] = summary; + + MinecraftInstance* mc = dynamic_cast(instance.get()); + if (mc) { + auto profile = mc->getPackProfile(); + auto minecraft = profile->getComponent("net.minecraft"); + + QJsonObject dependencies; + dependencies["minecraft"] = minecraft->m_version; + obj["dependencies"] = dependencies; + } + + return QJsonDocument(obj).toJson(QJsonDocument::Compact); +} \ No newline at end of file diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h new file mode 100644 index 00000000..c38be204 --- /dev/null +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "BaseInstance.h" +#include "MMCZip.h" +#include "tasks/Task.h" + +class ModrinthPackExportTask : public Task { + public: + ModrinthPackExportTask(const QString& name, + const QString& version, + const QString& summary, + InstancePtr instance, + const QString& output, + MMCZip::FilterFunction filter); + + protected: + void executeTask() override; + + private: + const QString name, version, summary; + const InstancePtr instance; + const QString output; + const MMCZip::FilterFunction filter; + + QByteArray generateIndex(); +}; \ No newline at end of file diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 14518783..4c2e5593 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -17,16 +17,16 @@ */ #include "ExportMrPackDialog.h" -#include -#include "FileSystem.h" -#include "minecraft/MinecraftInstance.h" -#include "minecraft/PackProfile.h" +#include "ui/dialogs/ProgressDialog.h" #include "ui_ExportMrPackDialog.h" #include #include +#include #include +#include "FileSystem.h" #include "MMCZip.h" +#include "modplatform/modrinth/ModrinthPackExportTask.h" ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) : QDialog(parent), instance(instance), ui(new Ui::ExportMrPackDialog) @@ -72,64 +72,10 @@ void ExportMrPackDialog::runExport() if (output.isEmpty()) return; - QFileInfoList files; - if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, - [this](const QString& path) { return proxy->blockedPaths().covers(path); })) { - QMessageBox::warning(this, tr("Unable to export modpack"), tr("Could not collect list of files")); - return; - } - - QuaZip zip(output); - if (!zip.open(QuaZip::mdCreate)) { - QFile::remove(output); - QMessageBox::warning(this, tr("Unable to export modpack"), tr("Could not create file")); - return; - } - - { - QuaZipFile indexFile(&zip); - if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) { - QFile::remove(output); - QMessageBox::warning(this, tr("Unable to export modpack"), tr("Could not create index")); - return; - } - indexFile.write(generateIndex()); - } - - // should exist - QDir dotMinecraft(instance->gameRoot()); - - for (const QFileInfo& file : files) - if (!JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + dotMinecraft.relativeFilePath(file.absoluteFilePath()))) - QMessageBox::warning(this, tr("Unable to export modpack"), tr("Could not compress %1").arg(file.absoluteFilePath())); - - zip.close(); - - if (zip.getZipError() != 0) { - QFile::remove(output); - QMessageBox::warning(this, tr("Unable to export modpack"), tr("A zip error occured")); - return; - } -} - -QByteArray ExportMrPackDialog::generateIndex() -{ - QJsonObject obj; - obj["formatVersion"] = 1; - obj["game"] = "minecraft"; - obj["name"] = ui->name->text(); - obj["versionId"] = ui->version->text(); - obj["summary"] = ui->summary->text(); - - MinecraftInstance* mc = dynamic_cast(instance.get()); - if (mc) { - auto profile = mc->getPackProfile(); - auto minecraft = profile->getComponent("net.minecraft"); - - QJsonObject dependencies; - dependencies["minecraft"] = minecraft->m_version; - obj["dependencies"] = dependencies; - } + ModrinthPackExportTask task(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, + [this](const QString& path) { return proxy->blockedPaths().covers(path); }); - return QJsonDocument(obj).toJson(QJsonDocument::Compact); + ProgressDialog progress(this); + progress.setSkipButton(true, tr("Abort")); + progress.execWithTask(&task); } \ No newline at end of file diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportMrPackDialog.h index 0cf4eb7f..89263fc6 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.h +++ b/launcher/ui/dialogs/ExportMrPackDialog.h @@ -36,10 +36,9 @@ class ExportMrPackDialog : public QDialog { void done(int result) override; private: - InstancePtr instance; + const InstancePtr instance; Ui::ExportMrPackDialog* ui; PackIgnoreProxy* proxy; void runExport(); - QByteArray generateIndex(); }; -- cgit From f28a7b9d083a9181c04c7100f50152c116e72cb6 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 2 Mar 2023 19:50:42 +0000 Subject: Add PackIgnoreProxy.h to cmake Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index f3af2ebf..380e8336 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -667,6 +667,7 @@ SET(LAUNCHER_SOURCES SkinUtils.cpp SkinUtils.h PackIgnoreProxy.cpp + PackIgnoreProxy.h # GUI - setup wizard ui/setupwizard/SetupWizard.h -- cgit From adcdf28d64abbe16304c2d377488af1898f9b2af Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 3 Mar 2023 11:14:57 +0000 Subject: Move task to another thread I don't know whether this is the prefered method. Signed-off-by: TheKodeToad --- .../modrinth/ModrinthPackExportTask.cpp | 79 +++++++++++----------- launcher/ui/dialogs/ExportMrPackDialog.cpp | 32 ++++----- launcher/ui/dialogs/ExportMrPackDialog.h | 2 - 3 files changed, 55 insertions(+), 58 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 029b47a5..331fbf94 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -17,6 +17,7 @@ */ #include "ModrinthPackExportTask.h" +#include #include #include #include "MMCZip.h" @@ -34,57 +35,59 @@ ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, void ModrinthPackExportTask::executeTask() { - QFileInfoList files; - if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) { - emitFailed(tr("Could not collect list of files")); - return; - } - - setStatus("Adding files..."); + QtConcurrent::run(QThreadPool::globalInstance(), [this] { + QFileInfoList files; + if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) { + emitFailed(tr("Could not collect list of files")); + return; + } - QuaZip zip(output); - if (!zip.open(QuaZip::mdCreate)) { - QFile::remove(output); - emitFailed(tr("Could not create file")); - return; - } + setStatus("Adding files..."); - { - QuaZipFile indexFile(&zip); - if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) { + QuaZip zip(output); + if (!zip.open(QuaZip::mdCreate)) { QFile::remove(output); - - emitFailed(tr("Could not create index")); + emitFailed(tr("Could not create file")); return; } - indexFile.write(generateIndex()); - } - // should exist - QDir dotMinecraft(instance->gameRoot()); + { + QuaZipFile indexFile(&zip); + if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) { + QFile::remove(output); - { - size_t i = 0; - for (const QFileInfo& file : files) { - setProgress(i, files.length()); - if (!JlCompress::compressFile(&zip, file.absoluteFilePath(), - "overrides/" + dotMinecraft.relativeFilePath(file.absoluteFilePath()))) { - emitFailed(tr("Could not compress %1").arg(file.absoluteFilePath())); + emitFailed(tr("Could not create index")); return; } - i++; + indexFile.write(generateIndex()); } - } - zip.close(); + // should exist + QDir dotMinecraft(instance->gameRoot()); + + { + size_t i = 0; + for (const QFileInfo& file : files) { + setProgress(i, files.length()); + if (!JlCompress::compressFile(&zip, file.absoluteFilePath(), + "overrides/" + dotMinecraft.relativeFilePath(file.absoluteFilePath()))) { + emitFailed(tr("Could not compress %1").arg(file.absoluteFilePath())); + return; + } + i++; + } + } - if (zip.getZipError() != 0) { - QFile::remove(output); - emitFailed(tr("A zip error occured")); - return; - } + zip.close(); + + if (zip.getZipError() != 0) { + QFile::remove(output); + emitFailed(tr("A zip error occured")); + return; + } - emitSucceeded(); + emitSucceeded(); + }); } QByteArray ModrinthPackExportTask::generateIndex() diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 4c2e5593..81663c9a 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -56,26 +56,22 @@ ExportMrPackDialog::~ExportMrPackDialog() void ExportMrPackDialog::done(int result) { - if (result == Accepted) - runExport(); + if (result == Accepted) { + const QString filename = FS::RemoveInvalidFilenameChars(ui->name->text()); + const QString output = + QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), FS::PathCombine(QDir::homePath(), filename + ".mrpack"), + "Modrinth modpack (*.mrpack *.zip)", nullptr); - QDialog::done(result); -} + if (output.isEmpty()) + return; -void ExportMrPackDialog::runExport() -{ - const QString filename = FS::RemoveInvalidFilenameChars(ui->name->text()); - const QString output = - QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), FS::PathCombine(QDir::homePath(), filename + ".mrpack"), - "Modrinth modpack (*.mrpack *.zip)", nullptr); + ModrinthPackExportTask task(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, + [this](const QString& path) { return proxy->blockedPaths().covers(path); }); - if (output.isEmpty()) - return; + ProgressDialog progress(this); + progress.setSkipButton(true, tr("Abort")); + progress.execWithTask(&task); + } - ModrinthPackExportTask task(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, - [this](const QString& path) { return proxy->blockedPaths().covers(path); }); - - ProgressDialog progress(this); - progress.setSkipButton(true, tr("Abort")); - progress.execWithTask(&task); + QDialog::done(result); } \ No newline at end of file diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportMrPackDialog.h index 89263fc6..3ded4887 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.h +++ b/launcher/ui/dialogs/ExportMrPackDialog.h @@ -39,6 +39,4 @@ class ExportMrPackDialog : public QDialog { const InstancePtr instance; Ui::ExportMrPackDialog* ui; PackIgnoreProxy* proxy; - - void runExport(); }; -- cgit From dcaa907fede11c8f0aeddde8a78e8d9397eaee2f Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 3 Mar 2023 11:24:10 +0000 Subject: Mod loader support Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 331fbf94..1bb78cae 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -102,10 +102,22 @@ QByteArray ModrinthPackExportTask::generateIndex() MinecraftInstance* mc = dynamic_cast(instance.get()); if (mc) { auto profile = mc->getPackProfile(); + // collect all supported components auto minecraft = profile->getComponent("net.minecraft"); + auto quilt = profile->getComponent("org.quiltmc.quilt-loader"); + auto fabric = profile->getComponent("net.fabricmc.fabric-loader"); + auto forge = profile->getComponent("net.minecraftforge"); + // convert all available components to mrpack dependencies QJsonObject dependencies; - dependencies["minecraft"] = minecraft->m_version; + if (minecraft != nullptr) + dependencies["minecraft"] = minecraft->m_version; + if (quilt != nullptr) + dependencies["quilt-loader"] = quilt->m_version; + if (fabric != nullptr) + dependencies["fabric-loader"] = fabric->m_version; + if (forge != nullptr) + dependencies["forge"] = forge->m_version; obj["dependencies"] = dependencies; } -- cgit From 2343aad088e302bf9f4f75eb6c4d6d1da3c7fbe3 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 3 Mar 2023 15:00:07 +0000 Subject: Make it work! (TODO make it not crash) Signed-off-by: TheKodeToad --- .../modrinth/ModrinthPackExportTask.cpp | 119 ++++++++++++++++++--- .../modplatform/modrinth/ModrinthPackExportTask.h | 7 +- 2 files changed, 108 insertions(+), 18 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 1bb78cae..a319eec4 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -17,12 +17,17 @@ */ #include "ModrinthPackExportTask.h" -#include + +#include +#include #include #include +#include +#include "Json.h" #include "MMCZip.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" +#include "modplatform/modrinth/ModrinthAPI.h" ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, const QString& version, @@ -35,13 +40,76 @@ ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, void ModrinthPackExportTask::executeTask() { - QtConcurrent::run(QThreadPool::globalInstance(), [this] { - QFileInfoList files; - if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) { - emitFailed(tr("Could not collect list of files")); - return; + setStatus(tr("Searching for files...")); + + QFileInfoList files; + if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) { + emitFailed(tr("Could not collect list of files")); + return; + } + + QDir mc(instance->gameRoot()); + + ModrinthAPI api; + + static const QStringList prefixes({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); + // hash -> file + QMap hashes; + + for (QFileInfo file : files) { + QString relative = mc.relativeFilePath(file.absoluteFilePath()); + // require sensible file types + if (!(relative.endsWith(".zip") || relative.endsWith(".jar") || relative.endsWith(".litemod"))) + continue; + + if (!std::any_of(prefixes.begin(), prefixes.end(), + [&relative](const QString& prefix) { return relative.startsWith(prefix + QDir::separator()); })) + continue; + + QCryptographicHash hash(QCryptographicHash::Algorithm::Sha512); + + QFile openFile(file.absoluteFilePath()); + if (!openFile.open(QFile::ReadOnly)) { + qWarning() << "Could not open" << file << "for hashing"; + continue; } + if (!hash.addData(&openFile)) { + qWarning() << "Could not add hash data for" << file; + continue; + } + + hashes[hash.result().toHex()] = relative; + } + + QByteArray* response = new QByteArray; + Task::Ptr versionsTask = api.currentVersions(hashes.keys(), "sha512", response); + connect(versionsTask.get(), &NetJob::succeeded, this, [this, mc, files, hashes, response, versionsTask]() { + // file -> url + QMap resolved; + + try { + QJsonDocument doc = Json::requireDocument(*response); + for (auto iter = hashes.keyBegin(); iter != hashes.keyEnd(); iter++) { + QJsonObject obj = doc[*iter].toObject(); + if (obj.isEmpty()) + continue; + + QJsonArray files = obj["files"].toArray(); + if (auto fileIter = std::find_if(files.begin(), files.end(), + [&iter](const QJsonValue& file) { return file["hashes"]["sha512"] == *iter; }); + fileIter != files.end()) { + // map the file to the url + resolved[hashes[*iter]] = ResolvedFile{ fileIter->toObject()["hashes"].toObject()["sha1"].toString(), *iter, + fileIter->toObject()["url"].toString(), fileIter->toObject()["size"].toInt() }; + } + } + } catch (Json::JsonException& e) { + qWarning() << "Failed to parse versions response" << e.what(); + } + + delete response; + setStatus("Adding files..."); QuaZip zip(output); @@ -55,25 +123,19 @@ void ModrinthPackExportTask::executeTask() QuaZipFile indexFile(&zip); if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) { QFile::remove(output); - emitFailed(tr("Could not create index")); return; } - indexFile.write(generateIndex()); + indexFile.write(generateIndex(resolved)); } - // should exist - QDir dotMinecraft(instance->gameRoot()); - { size_t i = 0; for (const QFileInfo& file : files) { setProgress(i, files.length()); - if (!JlCompress::compressFile(&zip, file.absoluteFilePath(), - "overrides/" + dotMinecraft.relativeFilePath(file.absoluteFilePath()))) { - emitFailed(tr("Could not compress %1").arg(file.absoluteFilePath())); - return; - } + QString relative = mc.relativeFilePath(file.absoluteFilePath()); + if (!resolved.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) + qWarning() << "Could not compress" << file; i++; } } @@ -88,9 +150,11 @@ void ModrinthPackExportTask::executeTask() emitSucceeded(); }); + connect(versionsTask.get(), &NetJob::failed, this, [this](const QString& reason) { emitFailed(reason); }); + versionsTask->start(); } -QByteArray ModrinthPackExportTask::generateIndex() +QByteArray ModrinthPackExportTask::generateIndex(const QMap& urls) { QJsonObject obj; obj["formatVersion"] = 1; @@ -121,5 +185,26 @@ QByteArray ModrinthPackExportTask::generateIndex() obj["dependencies"] = dependencies; } + QJsonArray files; + QMapIterator iterator(urls); + while (iterator.hasNext()) { + iterator.next(); + + const ResolvedFile& value = iterator.value(); + + QJsonObject file; + file["path"] = iterator.key(); + file["downloads"] = QJsonArray({ iterator.value().url }); + + QJsonObject hashes; + hashes["sha1"] = value.sha1; + hashes["sha512"] = value.sha512; + file["hashes"] = hashes; + file["fileSize"] = value.size; + + files << file; + } + obj["files"] = files; + return QJsonDocument(obj).toJson(QJsonDocument::Compact); } \ No newline at end of file diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index c38be204..974c9f0e 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -40,5 +40,10 @@ class ModrinthPackExportTask : public Task { const QString output; const MMCZip::FilterFunction filter; - QByteArray generateIndex(); + struct ResolvedFile { + QString sha1, sha512, url; + int size; + }; + + QByteArray generateIndex(const QMap& urls); }; \ No newline at end of file -- cgit From 55f928f845b56d09a124f1ba85e196c2b91d856d Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 3 Mar 2023 15:06:29 +0000 Subject: More consistent naming Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 81663c9a..266479b3 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -60,7 +60,7 @@ void ExportMrPackDialog::done(int result) const QString filename = FS::RemoveInvalidFilenameChars(ui->name->text()); const QString output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), FS::PathCombine(QDir::homePath(), filename + ".mrpack"), - "Modrinth modpack (*.mrpack *.zip)", nullptr); + "Modrinth pack (*.mrpack *.zip)", nullptr); if (output.isEmpty()) return; -- cgit From a2716f5cf6d72168ab5aa4415c046505e42404f1 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 4 Mar 2023 10:24:25 +0000 Subject: Improve code Even more broken now (it is stuck loading forever)! Signed-off-by: TheKodeToad --- .../modrinth/ModrinthPackExportTask.cpp | 153 +++++++++++---------- .../modplatform/modrinth/ModrinthPackExportTask.h | 14 +- 2 files changed, 93 insertions(+), 74 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index a319eec4..d7a43c7a 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -29,6 +29,8 @@ #include "minecraft/PackProfile.h" #include "modplatform/modrinth/ModrinthAPI.h" +const QStringList ModrinthPackExportTask::PREFIXES = QStringList({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); + ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, const QString& version, const QString& summary, @@ -41,28 +43,34 @@ ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, void ModrinthPackExportTask::executeTask() { setStatus(tr("Searching for files...")); + setProgress(0, 0); + collectFiles(); + + QByteArray* response = new QByteArray; + Task::Ptr versionsTask = api.currentVersions(fileHashes.values(), "sha512", response); + connect(versionsTask.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); + connect(versionsTask.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed); + versionsTask->start(); +} - QFileInfoList files; +void ModrinthPackExportTask::collectFiles() +{ + files.clear(); if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) { emitFailed(tr("Could not collect list of files")); return; } - QDir mc(instance->gameRoot()); - - ModrinthAPI api; - - static const QStringList prefixes({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); - // hash -> file - QMap hashes; + fileHashes.clear(); + QDir mc(instance->gameRoot()); for (QFileInfo file : files) { QString relative = mc.relativeFilePath(file.absoluteFilePath()); // require sensible file types if (!(relative.endsWith(".zip") || relative.endsWith(".jar") || relative.endsWith(".litemod"))) continue; - if (!std::any_of(prefixes.begin(), prefixes.end(), + if (!std::any_of(PREFIXES.begin(), PREFIXES.end(), [&relative](const QString& prefix) { return relative.startsWith(prefix + QDir::separator()); })) continue; @@ -79,82 +87,81 @@ void ModrinthPackExportTask::executeTask() continue; } - hashes[hash.result().toHex()] = relative; + fileHashes[relative] = hash.result().toHex(); } +} - QByteArray* response = new QByteArray; - Task::Ptr versionsTask = api.currentVersions(hashes.keys(), "sha512", response); - connect(versionsTask.get(), &NetJob::succeeded, this, [this, mc, files, hashes, response, versionsTask]() { - // file -> url - QMap resolved; - - try { - QJsonDocument doc = Json::requireDocument(*response); - for (auto iter = hashes.keyBegin(); iter != hashes.keyEnd(); iter++) { - QJsonObject obj = doc[*iter].toObject(); - if (obj.isEmpty()) - continue; - - QJsonArray files = obj["files"].toArray(); - if (auto fileIter = std::find_if(files.begin(), files.end(), - [&iter](const QJsonValue& file) { return file["hashes"]["sha512"] == *iter; }); - fileIter != files.end()) { - // map the file to the url - resolved[hashes[*iter]] = ResolvedFile{ fileIter->toObject()["hashes"].toObject()["sha1"].toString(), *iter, - fileIter->toObject()["url"].toString(), fileIter->toObject()["size"].toInt() }; - } +void ModrinthPackExportTask::parseApiResponse(QByteArray* response) +{ + QMap resolved; + + try { + QJsonDocument doc = Json::requireDocument(*response); + + QMapIterator iterator(fileHashes); + while (iterator.hasNext()) { + iterator.next(); + + QJsonObject obj = doc[iterator.value()].toObject(); + if (obj.isEmpty()) + continue; + + QJsonArray files = obj["files"].toArray(); + if (auto fileIter = std::find_if(files.begin(), files.end(), + [&iterator](const QJsonValue& file) { return file["hashes"]["sha512"] == iterator.value(); }); + fileIter != files.end()) { + // map the file to the url + resolved[iterator.key()] = ResolvedFile{ fileIter->toObject()["hashes"].toObject()["sha1"].toString(), iterator.value(), + fileIter->toObject()["url"].toString(), fileIter->toObject()["size"].toInt() }; } - } catch (Json::JsonException& e) { - qWarning() << "Failed to parse versions response" << e.what(); } + } catch (Json::JsonException& e) { + qWarning() << "Failed to parse versions response" << e.what(); + } - delete response; - - setStatus("Adding files..."); + buildZip(resolved); +} - QuaZip zip(output); - if (!zip.open(QuaZip::mdCreate)) { - QFile::remove(output); - emitFailed(tr("Could not create file")); - return; - } +void ModrinthPackExportTask::buildZip(const QMap& resolvedFiles) +{ + setStatus("Adding files..."); + QuaZip zip(output); + if (!zip.open(QuaZip::mdCreate)) { + QFile::remove(output); + emitFailed(tr("Could not create file")); + return; + } - { - QuaZipFile indexFile(&zip); - if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) { - QFile::remove(output); - emitFailed(tr("Could not create index")); - return; - } - indexFile.write(generateIndex(resolved)); - } + QuaZipFile indexFile(&zip); + if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) { + QFile::remove(output); + emitFailed(tr("Could not create index")); + return; + } + indexFile.write(generateIndex(resolvedFiles)); - { - size_t i = 0; - for (const QFileInfo& file : files) { - setProgress(i, files.length()); - QString relative = mc.relativeFilePath(file.absoluteFilePath()); - if (!resolved.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) - qWarning() << "Could not compress" << file; - i++; - } - } + QDir mc(instance->gameRoot()); + size_t i = 0; + for (const QFileInfo& file : files) { + setProgress(i, files.length()); + QString relative = mc.relativeFilePath(file.absoluteFilePath()); + if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) + qWarning() << "Could not compress" << file; + i++; + } - zip.close(); + zip.close(); - if (zip.getZipError() != 0) { - QFile::remove(output); - emitFailed(tr("A zip error occured")); - return; - } + if (zip.getZipError() != 0) { + QFile::remove(output); + emitFailed(tr("A zip error occured")); + return; + } - emitSucceeded(); - }); - connect(versionsTask.get(), &NetJob::failed, this, [this](const QString& reason) { emitFailed(reason); }); - versionsTask->start(); + emitSucceeded(); } -QByteArray ModrinthPackExportTask::generateIndex(const QMap& urls) +QByteArray ModrinthPackExportTask::generateIndex(const QMap& resolvedFiles) { QJsonObject obj; obj["formatVersion"] = 1; @@ -186,7 +193,7 @@ QByteArray ModrinthPackExportTask::generateIndex(const QMap iterator(urls); + QMapIterator iterator(resolvedFiles); while (iterator.hasNext()) { iterator.next(); diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index 974c9f0e..4ac00522 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -20,6 +20,7 @@ #include "BaseInstance.h" #include "MMCZip.h" +#include "modplatform/modrinth/ModrinthAPI.h" #include "tasks/Task.h" class ModrinthPackExportTask : public Task { @@ -35,15 +36,26 @@ class ModrinthPackExportTask : public Task { void executeTask() override; private: + static const QStringList PREFIXES; + + // inputs const QString name, version, summary; const InstancePtr instance; const QString output; const MMCZip::FilterFunction filter; + ModrinthAPI api; + QFileInfoList files; + QMap fileHashes; + struct ResolvedFile { QString sha1, sha512, url; int size; }; - QByteArray generateIndex(const QMap& urls); + void collectFiles(); + void parseApiResponse(QByteArray* response); + void buildZip(const QMap& resolvedFiles); + + QByteArray generateIndex(const QMap& resolvedFiles); }; \ No newline at end of file -- cgit From f583e617ec86a7538523a99ae008143a787e593b Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 4 Mar 2023 10:37:52 +0000 Subject: Implement abort (possible broken?) and therefore make it work without crashing! The shared pointer was going out of scope 🤦. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 14 ++++++++++---- launcher/modplatform/modrinth/ModrinthPackExportTask.h | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index d7a43c7a..c151edf5 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -47,10 +47,16 @@ void ModrinthPackExportTask::executeTask() collectFiles(); QByteArray* response = new QByteArray; - Task::Ptr versionsTask = api.currentVersions(fileHashes.values(), "sha512", response); - connect(versionsTask.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); - connect(versionsTask.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed); - versionsTask->start(); + task = api.currentVersions(fileHashes.values(), "sha512", response); + connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); + connect(task.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed); + task->start(); +} + +bool ModrinthPackExportTask::abort() { + if (!task.isNull()) + return task->abort(); + return false; } void ModrinthPackExportTask::collectFiles() diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index 4ac00522..ec87c1cd 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -34,6 +34,7 @@ class ModrinthPackExportTask : public Task { protected: void executeTask() override; + bool abort() override; private: static const QStringList PREFIXES; @@ -47,6 +48,7 @@ class ModrinthPackExportTask : public Task { ModrinthAPI api; QFileInfoList files; QMap fileHashes; + Task::Ptr task; struct ResolvedFile { QString sha1, sha512, url; -- cgit From 87384182a19ea852522af1b0d69420a510c0a94b Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 4 Mar 2023 11:07:07 +0000 Subject: Fix abort? Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 8 ++++++-- launcher/ui/dialogs/ExportMrPackDialog.cpp | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index c151edf5..5ddd3408 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -54,8 +54,12 @@ void ModrinthPackExportTask::executeTask() } bool ModrinthPackExportTask::abort() { - if (!task.isNull()) - return task->abort(); + if (!task.isNull() && task->abort()) { + task = nullptr; + emitFailed(tr("Aborted")); + return true; + } + return false; } diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 266479b3..13262a7e 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -70,7 +70,8 @@ void ExportMrPackDialog::done(int result) ProgressDialog progress(this); progress.setSkipButton(true, tr("Abort")); - progress.execWithTask(&task); + if (progress.execWithTask(&task) != QDialog::Accepted) + return; } QDialog::done(result); -- cgit From 970ec8187c2a6b45b9b1031260c07f4e26fe8827 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 4 Mar 2023 19:55:38 +0000 Subject: More refactoring Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 4 +- launcher/FileIgnoreProxy.cpp | 266 +++++++++++++++++++++ launcher/FileIgnoreProxy.h | 71 ++++++ launcher/PackIgnoreProxy.cpp | 266 --------------------- launcher/PackIgnoreProxy.h | 71 ------ .../modrinth/ModrinthPackExportTask.cpp | 29 ++- .../modplatform/modrinth/ModrinthPackExportTask.h | 17 +- launcher/ui/dialogs/ExportInstanceDialog.cpp | 2 +- launcher/ui/dialogs/ExportInstanceDialog.h | 4 +- launcher/ui/dialogs/ExportMrPackDialog.cpp | 9 +- launcher/ui/dialogs/ExportMrPackDialog.h | 4 +- 11 files changed, 373 insertions(+), 370 deletions(-) create mode 100644 launcher/FileIgnoreProxy.cpp create mode 100644 launcher/FileIgnoreProxy.h delete mode 100644 launcher/PackIgnoreProxy.cpp delete mode 100644 launcher/PackIgnoreProxy.h (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 380e8336..66099c4e 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -666,8 +666,8 @@ SET(LAUNCHER_SOURCES # FIXME: maybe find a better home for this. SkinUtils.cpp SkinUtils.h - PackIgnoreProxy.cpp - PackIgnoreProxy.h + FileIgnoreProxy.cpp + FileIgnoreProxy.h # GUI - setup wizard ui/setupwizard/SetupWizard.h diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp new file mode 100644 index 00000000..7dda0290 --- /dev/null +++ b/launcher/FileIgnoreProxy.cpp @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "FileIgnoreProxy.h" + +#include +#include +#include +#include +#include "FileSystem.h" +#include "SeparatorPrefixTree.h" +#include "StringUtils.h" + +FileIgnoreProxy::FileIgnoreProxy(QString root, QObject* parent) : QSortFilterProxyModel(parent), root(root) {} +// NOTE: Sadly, we have to do sorting ourselves. +bool FileIgnoreProxy::lessThan(const QModelIndex& left, const QModelIndex& right) const +{ + QFileSystemModel* fsm = qobject_cast(sourceModel()); + if (!fsm) { + return QSortFilterProxyModel::lessThan(left, right); + } + bool asc = sortOrder() == Qt::AscendingOrder ? true : false; + + QFileInfo leftFileInfo = fsm->fileInfo(left); + QFileInfo rightFileInfo = fsm->fileInfo(right); + + if (!leftFileInfo.isDir() && rightFileInfo.isDir()) { + return !asc; + } + if (leftFileInfo.isDir() && !rightFileInfo.isDir()) { + return asc; + } + + // sort and proxy model breaks the original model... + if (sortColumn() == 0) { + return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), Qt::CaseInsensitive) < 0; + } + if (sortColumn() == 1) { + auto leftSize = leftFileInfo.size(); + auto rightSize = rightFileInfo.size(); + if ((leftSize == rightSize) || (leftFileInfo.isDir() && rightFileInfo.isDir())) { + return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), Qt::CaseInsensitive) < 0 ? asc : !asc; + } + return leftSize < rightSize; + } + return QSortFilterProxyModel::lessThan(left, right); +} + +Qt::ItemFlags FileIgnoreProxy::flags(const QModelIndex& index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + + auto sourceIndex = mapToSource(index); + Qt::ItemFlags flags = sourceIndex.flags(); + if (index.column() == 0) { + flags |= Qt::ItemIsUserCheckable; + if (sourceIndex.model()->hasChildren(sourceIndex)) { + flags |= Qt::ItemIsAutoTristate; + } + } + + return flags; +} + +QVariant FileIgnoreProxy::data(const QModelIndex& index, int role) const +{ + QModelIndex sourceIndex = mapToSource(index); + + if (index.column() == 0 && role == Qt::CheckStateRole) { + QFileSystemModel* fsm = qobject_cast(sourceModel()); + auto blockedPath = relPath(fsm->filePath(sourceIndex)); + auto cover = blocked.cover(blockedPath); + if (!cover.isNull()) { + return QVariant(Qt::Unchecked); + } else if (blocked.exists(blockedPath)) { + return QVariant(Qt::PartiallyChecked); + } else { + return QVariant(Qt::Checked); + } + } + + return sourceIndex.data(role); +} + +bool FileIgnoreProxy::setData(const QModelIndex& index, const QVariant& value, int role) +{ + if (index.column() == 0 && role == Qt::CheckStateRole) { + Qt::CheckState state = static_cast(value.toInt()); + return setFilterState(index, state); + } + + QModelIndex sourceIndex = mapToSource(index); + return QSortFilterProxyModel::sourceModel()->setData(sourceIndex, value, role); +} + +QString FileIgnoreProxy::relPath(const QString& path) const +{ + QString prefix = QDir().absoluteFilePath(root); + prefix += '/'; + if (!path.startsWith(prefix)) { + return QString(); + } + return path.mid(prefix.size()); +} + +bool FileIgnoreProxy::setFilterState(QModelIndex index, Qt::CheckState state) +{ + QFileSystemModel* fsm = qobject_cast(sourceModel()); + + if (!fsm) { + return false; + } + + QModelIndex sourceIndex = mapToSource(index); + auto blockedPath = relPath(fsm->filePath(sourceIndex)); + bool changed = false; + if (state == Qt::Unchecked) { + // blocking a path + auto& node = blocked.insert(blockedPath); + // get rid of all blocked nodes below + node.clear(); + changed = true; + } else if (state == Qt::Checked || state == Qt::PartiallyChecked) { + if (!blocked.remove(blockedPath)) { + auto cover = blocked.cover(blockedPath); + qDebug() << "Blocked by cover" << cover; + // uncover + blocked.remove(cover); + // block all contents, except for any cover + QModelIndex rootIndex = fsm->index(FS::PathCombine(root, cover)); + QModelIndex doing = rootIndex; + int row = 0; + QStack todo; + while (1) { + auto node = fsm->index(row, 0, doing); + if (!node.isValid()) { + if (!todo.size()) { + break; + } else { + doing = todo.pop(); + row = 0; + continue; + } + } + auto relpath = relPath(fsm->filePath(node)); + if (blockedPath.startsWith(relpath)) // cover found? + { + // continue processing cover later + todo.push(node); + } else { + // or just block this one. + blocked.insert(relpath); + } + row++; + } + } + changed = true; + } + if (changed) { + // update the thing + emit dataChanged(index, index, { Qt::CheckStateRole }); + // update everything above index + QModelIndex up = index.parent(); + while (1) { + if (!up.isValid()) + break; + emit dataChanged(up, up, { Qt::CheckStateRole }); + up = up.parent(); + } + // and everything below the index + QModelIndex doing = index; + int row = 0; + QStack todo; + while (1) { + auto node = this->index(row, 0, doing); + if (!node.isValid()) { + if (!todo.size()) { + break; + } else { + doing = todo.pop(); + row = 0; + continue; + } + } + emit dataChanged(node, node, { Qt::CheckStateRole }); + todo.push(node); + row++; + } + // siblings and unrelated nodes are ignored + } + return true; +} + +bool FileIgnoreProxy::shouldExpand(QModelIndex index) +{ + QModelIndex sourceIndex = mapToSource(index); + QFileSystemModel* fsm = qobject_cast(sourceModel()); + if (!fsm) { + return false; + } + auto blockedPath = relPath(fsm->filePath(sourceIndex)); + auto found = blocked.find(blockedPath); + if (found) { + return !found->leaf(); + } + return false; +} + +void FileIgnoreProxy::setBlockedPaths(QStringList paths) +{ + beginResetModel(); + blocked.clear(); + blocked.insert(paths); + endResetModel(); +} + +const SeparatorPrefixTree<'/'>& FileIgnoreProxy::blockedPaths() const +{ + return blocked; +} + +bool FileIgnoreProxy::filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const +{ + Q_UNUSED(source_parent) + + // adjust the columns you want to filter out here + // return false for those that will be hidden + if (source_column == 2 || source_column == 3) + return false; + + return true; +} \ No newline at end of file diff --git a/launcher/FileIgnoreProxy.h b/launcher/FileIgnoreProxy.h new file mode 100644 index 00000000..a0f6c51a --- /dev/null +++ b/launcher/FileIgnoreProxy.h @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include "SeparatorPrefixTree.h" + +class FileIgnoreProxy : public QSortFilterProxyModel { + Q_OBJECT + + public: + FileIgnoreProxy(QString root, QObject* parent); + // NOTE: Sadly, we have to do sorting ourselves. + bool lessThan(const QModelIndex& left, const QModelIndex& right) const; + + virtual Qt::ItemFlags flags(const QModelIndex& index) const; + + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); + + QString relPath(const QString& path) const; + + bool setFilterState(QModelIndex index, Qt::CheckState state); + + bool shouldExpand(QModelIndex index); + + void setBlockedPaths(QStringList paths); + + const SeparatorPrefixTree<'/'>& blockedPaths() const; + + protected: + bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const; + + private: + const QString root; + SeparatorPrefixTree<'/'> blocked; +}; \ No newline at end of file diff --git a/launcher/PackIgnoreProxy.cpp b/launcher/PackIgnoreProxy.cpp deleted file mode 100644 index bd0a82a4..00000000 --- a/launcher/PackIgnoreProxy.cpp +++ /dev/null @@ -1,266 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2023 TheKodeToad - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright 2013-2021 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "PackIgnoreProxy.h" - -#include -#include -#include -#include -#include "FileSystem.h" -#include "SeparatorPrefixTree.h" -#include "StringUtils.h" - -PackIgnoreProxy::PackIgnoreProxy(QString root, QObject* parent) : QSortFilterProxyModel(parent), root(root) {} -// NOTE: Sadly, we have to do sorting ourselves. -bool PackIgnoreProxy::lessThan(const QModelIndex& left, const QModelIndex& right) const -{ - QFileSystemModel* fsm = qobject_cast(sourceModel()); - if (!fsm) { - return QSortFilterProxyModel::lessThan(left, right); - } - bool asc = sortOrder() == Qt::AscendingOrder ? true : false; - - QFileInfo leftFileInfo = fsm->fileInfo(left); - QFileInfo rightFileInfo = fsm->fileInfo(right); - - if (!leftFileInfo.isDir() && rightFileInfo.isDir()) { - return !asc; - } - if (leftFileInfo.isDir() && !rightFileInfo.isDir()) { - return asc; - } - - // sort and proxy model breaks the original model... - if (sortColumn() == 0) { - return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), Qt::CaseInsensitive) < 0; - } - if (sortColumn() == 1) { - auto leftSize = leftFileInfo.size(); - auto rightSize = rightFileInfo.size(); - if ((leftSize == rightSize) || (leftFileInfo.isDir() && rightFileInfo.isDir())) { - return StringUtils::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(), Qt::CaseInsensitive) < 0 ? asc : !asc; - } - return leftSize < rightSize; - } - return QSortFilterProxyModel::lessThan(left, right); -} - -Qt::ItemFlags PackIgnoreProxy::flags(const QModelIndex& index) const -{ - if (!index.isValid()) - return Qt::NoItemFlags; - - auto sourceIndex = mapToSource(index); - Qt::ItemFlags flags = sourceIndex.flags(); - if (index.column() == 0) { - flags |= Qt::ItemIsUserCheckable; - if (sourceIndex.model()->hasChildren(sourceIndex)) { - flags |= Qt::ItemIsAutoTristate; - } - } - - return flags; -} - -QVariant PackIgnoreProxy::data(const QModelIndex& index, int role) const -{ - QModelIndex sourceIndex = mapToSource(index); - - if (index.column() == 0 && role == Qt::CheckStateRole) { - QFileSystemModel* fsm = qobject_cast(sourceModel()); - auto blockedPath = relPath(fsm->filePath(sourceIndex)); - auto cover = blocked.cover(blockedPath); - if (!cover.isNull()) { - return QVariant(Qt::Unchecked); - } else if (blocked.exists(blockedPath)) { - return QVariant(Qt::PartiallyChecked); - } else { - return QVariant(Qt::Checked); - } - } - - return sourceIndex.data(role); -} - -bool PackIgnoreProxy::setData(const QModelIndex& index, const QVariant& value, int role) -{ - if (index.column() == 0 && role == Qt::CheckStateRole) { - Qt::CheckState state = static_cast(value.toInt()); - return setFilterState(index, state); - } - - QModelIndex sourceIndex = mapToSource(index); - return QSortFilterProxyModel::sourceModel()->setData(sourceIndex, value, role); -} - -QString PackIgnoreProxy::relPath(const QString& path) const -{ - QString prefix = QDir().absoluteFilePath(root); - prefix += '/'; - if (!path.startsWith(prefix)) { - return QString(); - } - return path.mid(prefix.size()); -} - -bool PackIgnoreProxy::setFilterState(QModelIndex index, Qt::CheckState state) -{ - QFileSystemModel* fsm = qobject_cast(sourceModel()); - - if (!fsm) { - return false; - } - - QModelIndex sourceIndex = mapToSource(index); - auto blockedPath = relPath(fsm->filePath(sourceIndex)); - bool changed = false; - if (state == Qt::Unchecked) { - // blocking a path - auto& node = blocked.insert(blockedPath); - // get rid of all blocked nodes below - node.clear(); - changed = true; - } else if (state == Qt::Checked || state == Qt::PartiallyChecked) { - if (!blocked.remove(blockedPath)) { - auto cover = blocked.cover(blockedPath); - qDebug() << "Blocked by cover" << cover; - // uncover - blocked.remove(cover); - // block all contents, except for any cover - QModelIndex rootIndex = fsm->index(FS::PathCombine(root, cover)); - QModelIndex doing = rootIndex; - int row = 0; - QStack todo; - while (1) { - auto node = fsm->index(row, 0, doing); - if (!node.isValid()) { - if (!todo.size()) { - break; - } else { - doing = todo.pop(); - row = 0; - continue; - } - } - auto relpath = relPath(fsm->filePath(node)); - if (blockedPath.startsWith(relpath)) // cover found? - { - // continue processing cover later - todo.push(node); - } else { - // or just block this one. - blocked.insert(relpath); - } - row++; - } - } - changed = true; - } - if (changed) { - // update the thing - emit dataChanged(index, index, { Qt::CheckStateRole }); - // update everything above index - QModelIndex up = index.parent(); - while (1) { - if (!up.isValid()) - break; - emit dataChanged(up, up, { Qt::CheckStateRole }); - up = up.parent(); - } - // and everything below the index - QModelIndex doing = index; - int row = 0; - QStack todo; - while (1) { - auto node = this->index(row, 0, doing); - if (!node.isValid()) { - if (!todo.size()) { - break; - } else { - doing = todo.pop(); - row = 0; - continue; - } - } - emit dataChanged(node, node, { Qt::CheckStateRole }); - todo.push(node); - row++; - } - // siblings and unrelated nodes are ignored - } - return true; -} - -bool PackIgnoreProxy::shouldExpand(QModelIndex index) -{ - QModelIndex sourceIndex = mapToSource(index); - QFileSystemModel* fsm = qobject_cast(sourceModel()); - if (!fsm) { - return false; - } - auto blockedPath = relPath(fsm->filePath(sourceIndex)); - auto found = blocked.find(blockedPath); - if (found) { - return !found->leaf(); - } - return false; -} - -void PackIgnoreProxy::setBlockedPaths(QStringList paths) -{ - beginResetModel(); - blocked.clear(); - blocked.insert(paths); - endResetModel(); -} - -const SeparatorPrefixTree<'/'>& PackIgnoreProxy::blockedPaths() const -{ - return blocked; -} - -bool PackIgnoreProxy::filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const -{ - Q_UNUSED(source_parent) - - // adjust the columns you want to filter out here - // return false for those that will be hidden - if (source_column == 2 || source_column == 3) - return false; - - return true; -} \ No newline at end of file diff --git a/launcher/PackIgnoreProxy.h b/launcher/PackIgnoreProxy.h deleted file mode 100644 index aec42b41..00000000 --- a/launcher/PackIgnoreProxy.h +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2023 TheKodeToad - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright 2013-2021 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include "SeparatorPrefixTree.h" - -class PackIgnoreProxy : public QSortFilterProxyModel { - Q_OBJECT - - public: - PackIgnoreProxy(QString root, QObject* parent); - // NOTE: Sadly, we have to do sorting ourselves. - bool lessThan(const QModelIndex& left, const QModelIndex& right) const; - - virtual Qt::ItemFlags flags(const QModelIndex& index) const; - - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; - virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); - - QString relPath(const QString& path) const; - - bool setFilterState(QModelIndex index, Qt::CheckState state); - - bool shouldExpand(QModelIndex index); - - void setBlockedPaths(QStringList paths); - - const SeparatorPrefixTree<'/'>& blockedPaths() const; - - protected: - bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const; - - private: - const QString root; - SeparatorPrefixTree<'/'> blocked; -}; \ No newline at end of file diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 5ddd3408..3c69413d 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -27,6 +27,7 @@ #include "MMCZip.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" +#include "minecraft/mod/Mod.h" #include "modplatform/modrinth/ModrinthAPI.h" const QStringList ModrinthPackExportTask::PREFIXES = QStringList({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); @@ -47,13 +48,14 @@ void ModrinthPackExportTask::executeTask() collectFiles(); QByteArray* response = new QByteArray; - task = api.currentVersions(fileHashes.values(), "sha512", response); + task = api.currentVersions(pendingHashes.values(), "sha512", response); connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); connect(task.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed); task->start(); } -bool ModrinthPackExportTask::abort() { +bool ModrinthPackExportTask::abort() +{ if (!task.isNull() && task->abort()) { task = nullptr; emitFailed(tr("Aborted")); @@ -71,7 +73,8 @@ void ModrinthPackExportTask::collectFiles() return; } - fileHashes.clear(); + pendingHashes.clear(); + resolvedFiles.clear(); QDir mc(instance->gameRoot()); for (QFileInfo file : files) { @@ -97,18 +100,16 @@ void ModrinthPackExportTask::collectFiles() continue; } - fileHashes[relative] = hash.result().toHex(); + pendingHashes[relative] = hash.result().toHex(); } } void ModrinthPackExportTask::parseApiResponse(QByteArray* response) { - QMap resolved; - try { QJsonDocument doc = Json::requireDocument(*response); - QMapIterator iterator(fileHashes); + QMapIterator iterator(pendingHashes); while (iterator.hasNext()) { iterator.next(); @@ -121,18 +122,20 @@ void ModrinthPackExportTask::parseApiResponse(QByteArray* response) [&iterator](const QJsonValue& file) { return file["hashes"]["sha512"] == iterator.value(); }); fileIter != files.end()) { // map the file to the url - resolved[iterator.key()] = ResolvedFile{ fileIter->toObject()["hashes"].toObject()["sha1"].toString(), iterator.value(), - fileIter->toObject()["url"].toString(), fileIter->toObject()["size"].toInt() }; + resolvedFiles[iterator.key()] = + ResolvedFile{ fileIter->toObject()["hashes"].toObject()["sha1"].toString(), iterator.value(), + fileIter->toObject()["url"].toString(), fileIter->toObject()["size"].toInt() }; } } } catch (Json::JsonException& e) { qWarning() << "Failed to parse versions response" << e.what(); } + pendingHashes.clear(); - buildZip(resolved); + buildZip(); } -void ModrinthPackExportTask::buildZip(const QMap& resolvedFiles) +void ModrinthPackExportTask::buildZip() { setStatus("Adding files..."); QuaZip zip(output); @@ -148,7 +151,7 @@ void ModrinthPackExportTask::buildZip(const QMap& resolve emitFailed(tr("Could not create index")); return; } - indexFile.write(generateIndex(resolvedFiles)); + indexFile.write(generateIndex()); QDir mc(instance->gameRoot()); size_t i = 0; @@ -171,7 +174,7 @@ void ModrinthPackExportTask::buildZip(const QMap& resolve emitSucceeded(); } -QByteArray ModrinthPackExportTask::generateIndex(const QMap& resolvedFiles) +QByteArray ModrinthPackExportTask::generateIndex() { QJsonObject obj; obj["formatVersion"] = 1; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index ec87c1cd..d7a42e7b 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -37,6 +37,11 @@ class ModrinthPackExportTask : public Task { bool abort() override; private: + struct ResolvedFile { + QString sha1, sha512, url; + int size; + }; + static const QStringList PREFIXES; // inputs @@ -47,17 +52,13 @@ class ModrinthPackExportTask : public Task { ModrinthAPI api; QFileInfoList files; - QMap fileHashes; + QMap pendingHashes; + QMap resolvedFiles; Task::Ptr task; - struct ResolvedFile { - QString sha1, sha512, url; - int size; - }; - void collectFiles(); void parseApiResponse(QByteArray* response); - void buildZip(const QMap& resolvedFiles); + void buildZip(); - QByteArray generateIndex(const QMap& resolvedFiles); + QByteArray generateIndex(); }; \ No newline at end of file diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index f310a689..ea01c5e2 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -57,7 +57,7 @@ ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget *parent ui->setupUi(this); auto model = new QFileSystemModel(this); auto root = instance->instanceRoot(); - proxyModel = new PackIgnoreProxy(root, this); + proxyModel = new FileIgnoreProxy(root, this); loadPackIgnore(); proxyModel->setSourceModel(model); ui->treeView->setModel(proxyModel); diff --git a/launcher/ui/dialogs/ExportInstanceDialog.h b/launcher/ui/dialogs/ExportInstanceDialog.h index b1b8f911..d96f4537 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.h +++ b/launcher/ui/dialogs/ExportInstanceDialog.h @@ -18,7 +18,7 @@ #include #include #include -#include "PackIgnoreProxy.h" +#include "FileIgnoreProxy.h" class BaseInstance; typedef std::shared_ptr InstancePtr; @@ -47,7 +47,7 @@ private: private: Ui::ExportInstanceDialog *ui; InstancePtr m_instance; - PackIgnoreProxy * proxyModel; + FileIgnoreProxy * proxyModel; private slots: void rowsInserted(QModelIndex parent, int top, int bottom); diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 13262a7e..1a69cc53 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -37,7 +37,7 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) auto model = new QFileSystemModel(this); // use the game root - everything outside cannot be exported QString root = instance->gameRoot(); - proxy = new PackIgnoreProxy(root, this); + proxy = new FileIgnoreProxy(root, this); proxy->setSourceModel(model); ui->treeView->setModel(proxy); ui->treeView->setRootIndex(proxy->mapFromSource(model->index(root))); @@ -58,16 +58,15 @@ void ExportMrPackDialog::done(int result) { if (result == Accepted) { const QString filename = FS::RemoveInvalidFilenameChars(ui->name->text()); - const QString output = - QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), FS::PathCombine(QDir::homePath(), filename + ".mrpack"), - "Modrinth pack (*.mrpack *.zip)", nullptr); + const QString output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), + FS::PathCombine(QDir::homePath(), filename + ".mrpack"), + "Modrinth pack (*.mrpack *.zip)", nullptr); if (output.isEmpty()) return; ModrinthPackExportTask task(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); - ProgressDialog progress(this); progress.setSkipButton(true, tr("Abort")); if (progress.execWithTask(&task) != QDialog::Accepted) diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportMrPackDialog.h index 3ded4887..63e3f016 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.h +++ b/launcher/ui/dialogs/ExportMrPackDialog.h @@ -20,7 +20,7 @@ #include #include "BaseInstance.h" -#include "PackIgnoreProxy.h" +#include "FileIgnoreProxy.h" namespace Ui { class ExportMrPackDialog; @@ -38,5 +38,5 @@ class ExportMrPackDialog : public QDialog { private: const InstancePtr instance; Ui::ExportMrPackDialog* ui; - PackIgnoreProxy* proxy; + FileIgnoreProxy* proxy; }; -- cgit From 5d5fcae5010ce0860bef23d161f0b0d698ade1ab Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 6 Mar 2023 17:22:20 +0000 Subject: Further reduce buggy behaviour Signed-off-by: TheKodeToad --- .../modrinth/ModrinthPackExportTask.cpp | 84 +++++++++++++--------- .../modplatform/modrinth/ModrinthPackExportTask.h | 1 + 2 files changed, 53 insertions(+), 32 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 3c69413d..e12ee923 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -19,6 +19,7 @@ #include "ModrinthPackExportTask.h" #include +#include #include #include #include @@ -56,13 +57,17 @@ void ModrinthPackExportTask::executeTask() bool ModrinthPackExportTask::abort() { - if (!task.isNull() && task->abort()) { + if (task != nullptr) { + if (!task->abort()) + return false; + task = nullptr; emitFailed(tr("Aborted")); return true; } - return false; + pendingAbort = true; + return true; } void ModrinthPackExportTask::collectFiles() @@ -106,6 +111,8 @@ void ModrinthPackExportTask::collectFiles() void ModrinthPackExportTask::parseApiResponse(QByteArray* response) { + task = nullptr; + try { QJsonDocument doc = Json::requireDocument(*response); @@ -137,41 +144,54 @@ void ModrinthPackExportTask::parseApiResponse(QByteArray* response) void ModrinthPackExportTask::buildZip() { - setStatus("Adding files..."); - QuaZip zip(output); - if (!zip.open(QuaZip::mdCreate)) { - QFile::remove(output); - emitFailed(tr("Could not create file")); - return; - } + QtConcurrent::run(QThreadPool::globalInstance(), [this]() { + setStatus("Adding files..."); + QuaZip zip(output); + if (!zip.open(QuaZip::mdCreate)) { + QFile::remove(output); + emitFailed(tr("Could not create file")); + return; + } - QuaZipFile indexFile(&zip); - if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) { - QFile::remove(output); - emitFailed(tr("Could not create index")); - return; - } - indexFile.write(generateIndex()); + if (pendingAbort) { + emitFailed(tr("Aborted")); + return; + } - QDir mc(instance->gameRoot()); - size_t i = 0; - for (const QFileInfo& file : files) { - setProgress(i, files.length()); - QString relative = mc.relativeFilePath(file.absoluteFilePath()); - if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) - qWarning() << "Could not compress" << file; - i++; - } + QuaZipFile indexFile(&zip); + if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) { + QFile::remove(output); + emitFailed(tr("Could not create index")); + return; + } + indexFile.write(generateIndex()); + + QDir mc(instance->gameRoot()); + size_t i = 0; + for (const QFileInfo& file : files) { + if (pendingAbort) { + QFile::remove(output); + emitFailed(tr("Aborted")); + return; + } - zip.close(); + setProgress(i, files.length()); + QString relative = mc.relativeFilePath(file.absoluteFilePath()); + if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) + qWarning() << "Could not compress" << file; + i++; + } - if (zip.getZipError() != 0) { - QFile::remove(output); - emitFailed(tr("A zip error occured")); - return; - } + zip.close(); + + if (zip.getZipError() != 0) { + QFile::remove(output); + emitFailed(tr("A zip error occured")); + return; + } - emitSucceeded(); + emitSucceeded(); + }); } QByteArray ModrinthPackExportTask::generateIndex() diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index d7a42e7b..04578d2c 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -55,6 +55,7 @@ class ModrinthPackExportTask : public Task { QMap pendingHashes; QMap resolvedFiles; Task::Ptr task; + bool pendingAbort = false; void collectFiles(); void parseApiResponse(QByteArray* response); -- cgit From 2cc9b0df068ace61c60217973d4d66412cb53968 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 8 Mar 2023 18:10:52 +0000 Subject: Only select some paths by default - again! Signed-off-by: TheKodeToad --- launcher/FileIgnoreProxy.cpp | 5 ----- launcher/FileIgnoreProxy.h | 3 ++- launcher/ui/dialogs/ExportMrPackDialog.cpp | 17 ++++++++++++++++- 3 files changed, 18 insertions(+), 7 deletions(-) (limited to 'launcher') diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp index 7dda0290..fd05624a 100644 --- a/launcher/FileIgnoreProxy.cpp +++ b/launcher/FileIgnoreProxy.cpp @@ -248,11 +248,6 @@ void FileIgnoreProxy::setBlockedPaths(QStringList paths) endResetModel(); } -const SeparatorPrefixTree<'/'>& FileIgnoreProxy::blockedPaths() const -{ - return blocked; -} - bool FileIgnoreProxy::filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const { Q_UNUSED(source_parent) diff --git a/launcher/FileIgnoreProxy.h b/launcher/FileIgnoreProxy.h index a0f6c51a..baf05c7a 100644 --- a/launcher/FileIgnoreProxy.h +++ b/launcher/FileIgnoreProxy.h @@ -60,7 +60,8 @@ class FileIgnoreProxy : public QSortFilterProxyModel { void setBlockedPaths(QStringList paths); - const SeparatorPrefixTree<'/'>& blockedPaths() const; + inline const SeparatorPrefixTree<'/'>& blockedPaths() const { return blocked; } + inline SeparatorPrefixTree<'/'>& blockedPaths() { return blocked; } protected: bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const; diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 1a69cc53..03238ec4 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -39,11 +39,26 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) QString root = instance->gameRoot(); proxy = new FileIgnoreProxy(root, this); proxy->setSourceModel(model); + + QDir::Filters filter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); + + for (QString file : QDir(root).entryList(filter)) { + if (!(file == "mods" || file == "coremods" || file == "datapacks" || file == "config" || file == "options.txt" || + file == "servers.dat")) + proxy->blockedPaths().insert(file); + } + + QDir modsIndex(instance->gameRoot() + "/mods/.index"); + if (modsIndex.exists()) + proxy->blockedPaths().insert("mods/.index"); + ui->treeView->setModel(proxy); ui->treeView->setRootIndex(proxy->mapFromSource(model->index(root))); ui->treeView->sortByColumn(0, Qt::AscendingOrder); - model->setFilter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); + + model->setFilter(filter); model->setRootPath(root); + auto headerView = ui->treeView->header(); headerView->setSectionResizeMode(QHeaderView::ResizeToContents); headerView->setSectionResizeMode(0, QHeaderView::Stretch); -- cgit From ddca838e46d2d147cbc5965be31895dd73676c79 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 18 Mar 2023 12:21:13 +0000 Subject: Info and error dialogs TODO: is there a better approach? Signed-off-by: TheKodeToad --- .../modplatform/modrinth/ModrinthPackExportTask.cpp | 21 ++++++++++++--------- launcher/ui/dialogs/ExportMrPackDialog.cpp | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 9 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index e12ee923..e8bc3673 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -18,8 +18,7 @@ #include "ModrinthPackExportTask.h" -#include -#include +#include #include #include #include @@ -28,7 +27,6 @@ #include "MMCZip.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" -#include "minecraft/mod/Mod.h" #include "modplatform/modrinth/ModrinthAPI.h" const QStringList ModrinthPackExportTask::PREFIXES = QStringList({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); @@ -62,7 +60,7 @@ bool ModrinthPackExportTask::abort() return false; task = nullptr; - emitFailed(tr("Aborted")); + emitAborted(); return true; } @@ -154,14 +152,16 @@ void ModrinthPackExportTask::buildZip() } if (pendingAbort) { - emitFailed(tr("Aborted")); + QMetaObject::invokeMethod( + this, [this]() { emitAborted(); }, Qt::QueuedConnection); return; } QuaZipFile indexFile(&zip); if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) { QFile::remove(output); - emitFailed(tr("Could not create index")); + QMetaObject::invokeMethod( + this, [this]() { emitFailed(tr("Could not create index")); }, Qt::QueuedConnection); return; } indexFile.write(generateIndex()); @@ -171,7 +171,8 @@ void ModrinthPackExportTask::buildZip() for (const QFileInfo& file : files) { if (pendingAbort) { QFile::remove(output); - emitFailed(tr("Aborted")); + QMetaObject::invokeMethod( + this, [this]() { emitAborted(); }, Qt::QueuedConnection); return; } @@ -186,11 +187,13 @@ void ModrinthPackExportTask::buildZip() if (zip.getZipError() != 0) { QFile::remove(output); - emitFailed(tr("A zip error occured")); + QMetaObject::invokeMethod( + this, [this]() { emitFailed(tr("A zip error occurred")); }, Qt::QueuedConnection); return; } - emitSucceeded(); + QMetaObject::invokeMethod( + this, [this]() { emitSucceeded(); }, Qt::QueuedConnection); }); } diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 03238ec4..8a49f314 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -17,6 +17,8 @@ */ #include "ExportMrPackDialog.h" +#include "Application.h" +#include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" #include "ui_ExportMrPackDialog.h" @@ -82,6 +84,20 @@ void ExportMrPackDialog::done(int result) ModrinthPackExportTask task(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); + + connect(&task, &Task::failed, + [this](const QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); + + connect(&task, &Task::succeeded, [this, &task]() { + QStringList warnings = task.warnings(); + if (warnings.count() > 0) + CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show(); + }); + connect(&task, &Task::aborted, [this] { + CustomMessageBox::selectable(this, tr("Task aborted"), tr("The task has been aborted by the user."), QMessageBox::Information) + ->show(); + }); + ProgressDialog progress(this); progress.setSkipButton(true, tr("Abort")); if (progress.execWithTask(&task) != QDialog::Accepted) -- cgit From 5346dfc782d1736811b60b8548ce4c4335caabff Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 18 Mar 2023 12:57:44 +0000 Subject: Use first line of notes for summary Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 8a49f314..28c719c7 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -17,7 +17,6 @@ */ #include "ExportMrPackDialog.h" -#include "Application.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" #include "ui_ExportMrPackDialog.h" @@ -35,6 +34,7 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) { ui->setupUi(this); ui->name->setText(instance->name()); + ui->summary->setText(instance->notes().split(QRegExp("\\r?\\n"))[0]); auto model = new QFileSystemModel(this); // use the game root - everything outside cannot be exported -- cgit From 8837f06e4e97ed966662b52db206facd7f91a489 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 18 Mar 2023 14:01:41 +0000 Subject: Only add summary if not empty Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index e8bc3673..cfd751d5 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -204,7 +204,8 @@ QByteArray ModrinthPackExportTask::generateIndex() obj["game"] = "minecraft"; obj["name"] = name; obj["versionId"] = version; - obj["summary"] = summary; + if (!summary.isEmpty()) + obj["summary"] = summary; MinecraftInstance* mc = dynamic_cast(instance.get()); if (mc) { -- cgit From ec8cb056bf717edb97bf3e65fbad0ffc1b78ec34 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 19 Mar 2023 11:49:09 +0000 Subject: QRegExp -> QRegularExpression :P Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 28c719c7..02b6721d 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -34,7 +34,7 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) { ui->setupUi(this); ui->name->setText(instance->name()); - ui->summary->setText(instance->notes().split(QRegExp("\\r?\\n"))[0]); + ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); auto model = new QFileSystemModel(this); // use the game root - everything outside cannot be exported -- cgit From 710156b9f1b9555cd7e5562c8673074f80457d92 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 19 Mar 2023 21:25:12 +0000 Subject: Replace native file separator - this was accidentally brought to my attention on Modrinth's guild Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index cfd751d5..f86f1ad1 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -237,7 +237,9 @@ QByteArray ModrinthPackExportTask::generateIndex() const ResolvedFile& value = iterator.value(); QJsonObject file; - file["path"] = iterator.key(); + QString path = iterator.key(); + path.replace(QDir::separator(), "/"); + file["path"] = path; file["downloads"] = QJsonArray({ iterator.value().url }); QJsonObject hashes; -- cgit From 46f448dfba2a3c4bffe60f373ee27b1d19873c9e Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 19 Mar 2023 21:26:25 +0000 Subject: Improve invokeMethod syntax Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index f86f1ad1..46bfab6d 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -152,8 +152,7 @@ void ModrinthPackExportTask::buildZip() } if (pendingAbort) { - QMetaObject::invokeMethod( - this, [this]() { emitAborted(); }, Qt::QueuedConnection); + QMetaObject::invokeMethod(this, &ModrinthPackExportTask::emitAborted, Qt::QueuedConnection); return; } @@ -171,8 +170,7 @@ void ModrinthPackExportTask::buildZip() for (const QFileInfo& file : files) { if (pendingAbort) { QFile::remove(output); - QMetaObject::invokeMethod( - this, [this]() { emitAborted(); }, Qt::QueuedConnection); + QMetaObject::invokeMethod(this, &ModrinthPackExportTask::emitAborted, Qt::QueuedConnection); return; } @@ -192,8 +190,7 @@ void ModrinthPackExportTask::buildZip() return; } - QMetaObject::invokeMethod( - this, [this]() { emitSucceeded(); }, Qt::QueuedConnection); + QMetaObject::invokeMethod(this, &ModrinthPackExportTask::emitSucceeded, Qt::QueuedConnection); }); } @@ -226,6 +223,7 @@ QByteArray ModrinthPackExportTask::generateIndex() dependencies["fabric-loader"] = fabric->m_version; if (forge != nullptr) dependencies["forge"] = forge->m_version; + obj["dependencies"] = dependencies; } -- cgit From e42050cc8a2f74178d6cd0afe8c92ae9b802cf73 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 28 Mar 2023 14:22:28 +0100 Subject: Skip lookup if no files and fail if zipping fails Signed-off-by: TheKodeToad --- .../modrinth/ModrinthPackExportTask.cpp | 22 +++++++++++++++------- launcher/ui/dialogs/ExportMrPackDialog.cpp | 6 ------ 2 files changed, 15 insertions(+), 13 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 46bfab6d..d630f5d0 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -46,11 +46,15 @@ void ModrinthPackExportTask::executeTask() setProgress(0, 0); collectFiles(); - QByteArray* response = new QByteArray; - task = api.currentVersions(pendingHashes.values(), "sha512", response); - connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); - connect(task.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed); - task->start(); + if (pendingHashes.isEmpty()) + buildZip(); + else { + QByteArray* response = new QByteArray; + task = api.currentVersions(pendingHashes.values(), "sha512", response); + connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); + connect(task.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed); + task->start(); + } } bool ModrinthPackExportTask::abort() @@ -176,8 +180,12 @@ void ModrinthPackExportTask::buildZip() setProgress(i, files.length()); QString relative = mc.relativeFilePath(file.absoluteFilePath()); - if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) - qWarning() << "Could not compress" << file; + if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) { + QFile::remove(output); + QMetaObject::invokeMethod( + this, [this, relative]() { emitFailed(tr("Could not compress %1").arg(relative)); }, Qt::QueuedConnection); + return; + } i++; } diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 02b6721d..a622eb30 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -87,12 +87,6 @@ void ExportMrPackDialog::done(int result) connect(&task, &Task::failed, [this](const QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); - - connect(&task, &Task::succeeded, [this, &task]() { - QStringList warnings = task.warnings(); - if (warnings.count() > 0) - CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show(); - }); connect(&task, &Task::aborted, [this] { CustomMessageBox::selectable(this, tr("Task aborted"), tr("The task has been aborted by the user."), QMessageBox::Information) ->show(); -- cgit From 871d647c93944b7dabd070ed49a6eeaa8745d55a Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 6 Apr 2023 19:18:36 +0100 Subject: Use local metadata Signed-off-by: TheKodeToad --- buildconfig/BuildConfig.h | 2 + .../modrinth/ModrinthPackExportTask.cpp | 87 +++++++++++++++++----- .../modplatform/modrinth/ModrinthPackExportTask.h | 5 +- 3 files changed, 73 insertions(+), 21 deletions(-) (limited to 'launcher') diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index a05d7a9e..38fa3a65 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -36,6 +36,7 @@ #pragma once #include +#include /** * \brief The Config class holds all the build-time information passed from the build system. @@ -160,6 +161,7 @@ class Config { QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2"; QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2"; + QStringList MODRINTH_MRPACK_HOSTS{"cdn.modrinth.com", "github.com", "raw.githubusercontent.com", "gitlab.com"}; QString FLAME_BASE_URL = "https://api.curseforge.com/v1"; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index d630f5d0..2ec51991 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -22,14 +22,15 @@ #include #include #include -#include #include "Json.h" #include "MMCZip.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" +#include "minecraft/mod/ModFolderModel.h" #include "modplatform/modrinth/ModrinthAPI.h" -const QStringList ModrinthPackExportTask::PREFIXES = QStringList({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); +const QStringList ModrinthPackExportTask::PREFIXES({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); +const QStringList ModrinthPackExportTask::ALLOWED_HOSTS({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, const QString& version, @@ -45,16 +46,6 @@ void ModrinthPackExportTask::executeTask() setStatus(tr("Searching for files...")); setProgress(0, 0); collectFiles(); - - if (pendingHashes.isEmpty()) - buildZip(); - else { - QByteArray* response = new QByteArray; - task = api.currentVersions(pendingHashes.values(), "sha512", response); - connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); - connect(task.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed); - task->start(); - } } bool ModrinthPackExportTask::abort() @@ -83,6 +74,17 @@ void ModrinthPackExportTask::collectFiles() pendingHashes.clear(); resolvedFiles.clear(); + const MinecraftInstance* mcInstance = dynamic_cast(instance.get()); + auto mods = mcInstance->loaderModList(); + mods->update(); + connect(mods.get(), &ModFolderModel::updateFinished, this, &ModrinthPackExportTask::collectHashes); +} + +void ModrinthPackExportTask::collectHashes() +{ + const MinecraftInstance* mcInstance = dynamic_cast(instance.get()); + auto mods = mcInstance->loaderModList(); + QDir mc(instance->gameRoot()); for (QFileInfo file : files) { QString relative = mc.relativeFilePath(file.absoluteFilePath()); @@ -102,13 +104,58 @@ void ModrinthPackExportTask::collectFiles() continue; } - if (!hash.addData(&openFile)) { - qWarning() << "Could not add hash data for" << file; + QByteArray data = openFile.readAll(); + if (openFile.error() != QFileDevice::NoError) { + qWarning() << "Could not read" << file; continue; } + hash.addData(data); + + auto allMods = mods->allMods(); + if (auto modIter = std::find_if(allMods.begin(), allMods.end(), [&file](Mod* mod) { return mod->fileinfo() == file; }); + modIter != allMods.end()) { + Mod* mod = *modIter; + if (mod->metadata() != nullptr) { + QUrl& url = mod->metadata()->url; + // most likely some of these may be from curseforge + if (!url.isEmpty() && BuildConfig.MODRINTH_MRPACK_HOSTS.contains(url.host())) { + qDebug() << "Resolving" << relative << "from index"; + + // we've already read it + // let's go back! + openFile.seek(openFile.size()); + + QCryptographicHash hash2(QCryptographicHash::Algorithm::Sha1); + hash2.addData(data); + + ResolvedFile file{ hash2.result().toHex(), hash.result().toHex(), url.toString(), openFile.size() }; + resolvedFiles[relative] = file; + + // nice! we've managed to resolve based on local metadata! + // no need to enqueue it + continue; + } + } + } + qDebug() << "Enqueueing" << relative << "for Modrinth query"; pendingHashes[relative] = hash.result().toHex(); } + + makeApiRequest(); +} + +void ModrinthPackExportTask::makeApiRequest() +{ + if (pendingHashes.isEmpty()) + buildZip(); + else { + QByteArray* response = new QByteArray; + task = api.currentVersions(pendingHashes.values(), "sha512", response); + connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); + connect(task.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed); + task->start(); + } } void ModrinthPackExportTask::parseApiResponse(QByteArray* response) @@ -146,7 +193,7 @@ void ModrinthPackExportTask::parseApiResponse(QByteArray* response) void ModrinthPackExportTask::buildZip() { - QtConcurrent::run(QThreadPool::globalInstance(), [this]() { + QThreadPool::globalInstance()->start([this]() { setStatus("Adding files..."); QuaZip zip(output); if (!zip.open(QuaZip::mdCreate)) { @@ -183,7 +230,7 @@ void ModrinthPackExportTask::buildZip() if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) { QFile::remove(output); QMetaObject::invokeMethod( - this, [this, relative]() { emitFailed(tr("Could not compress %1").arg(relative)); }, Qt::QueuedConnection); + this, [this, relative]() { emitFailed(tr("Could not read and compress %1").arg(relative)); }, Qt::QueuedConnection); return; } i++; @@ -216,10 +263,10 @@ QByteArray ModrinthPackExportTask::generateIndex() if (mc) { auto profile = mc->getPackProfile(); // collect all supported components - auto minecraft = profile->getComponent("net.minecraft"); - auto quilt = profile->getComponent("org.quiltmc.quilt-loader"); - auto fabric = profile->getComponent("net.fabricmc.fabric-loader"); - auto forge = profile->getComponent("net.minecraftforge"); + ComponentPtr minecraft = profile->getComponent("net.minecraft"); + ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader"); + ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader"); + ComponentPtr forge = profile->getComponent("net.minecraftforge"); // convert all available components to mrpack dependencies QJsonObject dependencies; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index 04578d2c..217956db 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -39,10 +39,11 @@ class ModrinthPackExportTask : public Task { private: struct ResolvedFile { QString sha1, sha512, url; - int size; + qint64 size; }; static const QStringList PREFIXES; + static const QStringList ALLOWED_HOSTS; // inputs const QString name, version, summary; @@ -58,6 +59,8 @@ class ModrinthPackExportTask : public Task { bool pendingAbort = false; void collectFiles(); + void collectHashes(); + void makeApiRequest(); void parseApiResponse(QByteArray* response); void buildZip(); -- cgit From 073aaf9b3bbe4edb763dfeb1a5b3d22473e59e41 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 6 Apr 2023 19:19:35 +0100 Subject: Remove "prototype" field Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 2ec51991..cfb59fc3 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -30,7 +30,6 @@ #include "modplatform/modrinth/ModrinthAPI.h" const QStringList ModrinthPackExportTask::PREFIXES({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); -const QStringList ModrinthPackExportTask::ALLOWED_HOSTS({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, const QString& version, -- cgit From d7a137ad13854d008de438786d6a97b4092bac99 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 6 Apr 2023 19:24:19 +0100 Subject: Remove more prototype not good code Signed-off-by: TheKodeToad --- .../modrinth/ModrinthPackExportTask.cpp | 22 +++++++++++++--------- .../modplatform/modrinth/ModrinthPackExportTask.h | 2 ++ 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index cfb59fc3..772928e9 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -37,7 +37,13 @@ ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter) - : name(name), version(version), summary(summary), instance(instance), output(output), filter(filter) + : name(name) + , version(version) + , summary(summary) + , instance(instance) + , mcInstance(dynamic_cast(instance.get())) + , output(output) + , filter(filter) {} void ModrinthPackExportTask::executeTask() @@ -73,17 +79,15 @@ void ModrinthPackExportTask::collectFiles() pendingHashes.clear(); resolvedFiles.clear(); - const MinecraftInstance* mcInstance = dynamic_cast(instance.get()); - auto mods = mcInstance->loaderModList(); - mods->update(); - connect(mods.get(), &ModFolderModel::updateFinished, this, &ModrinthPackExportTask::collectHashes); + if (mcInstance) { + mcInstance->loaderModList()->update(); + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, &ModrinthPackExportTask::collectHashes); + } else + collectHashes(); } void ModrinthPackExportTask::collectHashes() { - const MinecraftInstance* mcInstance = dynamic_cast(instance.get()); - auto mods = mcInstance->loaderModList(); - QDir mc(instance->gameRoot()); for (QFileInfo file : files) { QString relative = mc.relativeFilePath(file.absoluteFilePath()); @@ -110,7 +114,7 @@ void ModrinthPackExportTask::collectHashes() } hash.addData(data); - auto allMods = mods->allMods(); + auto allMods = mcInstance->loaderModList()->allMods(); if (auto modIter = std::find_if(allMods.begin(), allMods.end(), [&file](Mod* mod) { return mod->fileinfo() == file; }); modIter != allMods.end()) { Mod* mod = *modIter; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index 217956db..021d8a56 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -20,6 +20,7 @@ #include "BaseInstance.h" #include "MMCZip.h" +#include "minecraft/MinecraftInstance.h" #include "modplatform/modrinth/ModrinthAPI.h" #include "tasks/Task.h" @@ -48,6 +49,7 @@ class ModrinthPackExportTask : public Task { // inputs const QString name, version, summary; const InstancePtr instance; + const MinecraftInstance* mcInstance; const QString output; const MMCZip::FilterFunction filter; -- cgit From 012d8bb4680b54bedd9b58fb6102c768002cf0ed Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 6 Apr 2023 19:58:09 +0100 Subject: Revert concurrent syntax Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 772928e9..f4b2bcd3 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -20,14 +20,12 @@ #include #include -#include #include +#include #include "Json.h" #include "MMCZip.h" -#include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" #include "minecraft/mod/ModFolderModel.h" -#include "modplatform/modrinth/ModrinthAPI.h" const QStringList ModrinthPackExportTask::PREFIXES({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); @@ -190,13 +188,11 @@ void ModrinthPackExportTask::parseApiResponse(QByteArray* response) qWarning() << "Failed to parse versions response" << e.what(); } pendingHashes.clear(); - - buildZip(); } void ModrinthPackExportTask::buildZip() { - QThreadPool::globalInstance()->start([this]() { + static_cast(QtConcurrent::run(QThreadPool::globalInstance(), [this]() { setStatus("Adding files..."); QuaZip zip(output); if (!zip.open(QuaZip::mdCreate)) { @@ -249,7 +245,7 @@ void ModrinthPackExportTask::buildZip() } QMetaObject::invokeMethod(this, &ModrinthPackExportTask::emitSucceeded, Qt::QueuedConnection); - }); + })); } QByteArray ModrinthPackExportTask::generateIndex() @@ -301,6 +297,7 @@ QByteArray ModrinthPackExportTask::generateIndex() QJsonObject hashes; hashes["sha1"] = value.sha1; hashes["sha512"] = value.sha512; + file["hashes"] = hashes; file["fileSize"] = value.size; -- cgit From b65f4c9536691096d44ae427ff71bfe971592747 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 6 Apr 2023 19:59:15 +0100 Subject: Better collectFileListRecursively error Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index f4b2bcd3..2618074e 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -70,7 +70,7 @@ void ModrinthPackExportTask::collectFiles() { files.clear(); if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) { - emitFailed(tr("Could not collect list of files")); + emitFailed(tr("Could not search for files")); return; } -- cgit From 813ccc1381f8cb128d0bdcaac1e62d76e8b74289 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 7 Apr 2023 11:03:11 +0100 Subject: How did i- Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 2618074e..fc16f912 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -164,7 +164,7 @@ void ModrinthPackExportTask::parseApiResponse(QByteArray* response) task = nullptr; try { - QJsonDocument doc = Json::requireDocument(*response); + const QJsonDocument doc = Json::requireDocument(*response); QMapIterator iterator(pendingHashes); while (iterator.hasNext()) { @@ -188,6 +188,7 @@ void ModrinthPackExportTask::parseApiResponse(QByteArray* response) qWarning() << "Failed to parse versions response" << e.what(); } pendingHashes.clear(); + buildZip(); } void ModrinthPackExportTask::buildZip() -- cgit From 3a7961834abbd28014de89799514510e74f365ab Mon Sep 17 00:00:00 2001 From: Kode Date: Sun, 9 Apr 2023 21:28:40 +0100 Subject: Remove `seek` Don't need it if the data is already in a byte array. Signed-off-by: Kode --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index fc16f912..ed50fd20 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -122,10 +122,6 @@ void ModrinthPackExportTask::collectHashes() if (!url.isEmpty() && BuildConfig.MODRINTH_MRPACK_HOSTS.contains(url.host())) { qDebug() << "Resolving" << relative << "from index"; - // we've already read it - // let's go back! - openFile.seek(openFile.size()); - QCryptographicHash hash2(QCryptographicHash::Algorithm::Sha1); hash2.addData(data); @@ -307,4 +303,4 @@ QByteArray ModrinthPackExportTask::generateIndex() obj["files"] = files; return QJsonDocument(obj).toJson(QJsonDocument::Compact); -} \ No newline at end of file +} -- cgit From 6d5c629b4316fb37b1ca0705c17867d6d9c771bd Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 10 Apr 2023 00:04:35 +0300 Subject: Added dependencies to the APIs Signed-off-by: Trial97 --- launcher/modplatform/ModIndex.h | 9 +++++++ launcher/modplatform/flame/FlameModIndex.cpp | 30 +++++++++++++++++++++- .../modplatform/modrinth/ModrinthPackIndex.cpp | 21 ++++++++++++++- 3 files changed, 58 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 40f1efc4..ffa3a3ab 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -32,6 +32,8 @@ enum class ResourceProvider { MODRINTH, FLAME }; enum class ResourceType { MOD, RESOURCE_PACK, SHADER_PACK }; +enum class DependencyType { REQUIRED, OPTIONAL, INCOMPATIBLE, EMBEDDED, TOOL, INCLUDE }; + class ProviderCapabilities { public: auto name(ResourceProvider) -> const char*; @@ -51,6 +53,12 @@ struct DonationData { QString url; }; +struct Dependency { + QVariant addonId; + DependencyType type; + QString version; +}; + struct IndexedVersion { QVariant addonId; QVariant fileId; @@ -65,6 +73,7 @@ struct IndexedVersion { QString hash; bool is_preferred = true; QString changelog; + QList dependencies; // For internal use, not provided by APIs bool is_currently_selected = false; diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 7498e830..a820e3a1 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -136,7 +136,35 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> } } - if(load_changelog) + auto dependencies = Json::ensureArray(obj, "dependencies"); + for (auto d : dependencies) { + auto dep = Json::ensureObject(d); + ModPlatform::Dependency dependency; + dependency.addonId = Json::requireInteger(dep, "modId"); + switch (Json::requireInteger(dep, "relationType")) { + case 1: // EmbeddedLibrary + dependency.type = ModPlatform::DependencyType::EMBEDDED; + break; + case 2: // OptionalDependency + dependency.type = ModPlatform::DependencyType::OPTIONAL; + break; + case 3: // RequiredDependency + dependency.type = ModPlatform::DependencyType::REQUIRED; + break; + case 4: // Tool + dependency.type = ModPlatform::DependencyType::TOOL; + break; + case 5: // Incompatible + dependency.type = ModPlatform::DependencyType::INCOMPATIBLE; + break; + case 6: // Include + dependency.type = ModPlatform::DependencyType::INCLUDE; + break; + } + file.dependencies.append(dependency); + } + + if (load_changelog) file.changelog = api.getModFileChangelog(file.addonId.toInt(), file.fileId.toInt()); return file; diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 7ade131e..8e97ee7c 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -22,7 +22,6 @@ #include "Json.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" -#include "net/NetJob.h" static ModrinthAPI api; static ModPlatform::ProviderCapabilities ProviderCaps; @@ -140,6 +139,26 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t file.version_number = Json::requireString(obj, "version_number"); file.changelog = Json::requireString(obj, "changelog"); + auto dependencies = Json::ensureArray(obj, "dependencies"); + for (auto d : dependencies) { + auto dep = Json::ensureObject(d); + ModPlatform::Dependency dependency; + dependency.addonId = Json::requireString(dep, "project_id"); + dependency.version = Json::requireString(dep, "version_id"); + auto depType = Json::requireString(dep, "dependency_type"); + + if (depType == "required") + dependency.type = ModPlatform::DependencyType::REQUIRED; + else if (depType == "optional") + dependency.type = ModPlatform::DependencyType::OPTIONAL; + else if (depType == "incompatible") + dependency.type = ModPlatform::DependencyType::INCOMPATIBLE; + else if (depType == "embedded") + dependency.type = ModPlatform::DependencyType::EMBEDDED; + + file.dependencies.append(dependency); + } + auto files = Json::requireArray(obj, "files"); int i = 0; -- cgit From d524935b6726c1a8d589d01abad4d262a55af149 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 11 Apr 2023 20:55:10 +0300 Subject: Added task to load local mod information Signed-off-by: Trial97 --- launcher/minecraft/mod/tasks/LocalModGetTask.cpp | 51 ++++++++++++++++++++++++ launcher/minecraft/mod/tasks/LocalModGetTask.h | 46 +++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 launcher/minecraft/mod/tasks/LocalModGetTask.cpp create mode 100644 launcher/minecraft/mod/tasks/LocalModGetTask.h (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/LocalModGetTask.cpp b/launcher/minecraft/mod/tasks/LocalModGetTask.cpp new file mode 100644 index 00000000..9c056d02 --- /dev/null +++ b/launcher/minecraft/mod/tasks/LocalModGetTask.cpp @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * 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 . + */ + +#include "LocalModGetTask.h" + +#include "FileSystem.h" +#include "minecraft/mod/MetadataHandler.h" + +#ifdef Q_OS_WIN32 +#include +#endif + +LocalModGetTask::LocalModGetTask(QDir index_dir, QVariant addonId) : m_index_dir(index_dir), m_addonId(addonId) +{ + // Ensure a '.index' folder exists in the mods folder, and create it if it does not + if (!FS::ensureFolderPathExists(index_dir.path())) { + emitFailed(QString("Unable to create index for modId %1!").arg(m_addonId.toString())); + } + +#ifdef Q_OS_WIN32 + SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); +#endif +} + +void LocalModGetTask::executeTask() +{ + setStatus(tr("Updating index for modId:\n%1").arg(m_addonId.toString())); + emit getMod(Metadata::get(m_index_dir, m_addonId)); +} + +auto LocalModGetTask::abort() -> bool +{ + emitAborted(); + return true; +} diff --git a/launcher/minecraft/mod/tasks/LocalModGetTask.h b/launcher/minecraft/mod/tasks/LocalModGetTask.h new file mode 100644 index 00000000..5b741122 --- /dev/null +++ b/launcher/minecraft/mod/tasks/LocalModGetTask.h @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * 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 . + */ + +#pragma once + +#include + +#include "minecraft/mod/MetadataHandler.h" +#include "tasks/Task.h" + +class LocalModGetTask : public Task { + Q_OBJECT + public: + using Ptr = shared_qobject_ptr; + + explicit LocalModGetTask(QDir index_dir, QVariant addonId); + + auto canAbort() const -> bool override { return true; } + auto abort() -> bool override; + + protected slots: + //! Entry point for tasks. + void executeTask() override; + + signals: + void getMod(Metadata::ModStruct); + + private: + QDir m_index_dir; + QVariant m_addonId; +}; -- cgit From 4fbd5abe41ac10ecd28974ff857e9bce35c7d264 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 12 Apr 2023 00:45:44 +0300 Subject: Added task to load dependencies Signed-off-by: Trial97 --- launcher/minecraft/mod/MetadataHandler.h | 57 ++++------ .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 116 +++++++++++++++++++++ .../minecraft/mod/tasks/GetModDependenciesTask.h | 63 +++++++++++ .../minecraft/mod/tasks/LocalModGetAllTask.cpp | 52 +++++++++ launcher/minecraft/mod/tasks/LocalModGetAllTask.h | 45 ++++++++ launcher/minecraft/mod/tasks/LocalModGetTask.cpp | 51 --------- launcher/minecraft/mod/tasks/LocalModGetTask.h | 46 -------- launcher/modplatform/packwiz/Packwiz.cpp | 11 ++ launcher/modplatform/packwiz/Packwiz.h | 57 +++++----- 9 files changed, 339 insertions(+), 159 deletions(-) create mode 100644 launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp create mode 100644 launcher/minecraft/mod/tasks/GetModDependenciesTask.h create mode 100644 launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp create mode 100644 launcher/minecraft/mod/tasks/LocalModGetAllTask.h delete mode 100644 launcher/minecraft/mod/tasks/LocalModGetTask.cpp delete mode 100644 launcher/minecraft/mod/tasks/LocalModGetTask.h (limited to 'launcher') diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h index 39723b49..f7f08a79 100644 --- a/launcher/minecraft/mod/MetadataHandler.h +++ b/launcher/minecraft/mod/MetadataHandler.h @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* 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 . -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * 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 . + */ #pragma once @@ -42,28 +42,15 @@ class Metadata { return Packwiz::V1::createModFormat(index_dir, internal_mod, mod_slug); } - static void update(QDir& index_dir, ModStruct& mod) - { - Packwiz::V1::updateModIndex(index_dir, mod); - } + static void update(QDir& index_dir, ModStruct& mod) { Packwiz::V1::updateModIndex(index_dir, mod); } - static void remove(QDir& index_dir, QString mod_slug) - { - Packwiz::V1::deleteModIndex(index_dir, mod_slug); - } + static void remove(QDir& index_dir, QString mod_slug) { Packwiz::V1::deleteModIndex(index_dir, mod_slug); } - static void remove(QDir& index_dir, QVariant& mod_id) - { - Packwiz::V1::deleteModIndex(index_dir, mod_id); - } + static void remove(QDir& index_dir, QVariant& mod_id) { Packwiz::V1::deleteModIndex(index_dir, mod_id); } - static auto get(QDir& index_dir, QString mod_slug) -> ModStruct - { - return Packwiz::V1::getIndexForMod(index_dir, mod_slug); - } + static auto get(QDir& index_dir, QString mod_slug) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_slug); } - static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct - { - return Packwiz::V1::getIndexForMod(index_dir, mod_id); - } + static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_id); } + + static auto getAll(QDir& index_dir) -> QList { return Packwiz::V1::getAllMods(index_dir); } }; diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp new file mode 100644 index 00000000..dcff1028 --- /dev/null +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * 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 . + */ + +#include "GetModDependenciesTask.h" + +#include "QObjectPtr.h" +#include "minecraft/mod/MetadataHandler.h" +#include "minecraft/mod/tasks/LocalModGetAllTask.h" +#include "modplatform/ModIndex.h" +#include "tasks/ConcurrentTask.h" +#include "tasks/SequentialTask.h" + +#ifdef Q_OS_WIN32 +#include +#endif + +GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList selected, NewDependecyVersionAPITask& api) + : m_selected(selected), m_getDependenciesVersionAPI(api) +{ + m_getAllMods = makeShared(index_dir); + m_getNetworkDep = makeShared(this, "GetDepInfo"); + QObject::connect(m_getAllMods.get(), &LocalModGetAllTask::getAllMod, [this](QList mods) { + m_mods = mods; + prepareDependecies(); + }); + +#ifdef Q_OS_WIN32 + SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); +#endif +} + +void GetModDependenciesTask::executeTask() +{ + setStatus(tr("Geting all mods")); + m_getAllMods->start(); +} + +auto GetModDependenciesTask::abort() -> bool +{ + emitAborted(); + return true; +} + +void GetModDependenciesTask::prepareDependecies() +{ + auto c_dependencies = getDependenciesForVersions(m_selected); + if (c_dependencies.length() == 0) { + emitSucceeded(); + return; + } + for (auto dep : c_dependencies) { + auto task = m_getDependenciesVersionAPI( + dep, 20, [this](QList new_versions, int level) { addDependecies(new_versions, level - 1); }); + m_getNetworkDep->addTask(task); + } + m_getNetworkDep->start(); +} + +void GetModDependenciesTask::addDependecies(QList new_versions, int level) +{ + // some mutex? + m_dependencies.append(new_versions); + auto c_dependencies = getDependenciesForVersions(m_selected); + if (c_dependencies.length() == 0) { + return; + } + if (level == 0) { + qWarning() << "Dependency cycle exeeded"; + } + for (auto dep : c_dependencies) { + auto task = m_getDependenciesVersionAPI( + dep, 20, [this](QList new_versions, int level) { addDependecies(new_versions, level - 1); }); + m_getNetworkDep->addTask(task); + } +}; + +QList GetModDependenciesTask::getDependenciesForVersions(QList selected) +{ + auto c_dependencies = QList(); + for (auto version : selected) { + for (auto ver_dep : version.dependencies) { + if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) { + if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), + [ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); + dep == c_dependencies.end()) { // check the current dependency list + c_dependencies.append(ver_dep); + } else if (auto dep = + std::find_if(selected.begin(), selected.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); + dep == selected.end()) { // check the selected versions + c_dependencies.append(ver_dep); + } else if (auto dep = + std::find_if(m_mods.begin(), m_mods.end(), [ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; }); + dep == m_mods.end()) { // check the existing mods + c_dependencies.append(ver_dep); + } + } + } + } + return c_dependencies; +}; diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h new file mode 100644 index 00000000..28112bba --- /dev/null +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * 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 . + */ + +#pragma once + +#include +#include + +#include "minecraft/mod/MetadataHandler.h" +#include "minecraft/mod/tasks/LocalModGetAllTask.h" +#include "modplatform/ModIndex.h" +#include "tasks/SequentialTask.h" +#include "tasks/Task.h" + +class GetModDependenciesTask : public Task { + Q_OBJECT + public: + using Ptr = shared_qobject_ptr; + using LocalModGetAllTaskPtr = shared_qobject_ptr; + + using NewDependecyVersionAPITask = + std::function, int)>)>; + + explicit GetModDependenciesTask(QDir index_dir, QList selected, NewDependecyVersionAPITask& api); + + auto canAbort() const -> bool override { return true; } + auto abort() -> bool override; + + protected slots: + //! Entry point for tasks. + void executeTask() override; + + void prepareDependecies(); + void addDependecies(QList, int); + QList getDependenciesForVersions(QList); + + signals: + void getAllMod(QList); + + private: + QList m_selected; + QList m_dependencies; + QList m_mods; + + LocalModGetAllTaskPtr m_getAllMods = nullptr; + NewDependecyVersionAPITask m_getDependenciesVersionAPI; + SequentialTask::Ptr m_getNetworkDep; +}; diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp b/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp new file mode 100644 index 00000000..9e4293ff --- /dev/null +++ b/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * 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 . + */ + +#include "LocalModGetAllTask.h" + +#include "FileSystem.h" +#include "minecraft/mod/MetadataHandler.h" + +#ifdef Q_OS_WIN32 +#include +#endif + +LocalModGetAllTask::LocalModGetAllTask(QDir index_dir) : m_index_dir(index_dir) +{ + // Ensure a '.index' folder exists in the mods folder, and create it if it does not + if (!FS::ensureFolderPathExists(index_dir.path())) { + emitFailed(QString("Unable to create index for all mods!")); + } + +#ifdef Q_OS_WIN32 + SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); +#endif +} + +void LocalModGetAllTask::executeTask() +{ + setStatus(tr("Geting all mods")); + emit getAllMod(Metadata::getAll(m_index_dir)); + emitSucceeded(); +} + +auto LocalModGetAllTask::abort() -> bool +{ + emitAborted(); + return true; +} diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.h b/launcher/minecraft/mod/tasks/LocalModGetAllTask.h new file mode 100644 index 00000000..09e453e4 --- /dev/null +++ b/launcher/minecraft/mod/tasks/LocalModGetAllTask.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * 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 . + */ + +#pragma once + +#include + +#include "minecraft/mod/MetadataHandler.h" +#include "tasks/Task.h" + +class LocalModGetAllTask : public Task { + Q_OBJECT + public: + using Ptr = shared_qobject_ptr; + + explicit LocalModGetAllTask(QDir index_dir); + + auto canAbort() const -> bool override { return true; } + auto abort() -> bool override; + + protected slots: + //! Entry point for tasks. + void executeTask() override; + + signals: + void getAllMod(QList); + + private: + QDir m_index_dir; +}; diff --git a/launcher/minecraft/mod/tasks/LocalModGetTask.cpp b/launcher/minecraft/mod/tasks/LocalModGetTask.cpp deleted file mode 100644 index 9c056d02..00000000 --- a/launcher/minecraft/mod/tasks/LocalModGetTask.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * PolyMC - Minecraft Launcher - * Copyright (c) 2022 flowln - * Copyright (C) 2022 Sefa Eyeoglu - * - * 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 . - */ - -#include "LocalModGetTask.h" - -#include "FileSystem.h" -#include "minecraft/mod/MetadataHandler.h" - -#ifdef Q_OS_WIN32 -#include -#endif - -LocalModGetTask::LocalModGetTask(QDir index_dir, QVariant addonId) : m_index_dir(index_dir), m_addonId(addonId) -{ - // Ensure a '.index' folder exists in the mods folder, and create it if it does not - if (!FS::ensureFolderPathExists(index_dir.path())) { - emitFailed(QString("Unable to create index for modId %1!").arg(m_addonId.toString())); - } - -#ifdef Q_OS_WIN32 - SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); -#endif -} - -void LocalModGetTask::executeTask() -{ - setStatus(tr("Updating index for modId:\n%1").arg(m_addonId.toString())); - emit getMod(Metadata::get(m_index_dir, m_addonId)); -} - -auto LocalModGetTask::abort() -> bool -{ - emitAborted(); - return true; -} diff --git a/launcher/minecraft/mod/tasks/LocalModGetTask.h b/launcher/minecraft/mod/tasks/LocalModGetTask.h deleted file mode 100644 index 5b741122..00000000 --- a/launcher/minecraft/mod/tasks/LocalModGetTask.h +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * PolyMC - Minecraft Launcher - * Copyright (c) 2022 flowln - * - * 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 . - */ - -#pragma once - -#include - -#include "minecraft/mod/MetadataHandler.h" -#include "tasks/Task.h" - -class LocalModGetTask : public Task { - Q_OBJECT - public: - using Ptr = shared_qobject_ptr; - - explicit LocalModGetTask(QDir index_dir, QVariant addonId); - - auto canAbort() const -> bool override { return true; } - auto abort() -> bool override; - - protected slots: - //! Entry point for tasks. - void executeTask() override; - - signals: - void getMod(Metadata::ModStruct); - - private: - QDir m_index_dir; - QVariant m_addonId; -}; diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 510c7309..a2598b97 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "FileSystem.h" #include "StringUtils.h" @@ -311,4 +313,13 @@ auto V1::getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod return {}; } +auto V1::getAllMods(QDir& index_dir) -> QList +{ + auto files = index_dir.entryList(QDir::Filter::Files); + auto mods = QList(); + std::transform(files.begin(), files.end(), std::back_inserter(mods), + [index_dir](auto file_name) { return getIndexForMod(index_dir, file_name); }); + return mods; +} + } // namespace Packwiz diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 4b096eec..2801f5d0 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* 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 . -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * 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 . + */ #pragma once @@ -36,22 +36,22 @@ auto getRealIndexName(QDir& index_dir, QString normalized_index_name, bool shoul class V1 { public: struct Mod { - QString slug {}; - QString name {}; - QString filename {}; + QString slug{}; + QString name{}; + QString filename{}; // FIXME: make side an enum - QString side {"both"}; + QString side{ "both" }; // [download] - QString mode {}; - QUrl url {}; - QString hash_format {}; - QString hash {}; + QString mode{}; + QUrl url{}; + QString hash_format{}; + QString hash{}; // [update] - ModPlatform::ResourceProvider provider {}; - QVariant file_id {}; - QVariant project_id {}; + ModPlatform::ResourceProvider provider{}; + QVariant file_id{}; + QVariant project_id{}; public: // This is a totally heuristic, but should work for now. @@ -93,6 +93,9 @@ class V1 { * If the mod doesn't have a metadata, it simply returns an empty Mod object. * */ static auto getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod; + + /* Gets the metadata for all the mods */ + static auto getAllMods(QDir& index_dir) -> QList; }; -} // namespace Packwiz +} // namespace Packwiz -- cgit From 11f8d25d94296aab13f885fde14ff26767082600 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 12 Apr 2023 00:49:50 +0300 Subject: Added missing character Signed-off-by: Trial97 --- launcher/modplatform/packwiz/Packwiz.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index a2598b97..33b5f364 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -318,7 +318,7 @@ auto V1::getAllMods(QDir& index_dir) -> QList auto files = index_dir.entryList(QDir::Filter::Files); auto mods = QList(); std::transform(files.begin(), files.end(), std::back_inserter(mods), - [index_dir](auto file_name) { return getIndexForMod(index_dir, file_name); }); + [&index_dir](auto file_name) { return getIndexForMod(index_dir, file_name); }); return mods; } -- cgit From b8e0c8ebc62ce22d5dcaf4295d80c6070eb45f49 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 17 Apr 2023 10:16:03 +0100 Subject: Boring changes Signed-off-by: TheKodeToad --- buildconfig/BuildConfig.h | 3 ++- launcher/FileIgnoreProxy.cpp | 2 +- launcher/FileIgnoreProxy.h | 2 +- launcher/modplatform/modrinth/ModrinthPackExportTask.h | 2 +- launcher/ui/MainWindow.h | 2 +- launcher/ui/dialogs/ExportMrPackDialog.cpp | 3 ++- 6 files changed, 8 insertions(+), 6 deletions(-) (limited to 'launcher') diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h index 38fa3a65..8543d724 100644 --- a/buildconfig/BuildConfig.h +++ b/buildconfig/BuildConfig.h @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp index fd05624a..4fd1ef91 100644 --- a/launcher/FileIgnoreProxy.cpp +++ b/launcher/FileIgnoreProxy.cpp @@ -258,4 +258,4 @@ bool FileIgnoreProxy::filterAcceptsColumn(int source_column, const QModelIndex& return false; return true; -} \ No newline at end of file +} diff --git a/launcher/FileIgnoreProxy.h b/launcher/FileIgnoreProxy.h index baf05c7a..a5a1153d 100644 --- a/launcher/FileIgnoreProxy.h +++ b/launcher/FileIgnoreProxy.h @@ -69,4 +69,4 @@ class FileIgnoreProxy : public QSortFilterProxyModel { private: const QString root; SeparatorPrefixTree<'/'> blocked; -}; \ No newline at end of file +}; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index 021d8a56..8b17f644 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -67,4 +67,4 @@ class ModrinthPackExportTask : public Task { void buildZip(); QByteArray generateIndex(); -}; \ No newline at end of file +}; diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 35b4792d..a0f912df 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2023 TheKodeToad * diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index a622eb30..bc983efe 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -99,4 +99,5 @@ void ExportMrPackDialog::done(int result) } QDialog::done(result); -} \ No newline at end of file +} + -- cgit From ba17efa3816f13a6c986f2b9223f71fa1d560aac Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 17 Apr 2023 13:18:25 +0100 Subject: Smol fixes Signed-off-by: TheKodeToad --- .../modrinth/ModrinthPackExportTask.cpp | 59 +++++++++++----------- .../modplatform/modrinth/ModrinthPackExportTask.h | 2 + 2 files changed, 32 insertions(+), 29 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index ed50fd20..6da9d3c1 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -28,6 +28,7 @@ #include "minecraft/mod/ModFolderModel.h" const QStringList ModrinthPackExportTask::PREFIXES({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); +const QStringList ModrinthPackExportTask::FILE_EXTENSIONS({ "jar", "litemod", "zip" }); ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, const QString& version, @@ -40,6 +41,7 @@ ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, , summary(summary) , instance(instance) , mcInstance(dynamic_cast(instance.get())) + , gameRoot(instance->gameRoot()) , output(output) , filter(filter) {} @@ -86,18 +88,19 @@ void ModrinthPackExportTask::collectFiles() void ModrinthPackExportTask::collectHashes() { - QDir mc(instance->gameRoot()); - for (QFileInfo file : files) { - QString relative = mc.relativeFilePath(file.absoluteFilePath()); + for (const QFileInfo& file : files) { + const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); // require sensible file types - if (!(relative.endsWith(".zip") || relative.endsWith(".jar") || relative.endsWith(".litemod"))) - continue; - if (!std::any_of(PREFIXES.begin(), PREFIXES.end(), [&relative](const QString& prefix) { return relative.startsWith(prefix + QDir::separator()); })) continue; + if (!std::any_of(FILE_EXTENSIONS.begin(), FILE_EXTENSIONS.end(), [&relative](const QString& extension) { + return relative.endsWith('.' + extension) || relative.endsWith('.' + extension + ".disabled"); + })) { + continue; + } - QCryptographicHash hash(QCryptographicHash::Algorithm::Sha512); + QCryptographicHash sha512(QCryptographicHash::Algorithm::Sha512); QFile openFile(file.absoluteFilePath()); if (!openFile.open(QFile::ReadOnly)) { @@ -105,27 +108,27 @@ void ModrinthPackExportTask::collectHashes() continue; } - QByteArray data = openFile.readAll(); + const QByteArray data = openFile.readAll(); if (openFile.error() != QFileDevice::NoError) { qWarning() << "Could not read" << file; continue; } - hash.addData(data); + sha512.addData(data); auto allMods = mcInstance->loaderModList()->allMods(); if (auto modIter = std::find_if(allMods.begin(), allMods.end(), [&file](Mod* mod) { return mod->fileinfo() == file; }); modIter != allMods.end()) { - Mod* mod = *modIter; + const Mod* mod = *modIter; if (mod->metadata() != nullptr) { QUrl& url = mod->metadata()->url; // most likely some of these may be from curseforge if (!url.isEmpty() && BuildConfig.MODRINTH_MRPACK_HOSTS.contains(url.host())) { qDebug() << "Resolving" << relative << "from index"; - QCryptographicHash hash2(QCryptographicHash::Algorithm::Sha1); - hash2.addData(data); + QCryptographicHash sha1(QCryptographicHash::Algorithm::Sha1); + sha1.addData(data); - ResolvedFile file{ hash2.result().toHex(), hash.result().toHex(), url.toString(), openFile.size() }; + ResolvedFile file{ sha1.result().toHex(), sha512.result().toHex(), url.toString(), openFile.size() }; resolvedFiles[relative] = file; // nice! we've managed to resolve based on local metadata! @@ -136,7 +139,7 @@ void ModrinthPackExportTask::collectHashes() } qDebug() << "Enqueueing" << relative << "for Modrinth query"; - pendingHashes[relative] = hash.result().toHex(); + pendingHashes[relative] = sha512.result().toHex(); } makeApiRequest(); @@ -166,11 +169,11 @@ void ModrinthPackExportTask::parseApiResponse(QByteArray* response) while (iterator.hasNext()) { iterator.next(); - QJsonObject obj = doc[iterator.value()].toObject(); + const QJsonObject obj = doc[iterator.value()].toObject(); if (obj.isEmpty()) continue; - QJsonArray files = obj["files"].toArray(); + const QJsonArray files = obj["files"].toArray(); if (auto fileIter = std::find_if(files.begin(), files.end(), [&iterator](const QJsonValue& file) { return file["hashes"]["sha512"] == iterator.value(); }); fileIter != files.end()) { @@ -180,7 +183,7 @@ void ModrinthPackExportTask::parseApiResponse(QByteArray* response) fileIter->toObject()["url"].toString(), fileIter->toObject()["size"].toInt() }; } } - } catch (Json::JsonException& e) { + } catch (const Json::JsonException& e) { qWarning() << "Failed to parse versions response" << e.what(); } pendingHashes.clear(); @@ -212,8 +215,7 @@ void ModrinthPackExportTask::buildZip() } indexFile.write(generateIndex()); - QDir mc(instance->gameRoot()); - size_t i = 0; + size_t progress = 0; for (const QFileInfo& file : files) { if (pendingAbort) { QFile::remove(output); @@ -221,15 +223,15 @@ void ModrinthPackExportTask::buildZip() return; } - setProgress(i, files.length()); - QString relative = mc.relativeFilePath(file.absoluteFilePath()); + setProgress(progress, files.length()); + const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) { QFile::remove(output); QMetaObject::invokeMethod( this, [this, relative]() { emitFailed(tr("Could not read and compress %1").arg(relative)); }, Qt::QueuedConnection); return; } - i++; + progress++; } zip.close(); @@ -255,14 +257,13 @@ QByteArray ModrinthPackExportTask::generateIndex() if (!summary.isEmpty()) obj["summary"] = summary; - MinecraftInstance* mc = dynamic_cast(instance.get()); - if (mc) { - auto profile = mc->getPackProfile(); + if (mcInstance) { + auto profile = mcInstance->getPackProfile(); // collect all supported components - ComponentPtr minecraft = profile->getComponent("net.minecraft"); - ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader"); - ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader"); - ComponentPtr forge = profile->getComponent("net.minecraftforge"); + const ComponentPtr minecraft = profile->getComponent("net.minecraft"); + const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader"); + const ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader"); + const ComponentPtr forge = profile->getComponent("net.minecraftforge"); // convert all available components to mrpack dependencies QJsonObject dependencies; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index 8b17f644..c00751f2 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -44,12 +44,14 @@ class ModrinthPackExportTask : public Task { }; static const QStringList PREFIXES; + static const QStringList FILE_EXTENSIONS; static const QStringList ALLOWED_HOSTS; // inputs const QString name, version, summary; const InstancePtr instance; const MinecraftInstance* mcInstance; + const QDir gameRoot; const QString output; const MMCZip::FilterFunction filter; -- cgit From 2e9403a324bf7a62fd61b4df78d6c9cc13f65d01 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 17 Apr 2023 13:19:59 +0100 Subject: This was moved Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.h | 1 - 1 file changed, 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index c00751f2..a0b006b9 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -45,7 +45,6 @@ class ModrinthPackExportTask : public Task { static const QStringList PREFIXES; static const QStringList FILE_EXTENSIONS; - static const QStringList ALLOWED_HOSTS; // inputs const QString name, version, summary; -- cgit From 12f0d51c0cd03d660425566264b502736b104310 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:51:34 -0700 Subject: Fix: signal/slot macro -> func pointer & network fixes - convert qt connect calls to use function pointers instead of the signal/slot macros wherever practical (UI classes were mostly left alone, target was tasks and processes) - give signals an explicit receivers to use the static method over the instance method wherever practical - ensure networks tasks are using the `errorOccured` signal added in Qt5.15 over the deprecated `error` signal - ensure all networks tasks have an sslErrors signal connected - add seemingly missing `MinecraftAccount::authSucceeded` connection for `MSAInteractive` login flow Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/JavaCommon.cpp | 6 ++--- launcher/LoggedProcess.cpp | 8 +++---- launcher/icons/IconList.cpp | 5 ++--- launcher/java/JavaChecker.cpp | 14 ++++++------ launcher/java/JavaCheckerJob.cpp | 2 +- launcher/launch/steps/Update.cpp | 6 ++--- launcher/minecraft/WorldList.cpp | 3 +-- launcher/minecraft/auth/AuthRequest.cpp | 22 +++++++++---------- launcher/minecraft/auth/MinecraftAccount.cpp | 16 +++++++------- launcher/minecraft/services/CapeChange.cpp | 33 +++++++++++++++++++++------- launcher/minecraft/services/CapeChange.h | 1 + launcher/minecraft/services/SkinDelete.cpp | 22 ++++++++++++++----- launcher/minecraft/services/SkinDelete.h | 1 + launcher/minecraft/services/SkinUpload.cpp | 22 ++++++++++++++----- launcher/minecraft/services/SkinUpload.h | 1 + launcher/net/Download.cpp | 6 ++--- launcher/net/Download.h | 2 +- launcher/net/HttpMetaCache.cpp | 2 +- launcher/net/NetAction.h | 11 ++++++++++ launcher/net/Upload.cpp | 10 ++++++--- launcher/net/Upload.h | 2 +- launcher/screenshots/ImgurAlbumCreation.cpp | 10 ++++++--- launcher/screenshots/ImgurUpload.cpp | 10 ++++++--- launcher/settings/SettingsObject.cpp | 9 ++++---- launcher/tools/JProfiler.cpp | 4 ++-- launcher/tools/JVisualVM.cpp | 4 ++-- launcher/ui/pages/instance/VersionPage.cpp | 2 +- 27 files changed, 148 insertions(+), 86 deletions(-) (limited to 'launcher') diff --git a/launcher/JavaCommon.cpp b/launcher/JavaCommon.cpp index 52cc868a..e29e2270 100644 --- a/launcher/JavaCommon.cpp +++ b/launcher/JavaCommon.cpp @@ -122,8 +122,7 @@ void JavaCommon::TestCheck::run() return; } checker.reset(new JavaChecker()); - connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this, - SLOT(checkFinished(JavaCheckResult))); + connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinished); checker->m_path = m_path; checker->performCheck(); } @@ -137,8 +136,7 @@ void JavaCommon::TestCheck::checkFinished(JavaCheckResult result) return; } checker.reset(new JavaChecker()); - connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this, - SLOT(checkFinishedWithArgs(JavaCheckResult))); + connect(checker.get(), &JavaChecker::checkFinished, this, &JavaCommon::TestCheck::checkFinishedWithArgs); checker->m_path = m_path; checker->m_args = m_args; checker->m_minMem = m_minMem; diff --git a/launcher/LoggedProcess.cpp b/launcher/LoggedProcess.cpp index c8d5c34e..763a9b5c 100644 --- a/launcher/LoggedProcess.cpp +++ b/launcher/LoggedProcess.cpp @@ -44,11 +44,11 @@ LoggedProcess::LoggedProcess(QObject *parent) : QProcess(parent) // QProcess has a strange interface... let's map a lot of those into a few. connect(this, &QProcess::readyReadStandardOutput, this, &LoggedProcess::on_stdOut); connect(this, &QProcess::readyReadStandardError, this, &LoggedProcess::on_stdErr); - connect(this, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(on_exit(int,QProcess::ExitStatus))); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - connect(this, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(on_error(QProcess::ProcessError))); + connect(this, QOverload::of(&QProcess::finished), this, &LoggedProcess::on_exit); +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) // &QProcess::errorOccurred added in 5.6 + connect(this, &QProcess::errorOccurred, this, &LoggedProcess::on_error); #else - connect(this, SIGNAL(error(QProcess::ProcessError)), this, SLOT(on_error(QProcess::ProcessError))); + connect(this, QOverload::of(&QProcess::error), this, &LoggedProcess::on_error); #endif connect(this, &QProcess::stateChanged, this, &LoggedProcess::on_stateChange); } diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp index 1dfc6432..13174f6e 100644 --- a/launcher/icons/IconList.cpp +++ b/launcher/icons/IconList.cpp @@ -66,9 +66,8 @@ IconList::IconList(const QStringList &builtinPaths, QString path, QObject *paren m_watcher.reset(new QFileSystemWatcher()); is_watching = false; - connect(m_watcher.get(), SIGNAL(directoryChanged(QString)), - SLOT(directoryChanged(QString))); - connect(m_watcher.get(), SIGNAL(fileChanged(QString)), SLOT(fileChanged(QString))); + connect(m_watcher.get(), &QFileSystemWatcher::directoryChanged, this, &IconList::directoryChanged); + connect(m_watcher.get(), &QFileSystemWatcher::fileChanged, this, &IconList::fileChanged); directoryChanged(path); diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp index 041583d1..922580ce 100644 --- a/launcher/java/JavaChecker.cpp +++ b/launcher/java/JavaChecker.cpp @@ -87,15 +87,15 @@ void JavaChecker::performCheck() process->setProcessEnvironment(CleanEnviroment()); qDebug() << "Running java checker: " + m_path + args.join(" ");; - connect(process.get(), SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finished(int, QProcess::ExitStatus))); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - connect(process.get(), SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(error(QProcess::ProcessError))); + connect(process.get(), QOverload::of(&QProcess::finished), this, &JavaChecker::finished); +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) // &QProcess::errorOccurred added in 5.6 + connect(process.get(), &QProcess::errorOccurred, this, &JavaChecker::error); #else - connect(process.get(), SIGNAL(error(QProcess::ProcessError)), this, SLOT(error(QProcess::ProcessError))); + connect(process.get(), &QProcess::error, this, &JavaChecker::error); #endif - connect(process.get(), SIGNAL(readyReadStandardOutput()), this, SLOT(stdoutReady())); - connect(process.get(), SIGNAL(readyReadStandardError()), this, SLOT(stderrReady())); - connect(&killTimer, SIGNAL(timeout()), SLOT(timeout())); + connect(process.get(), &QProcess::readyReadStandardOutput, this, &JavaChecker::stdoutReady); + connect(process.get(), &QProcess::readyReadStandardError, this, &JavaChecker::stderrReady); + connect(&killTimer, &QTimer::timeout, this, &JavaChecker::timeout); killTimer.setSingleShot(true); killTimer.start(15000); process->start(); diff --git a/launcher/java/JavaCheckerJob.cpp b/launcher/java/JavaCheckerJob.cpp index 67d70066..48274974 100644 --- a/launcher/java/JavaCheckerJob.cpp +++ b/launcher/java/JavaCheckerJob.cpp @@ -38,7 +38,7 @@ void JavaCheckerJob::executeTask() for (auto iter : javacheckers) { javaresults.append(JavaCheckResult()); - connect(iter.get(), SIGNAL(checkFinished(JavaCheckResult)), SLOT(partFinished(JavaCheckResult))); + connect(iter.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished); iter->performCheck(); } } diff --git a/launcher/launch/steps/Update.cpp b/launcher/launch/steps/Update.cpp index 28bd153d..b67316b0 100644 --- a/launcher/launch/steps/Update.cpp +++ b/launcher/launch/steps/Update.cpp @@ -26,9 +26,9 @@ void Update::executeTask() m_updateTask.reset(m_parent->instance()->createUpdateTask(m_mode)); if(m_updateTask) { - connect(m_updateTask.get(), SIGNAL(finished()), this, SLOT(updateFinished())); - connect(m_updateTask.get(), &Task::progress, this, &Task::setProgress); - connect(m_updateTask.get(), &Task::status, this, &Task::setStatus); + connect(m_updateTask.get(), &Task::finished, this, &Update::updateFinished); + connect(m_updateTask.get(), &Task::progress, this, &Update::setProgress); + connect(m_updateTask.get(), &Task::status, this, &Update::setStatus); emit progressReportingRequest(); return; } diff --git a/launcher/minecraft/WorldList.cpp b/launcher/minecraft/WorldList.cpp index ae29a972..de21c474 100644 --- a/launcher/minecraft/WorldList.cpp +++ b/launcher/minecraft/WorldList.cpp @@ -53,8 +53,7 @@ WorldList::WorldList(const QString &dir) m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware); m_watcher = new QFileSystemWatcher(this); is_watching = false; - connect(m_watcher, SIGNAL(directoryChanged(QString)), this, - SLOT(directoryChanged(QString))); + connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &WorldList::directoryChanged); } void WorldList::startWatching() diff --git a/launcher/minecraft/auth/AuthRequest.cpp b/launcher/minecraft/auth/AuthRequest.cpp index bb82e1e2..a21634b7 100644 --- a/launcher/minecraft/auth/AuthRequest.cpp +++ b/launcher/minecraft/auth/AuthRequest.cpp @@ -55,12 +55,12 @@ void AuthRequest::get(const QNetworkRequest &req, int timeout/* = 60*1000*/) { reply_ = APPLICATION->network()->get(request_); status_ = Requesting; timedReplies_.add(new Katabasis::Reply(reply_, timeout)); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError))); -#else - connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError))); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(reply_, &QNetworkReply::errorOccurred, this, &AuthRequest::onRequestError); +#else // &QNetworkReply::error SIGNAL depricated + connect(reply_, QOverload::of(&QNetworkReply::error), this, &AuthRequest::onRequestError); #endif - connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished())); + connect(reply_, &QNetworkReply::finished, this, &AuthRequest::onRequestFinished); connect(reply_, &QNetworkReply::sslErrors, this, &AuthRequest::onSslErrors); } @@ -70,14 +70,14 @@ void AuthRequest::post(const QNetworkRequest &req, const QByteArray &data, int t status_ = Requesting; reply_ = APPLICATION->network()->post(request_, data_); timedReplies_.add(new Katabasis::Reply(reply_, timeout)); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError))); -#else - connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError))); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(reply_, &QNetworkReply::errorOccurred, this, &AuthRequest::onRequestError); +#else // &QNetworkReply::error SIGNAL depricated + connect(reply_, QOverload::of(&QNetworkReply::error), this, &AuthRequest::onRequestError); #endif - connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished())); + connect(reply_, &QNetworkReply::finished, this, &AuthRequest::onRequestFinished); connect(reply_, &QNetworkReply::sslErrors, this, &AuthRequest::onSslErrors); - connect(reply_, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(onUploadProgress(qint64,qint64))); + connect(reply_, &QNetworkReply::uploadProgress, this, &AuthRequest::onUploadProgress); } void AuthRequest::onRequestFinished() { diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp index 48cf5d42..3b050ac0 100644 --- a/launcher/minecraft/auth/MinecraftAccount.cpp +++ b/launcher/minecraft/auth/MinecraftAccount.cpp @@ -133,8 +133,8 @@ shared_qobject_ptr MinecraftAccount::login(QString password) { Q_ASSERT(m_currentTask.get() == nullptr); m_currentTask.reset(new MojangLogin(&data, password)); - connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded())); - connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString))); + connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded); + connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed); connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); }); emit activityChanged(true); return m_currentTask; @@ -144,8 +144,8 @@ shared_qobject_ptr MinecraftAccount::loginMSA() { Q_ASSERT(m_currentTask.get() == nullptr); m_currentTask.reset(new MSAInteractive(&data)); - connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded())); - connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString))); + connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded); + connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed); connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); }); emit activityChanged(true); return m_currentTask; @@ -155,8 +155,8 @@ shared_qobject_ptr MinecraftAccount::loginOffline() { Q_ASSERT(m_currentTask.get() == nullptr); m_currentTask.reset(new OfflineLogin(&data)); - connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded())); - connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString))); + connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded); + connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed); connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); }); emit activityChanged(true); return m_currentTask; @@ -177,8 +177,8 @@ shared_qobject_ptr MinecraftAccount::refresh() { m_currentTask.reset(new MojangRefresh(&data)); } - connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded())); - connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString))); + connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded); + connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed); connect(m_currentTask.get(), &Task::aborted, this, [this]{ authFailed(tr("Aborted")); }); emit activityChanged(true); return m_currentTask; diff --git a/launcher/minecraft/services/CapeChange.cpp b/launcher/minecraft/services/CapeChange.cpp index c73a11b6..1d5ea36d 100644 --- a/launcher/minecraft/services/CapeChange.cpp +++ b/launcher/minecraft/services/CapeChange.cpp @@ -54,9 +54,14 @@ void CapeChange::setCape(QString& cape) { setStatus(tr("Equipping cape")); m_reply = shared_qobject_ptr(rep); - connect(rep, &QNetworkReply::uploadProgress, this, &Task::setProgress); - connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError))); - connect(rep, SIGNAL(finished()), this, SLOT(downloadFinished())); + connect(rep, &QNetworkReply::uploadProgress, this, &CapeChange::setProgress); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(rep, &QNetworkReply::errorOccurred, this, &CapeChange::downloadError); +#else + connect(rep, QOverload::of(&QNetworkReply::error), this, &CapeChange::downloadError); +#endif + connect(rep, &QNetworkReply::sslErrors, this, &CapeChange::sslErrors); + connect(rep, &QNetworkReply::finished, this, &CapeChange::downloadFinished); } void CapeChange::clearCape() { @@ -68,13 +73,14 @@ void CapeChange::clearCape() { setStatus(tr("Removing cape")); m_reply = shared_qobject_ptr(rep); - connect(rep, &QNetworkReply::uploadProgress, this, &Task::setProgress); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError))); + connect(rep, &QNetworkReply::uploadProgress, this, &CapeChange::setProgress); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(rep, &QNetworkReply::errorOccurred, this, &CapeChange::downloadError); #else - connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError))); + connect(rep, QOverload::of(&QNetworkReply::error), this, &CapeChange::downloadError); #endif - connect(rep, SIGNAL(finished()), this, SLOT(downloadFinished())); + connect(rep, &QNetworkReply::sslErrors, this, &CapeChange::sslErrors); + connect(rep, &QNetworkReply::finished, this, &CapeChange::downloadFinished); } @@ -95,6 +101,17 @@ void CapeChange::downloadError(QNetworkReply::NetworkError error) emitFailed(m_reply->errorString()); } +void CapeChange::sslErrors(const QList& errors) +{ + int i = 1; + for (auto error : errors) { + qCritical() << "Cape change SSL Error #" << i << " : " << error.errorString(); + auto cert = error.certificate(); + qCritical() << "Certificate in question:\n" << cert.toText(); + i++; + } +} + void CapeChange::downloadFinished() { // if the download failed diff --git a/launcher/minecraft/services/CapeChange.h b/launcher/minecraft/services/CapeChange.h index 185d69b6..38069f90 100644 --- a/launcher/minecraft/services/CapeChange.h +++ b/launcher/minecraft/services/CapeChange.h @@ -27,6 +27,7 @@ protected: public slots: void downloadError(QNetworkReply::NetworkError); + void sslErrors(const QList& errors); void downloadFinished(); }; diff --git a/launcher/minecraft/services/SkinDelete.cpp b/launcher/minecraft/services/SkinDelete.cpp index 921bd094..fbaaeacb 100644 --- a/launcher/minecraft/services/SkinDelete.cpp +++ b/launcher/minecraft/services/SkinDelete.cpp @@ -53,13 +53,14 @@ void SkinDelete::executeTask() m_reply = shared_qobject_ptr(rep); setStatus(tr("Deleting skin")); - connect(rep, &QNetworkReply::uploadProgress, this, &Task::setProgress); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError))); + connect(rep, &QNetworkReply::uploadProgress, this, &SkinDelete::setProgress); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(rep, &QNetworkReply::errorOccurred, this, &SkinDelete::downloadError); #else - connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError))); + connect(rep, QOverload::of(&QNetworkReply::error), this, &SkinDelete::downloadError); #endif - connect(rep, SIGNAL(finished()), this, SLOT(downloadFinished())); + connect(rep, &QNetworkReply::sslErrors, this, &SkinDelete::sslErrors); + connect(rep, &QNetworkReply::finished, this, &SkinDelete::downloadFinished); } void SkinDelete::downloadError(QNetworkReply::NetworkError error) @@ -69,6 +70,17 @@ void SkinDelete::downloadError(QNetworkReply::NetworkError error) emitFailed(m_reply->errorString()); } +void SkinDelete::sslErrors(const QList& errors) +{ + int i = 1; + for (auto error : errors) { + qCritical() << "Skin Delete SSL Error #" << i << " : " << error.errorString(); + auto cert = error.certificate(); + qCritical() << "Certificate in question:\n" << cert.toText(); + i++; + } +} + void SkinDelete::downloadFinished() { // if the download failed diff --git a/launcher/minecraft/services/SkinDelete.h b/launcher/minecraft/services/SkinDelete.h index 83a84685..b9a1c9d3 100644 --- a/launcher/minecraft/services/SkinDelete.h +++ b/launcher/minecraft/services/SkinDelete.h @@ -22,5 +22,6 @@ protected: public slots: void downloadError(QNetworkReply::NetworkError); + void sslErrors(const QList& errors); void downloadFinished(); }; diff --git a/launcher/minecraft/services/SkinUpload.cpp b/launcher/minecraft/services/SkinUpload.cpp index c7987875..711f8739 100644 --- a/launcher/minecraft/services/SkinUpload.cpp +++ b/launcher/minecraft/services/SkinUpload.cpp @@ -78,13 +78,14 @@ void SkinUpload::executeTask() m_reply = shared_qobject_ptr(rep); setStatus(tr("Uploading skin")); - connect(rep, &QNetworkReply::uploadProgress, this, &Task::setProgress); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError))); + connect(rep, &QNetworkReply::uploadProgress, this, &SkinUpload::setProgress); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(rep, &QNetworkReply::errorOccurred, this, &SkinUpload::downloadError); #else - connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError))); + connect(rep, QOverload::of(&QNetworkReply::error), this, &SkinUpload::downloadError); #endif - connect(rep, SIGNAL(finished()), this, SLOT(downloadFinished())); + connect(rep, &QNetworkReply::sslErrors, this, &SkinUpload::sslErrors); + connect(rep, &QNetworkReply::finished, this, &SkinUpload::downloadFinished); } void SkinUpload::downloadError(QNetworkReply::NetworkError error) @@ -94,6 +95,17 @@ void SkinUpload::downloadError(QNetworkReply::NetworkError error) emitFailed(m_reply->errorString()); } +void SkinUpload::sslErrors(const QList& errors) +{ + int i = 1; + for (auto error : errors) { + qCritical() << "Skin Upload SSL Error #" << i << " : " << error.errorString(); + auto cert = error.certificate(); + qCritical() << "Certificate in question:\n" << cert.toText(); + i++; + } +} + void SkinUpload::downloadFinished() { // if the download failed diff --git a/launcher/minecraft/services/SkinUpload.h b/launcher/minecraft/services/SkinUpload.h index 2c1f0a2e..ac8c5b36 100644 --- a/launcher/minecraft/services/SkinUpload.h +++ b/launcher/minecraft/services/SkinUpload.h @@ -32,6 +32,7 @@ protected: public slots: void downloadError(QNetworkReply::NetworkError); + void sslErrors(const QList& errors); void downloadFinished(); }; diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index e8a1d0b0..30c1953f 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -129,10 +129,10 @@ void Download::executeTask() m_reply.reset(rep); connect(rep, &QNetworkReply::downloadProgress, this, &Download::downloadProgress); connect(rep, &QNetworkReply::finished, this, &Download::downloadFinished); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError))); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(rep, &QNetworkReply::errorOccurred, this, &Download::downloadError); #else - connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError))); + connect(rep, QOverload::of(&QNetworkReply::error), this, &Download::downloadError); #endif connect(rep, &QNetworkReply::sslErrors, this, &Download::sslErrors); connect(rep, &QNetworkReply::readyRead, this, &Download::downloadReadyRead); diff --git a/launcher/net/Download.h b/launcher/net/Download.h index 7e1df322..01ec46db 100644 --- a/launcher/net/Download.h +++ b/launcher/net/Download.h @@ -70,7 +70,7 @@ class Download : public NetAction { protected slots: void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; void downloadError(QNetworkReply::NetworkError error) override; - void sslErrors(const QList& errors); + void sslErrors(const QList& errors) override; void downloadFinished() override; void downloadReadyRead() override; diff --git a/launcher/net/HttpMetaCache.cpp b/launcher/net/HttpMetaCache.cpp index 0d7ca769..0ec82251 100644 --- a/launcher/net/HttpMetaCache.cpp +++ b/launcher/net/HttpMetaCache.cpp @@ -55,7 +55,7 @@ HttpMetaCache::HttpMetaCache(QString path) : QObject(), m_index_file(path) saveBatchingTimer.setSingleShot(true); saveBatchingTimer.setTimerType(Qt::VeryCoarseTimer); - connect(&saveBatchingTimer, SIGNAL(timeout()), SLOT(SaveNow())); + connect(&saveBatchingTimer, &QTimer::timeout, this, &HttpMetaCache::SaveNow); } HttpMetaCache::~HttpMetaCache() diff --git a/launcher/net/NetAction.h b/launcher/net/NetAction.h index 38fe058b..1ff8f601 100644 --- a/launcher/net/NetAction.h +++ b/launcher/net/NetAction.h @@ -61,6 +61,17 @@ class NetAction : public Task { virtual void downloadFinished() = 0; virtual void downloadReadyRead() = 0; + virtual void sslErrors(const QList& errors) { + int i = 1; + for (auto error : errors) { + qCritical() << "Network SSL Error #" << i << " : " << error.errorString(); + auto cert = error.certificate(); + qCritical() << "Certificate in question:\n" << cert.toText(); + i++; + } + + }; + public slots: void startAction(shared_qobject_ptr network) { diff --git a/launcher/net/Upload.cpp b/launcher/net/Upload.cpp index ccf43c2d..f3cdb786 100644 --- a/launcher/net/Upload.cpp +++ b/launcher/net/Upload.cpp @@ -232,9 +232,13 @@ namespace Net { QNetworkReply* rep = m_network->post(request, m_post_data); m_reply.reset(rep); - connect(rep, SIGNAL(downloadProgress(qint64, qint64)), SLOT(downloadProgress(qint64, qint64))); - connect(rep, SIGNAL(finished()), SLOT(downloadFinished())); - connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError))); + connect(rep, &QNetworkReply::downloadProgress, this, &Upload::downloadProgress); + connect(rep, &QNetworkReply::finished, this, &Upload::downloadFinished); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(rep, &QNetworkReply::errorOccurred, this, &Upload::downloadError); +#else + connect(rep, QOverload::of(&QNetworkReply::error), this, &Upload::downloadError); +#endif connect(rep, &QNetworkReply::sslErrors, this, &Upload::sslErrors); connect(rep, &QNetworkReply::readyRead, this, &Upload::downloadReadyRead); } diff --git a/launcher/net/Upload.h b/launcher/net/Upload.h index 5a0b2e74..f58b746a 100644 --- a/launcher/net/Upload.h +++ b/launcher/net/Upload.h @@ -54,7 +54,7 @@ namespace Net { protected slots: void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; void downloadError(QNetworkReply::NetworkError error) override; - void sslErrors(const QList & errors); + void sslErrors(const QList & errors) override; void downloadFinished() override; void downloadReadyRead() override; diff --git a/launcher/screenshots/ImgurAlbumCreation.cpp b/launcher/screenshots/ImgurAlbumCreation.cpp index a72c32d3..ab425f1a 100644 --- a/launcher/screenshots/ImgurAlbumCreation.cpp +++ b/launcher/screenshots/ImgurAlbumCreation.cpp @@ -74,17 +74,20 @@ void ImgurAlbumCreation::executeTask() m_reply.reset(rep); connect(rep, &QNetworkReply::uploadProgress, this, &ImgurAlbumCreation::downloadProgress); connect(rep, &QNetworkReply::finished, this, &ImgurAlbumCreation::downloadFinished); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError))); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(rep, &QNetworkReply::errorOccurred, this, &ImgurAlbumCreation::downloadError); #else - connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError))); + connect(rep, QOverload::of(&QNetworkReply::error), this, &ImgurAlbumCreation::downloadError); #endif + connect(rep, &QNetworkReply::sslErrors, this, &ImgurAlbumCreation::sslErrors); } + void ImgurAlbumCreation::downloadError(QNetworkReply::NetworkError error) { qDebug() << m_reply->errorString(); m_state = State::Failed; } + void ImgurAlbumCreation::downloadFinished() { if (m_state != State::Failed) @@ -120,6 +123,7 @@ void ImgurAlbumCreation::downloadFinished() return; } } + void ImgurAlbumCreation::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { setProgress(bytesReceived, bytesTotal); diff --git a/launcher/screenshots/ImgurUpload.cpp b/launcher/screenshots/ImgurUpload.cpp index f8ac9bc2..a50f9afa 100644 --- a/launcher/screenshots/ImgurUpload.cpp +++ b/launcher/screenshots/ImgurUpload.cpp @@ -89,12 +89,14 @@ void ImgurUpload::executeTask() m_reply.reset(rep); connect(rep, &QNetworkReply::uploadProgress, this, &ImgurUpload::downloadProgress); connect(rep, &QNetworkReply::finished, this, &ImgurUpload::downloadFinished); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError))); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(rep, &QNetworkReply::errorOccurred, this, &ImgurUpload::downloadError); #else - connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError))); + connect(rep, QOverload::of(&QNetworkReply::error), this, &ImgurUpload::downloadError); #endif + connect(rep, &QNetworkReply::sslErrors, this, &ImgurUpload::sslErrors); } + void ImgurUpload::downloadError(QNetworkReply::NetworkError error) { qCritical() << "ImgurUpload failed with error" << m_reply->errorString() << "Server reply:\n" << m_reply->readAll(); @@ -108,6 +110,7 @@ void ImgurUpload::downloadError(QNetworkReply::NetworkError error) m_reply.reset(); emitFailed(); } + void ImgurUpload::downloadFinished() { if(finished) @@ -144,6 +147,7 @@ void ImgurUpload::downloadFinished() emit succeeded(); return; } + void ImgurUpload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { setProgress(bytesReceived, bytesTotal); diff --git a/launcher/settings/SettingsObject.cpp b/launcher/settings/SettingsObject.cpp index 8a0bc045..634acd34 100644 --- a/launcher/settings/SettingsObject.cpp +++ b/launcher/settings/SettingsObject.cpp @@ -132,11 +132,10 @@ bool SettingsObject::reload() void SettingsObject::connectSignals(const Setting &setting) { - connect(&setting, SIGNAL(SettingChanged(const Setting &, QVariant)), - SLOT(changeSetting(const Setting &, QVariant))); - connect(&setting, SIGNAL(SettingChanged(const Setting &, QVariant)), + connect(&setting, &Setting::SettingChanged, this, &SettingsObject::changeSetting); + connect(&setting, SIGNAL(SettingChanged(const Setting &, QVariant)), this, SIGNAL(SettingChanged(const Setting &, QVariant))); - connect(&setting, SIGNAL(settingReset(Setting)), SLOT(resetSetting(const Setting &))); - connect(&setting, SIGNAL(settingReset(Setting)), SIGNAL(settingReset(const Setting &))); + connect(&setting, &Setting::settingReset, this, &SettingsObject::resetSetting); + connect(&setting, SIGNAL(settingReset(Setting)), this, SIGNAL(settingReset(const Setting &))); } diff --git a/launcher/tools/JProfiler.cpp b/launcher/tools/JProfiler.cpp index 1dc0d109..15c0cab6 100644 --- a/launcher/tools/JProfiler.cpp +++ b/launcher/tools/JProfiler.cpp @@ -68,8 +68,8 @@ void JProfiler::beginProfilingImpl(shared_qobject_ptr process) profiler->setArguments(profilerArgs); profiler->setProgram(profilerProgram); - connect(profiler, SIGNAL(started()), SLOT(profilerStarted())); - connect(profiler, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(profilerFinished(int,QProcess::ExitStatus))); + connect(profiler, &QProcess::started, this, &JProfiler::profilerStarted); + connect(profiler, QOverload::of(&QProcess::finished), this, &JProfiler::profilerFinished); m_profilerProcess = profiler; profiler->start(); diff --git a/launcher/tools/JVisualVM.cpp b/launcher/tools/JVisualVM.cpp index b1acc3c0..28ffb9cd 100644 --- a/launcher/tools/JVisualVM.cpp +++ b/launcher/tools/JVisualVM.cpp @@ -57,8 +57,8 @@ void JVisualVM::beginProfilingImpl(shared_qobject_ptr process) profiler->setArguments(profilerArgs); profiler->setProgram(programPath); - connect(profiler, SIGNAL(started()), SLOT(profilerStarted())); - connect(profiler, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(profilerFinished(int,QProcess::ExitStatus))); + connect(profiler, &QProcess::started, this, &JVisualVM::profilerStarted); + connect(profiler, QOverload::of(&QProcess::finished), this, &JVisualVM::profilerFinished); profiler->start(); m_profilerProcess = profiler; diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 7fff3b93..fffb96f2 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -501,7 +501,7 @@ void VersionPage::on_actionDownload_All_triggered() return; } ProgressDialog tDialog(this); - connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString))); + connect(updateTask.get(), &Task::failed, this, &VersionPage::onGameUpdateError); // FIXME: unused return value tDialog.execWithTask(updateTask.get()); updateButtons(); -- cgit From 709736d3f9a77206b5b6f809e5e45495f1db1315 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 17 Apr 2023 13:52:51 +0100 Subject: Make response const I don't think the segfault fix was ideal :P Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 6 ++---- launcher/modplatform/modrinth/ModrinthPackExportTask.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 6da9d3c1..54932131 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -56,9 +56,7 @@ void ModrinthPackExportTask::executeTask() bool ModrinthPackExportTask::abort() { if (task != nullptr) { - if (!task->abort()) - return false; - + task->abort(); task = nullptr; emitAborted(); return true; @@ -158,7 +156,7 @@ void ModrinthPackExportTask::makeApiRequest() } } -void ModrinthPackExportTask::parseApiResponse(QByteArray* response) +void ModrinthPackExportTask::parseApiResponse(const QByteArray* response) { task = nullptr; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index a0b006b9..25045cf2 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -64,7 +64,7 @@ class ModrinthPackExportTask : public Task { void collectFiles(); void collectHashes(); void makeApiRequest(); - void parseApiResponse(QByteArray* response); + void parseApiResponse(const QByteArray* response); void buildZip(); QByteArray generateIndex(); -- cgit From 5655a3351551aa36aeeba79b0ac7f2474ca74352 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Apr 2023 18:59:31 +0300 Subject: Added Dependency API Signed-off-by: Trial97 --- launcher/modplatform/ResourceAPI.h | 24 +++++++++++ launcher/modplatform/flame/FlameAPI.h | 15 +++++-- .../modplatform/helpers/NetworkResourceAPI.cpp | 49 ++++++++++++++++------ launcher/modplatform/helpers/NetworkResourceAPI.h | 2 + launcher/modplatform/modrinth/ModrinthAPI.h | 35 ++++++++-------- 5 files changed, 93 insertions(+), 32 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index 34f33779..a8e144dc 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -111,6 +111,24 @@ class ResourceAPI { std::function on_succeed; }; + struct DependencySearchArgs { + ModPlatform::Dependency dependency; + Version mcVersion; + ModLoaderTypes loader; + + DependencySearchArgs(DependencySearchArgs const&) = default; + void operator=(DependencySearchArgs other) + { + dependency = other.dependency; + mcVersion = other.mcVersion; + loader = other.loader; + } + }; + + struct DependencySearchCallbacks { + std::function on_succeed; + }; + public: /** Gets a list of available sorting methods for this API. */ [[nodiscard]] virtual auto getSortingMethods() const -> QList = 0; @@ -143,6 +161,12 @@ class ResourceAPI { return nullptr; } + [[nodiscard]] virtual Task::Ptr getDependencyVersion(DependencySearchArgs&&, DependencySearchCallbacks&&) const + { + qWarning() << "TODO"; + return nullptr; + } + static auto getModLoaderString(ModLoaderType type) -> const QString { switch (type) { diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 5811d717..91993e64 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -41,14 +41,15 @@ class FlameAPI : public NetworkResourceAPI { return 4; // TODO: remove this once Quilt drops official Fabric support if (loaders & Quilt) // NOTE: Most if not all Fabric mods should work *currently* - return 4; // Quilt would probably be 5 + return 4; // Quilt would probably be 5 return 0; } private: [[nodiscard]] std::optional getSearchURL(SearchArgs const& args) const override { - auto gameVersionStr = args.versions.has_value() ? QString("gameVersion=%1").arg(args.versions.value().front().toString()) : QString(); + auto gameVersionStr = + args.versions.has_value() ? QString("gameVersion=%1").arg(args.versions.value().front().toString()) : QString(); QStringList get_arguments; get_arguments.append(QString("classId=%1").arg(getClassId(args.type))); @@ -73,7 +74,7 @@ class FlameAPI : public NetworkResourceAPI { [[nodiscard]] std::optional getVersionsURL(VersionSearchArgs const& args) const override { - QString url{QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(args.pack.addonId.toString())}; + QString url{ QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(args.pack.addonId.toString()) }; QStringList get_parameters; if (args.mcVersions.has_value()) @@ -83,4 +84,12 @@ class FlameAPI : public NetworkResourceAPI { return url + get_parameters.join('&'); }; + + [[nodiscard]] std::optional getDependecyURL(DependencySearchArgs const& args) const override + { + return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2&modLoaderType=%") + .arg(args.dependency.addonId.toString()) + .arg(args.mcVersion.toString()) + .arg(getMappedModLoader(args.loader)); + }; }; diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp index 010ac15e..a7f763d3 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp +++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp @@ -24,7 +24,7 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks& netJob->addNetAction(Net::Download::makeByteArray(QUrl(search_url), response)); - QObject::connect(netJob.get(), &NetJob::succeeded, [=]{ + QObject::connect(netJob.get(), &NetJob::succeeded, [=] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -40,16 +40,14 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks& callbacks.on_succeed(doc); }); - QObject::connect(netJob.get(), &NetJob::failed, [=](QString reason){ + QObject::connect(netJob.get(), &NetJob::failed, [=](QString reason) { int network_error_code = -1; if (auto* failed_action = netJob->getFailedActions().at(0); failed_action && failed_action->m_reply) network_error_code = failed_action->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - callbacks.on_fail(reason, network_error_code); - }); - QObject::connect(netJob.get(), &NetJob::aborted, [=]{ - callbacks.on_abort(); + callbacks.on_fail(reason, network_error_code); }); + QObject::connect(netJob.get(), &NetJob::aborted, [=] { callbacks.on_abort(); }); return netJob; } @@ -101,9 +99,7 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi callbacks.on_succeed(doc, args.pack); }); - QObject::connect(netJob.get(), &NetJob::finished, [response] { - delete response; - }); + QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); return netJob; } @@ -120,9 +116,38 @@ Task::Ptr NetworkResourceAPI::getProject(QString addonId, QByteArray* response) netJob->addNetAction(Net::Download::makeByteArray(QUrl(project_url), response)); - QObject::connect(netJob.get(), &NetJob::finished, [response] { - delete response; - }); + QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); return netJob; } + +Task::Ptr NetworkResourceAPI::getDependencyVersion(DependencySearchArgs&& args, DependencySearchCallbacks&& callbacks) const +{ + auto versions_url_optional = getDependecyURL(args); + if (!versions_url_optional.has_value()) + return nullptr; + + auto versions_url = versions_url_optional.value(); + + auto netJob = makeShared(QString("%1::Dependecy").arg(args.dependency.addonId.toString()), APPLICATION->network()); + auto response = new QByteArray(); + + netJob->addNetAction(Net::Download::makeByteArray(versions_url, response)); + + QObject::connect(netJob.get(), &NetJob::succeeded, [=] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response for getting versions at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response; + return; + } + + callbacks.on_succeed(doc, args.dependency); + }); + + QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); + + return netJob; +}; diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.h b/launcher/modplatform/helpers/NetworkResourceAPI.h index 94813bec..bbe0a2c7 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.h +++ b/launcher/modplatform/helpers/NetworkResourceAPI.h @@ -14,9 +14,11 @@ class NetworkResourceAPI : public ResourceAPI { Task::Ptr getProjectInfo(ProjectInfoArgs&&, ProjectInfoCallbacks&&) const override; Task::Ptr getProjectVersions(VersionSearchArgs&&, VersionSearchCallbacks&&) const override; + Task::Ptr getDependencyVersion(DependencySearchArgs&&, DependencySearchCallbacks&&) const override; protected: [[nodiscard]] virtual auto getSearchURL(SearchArgs const& args) const -> std::optional = 0; [[nodiscard]] virtual auto getInfoURL(QString const& id) const -> std::optional = 0; [[nodiscard]] virtual auto getVersionsURL(VersionSearchArgs const& args) const -> std::optional = 0; + [[nodiscard]] virtual auto getDependecyURL(DependencySearchArgs const& args) const -> std::optional = 0; }; diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index b91ac5c1..2d6049ba 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -12,13 +12,9 @@ class ModrinthAPI : public NetworkResourceAPI { public: - auto currentVersion(QString hash, - QString hash_format, - QByteArray* response) -> Task::Ptr; + auto currentVersion(QString hash, QString hash_format, QByteArray* response) -> Task::Ptr; - auto currentVersions(const QStringList& hashes, - QString hash_format, - QByteArray* response) -> Task::Ptr; + auto currentVersions(const QStringList& hashes, QString hash_format, QByteArray* response) -> Task::Ptr; auto latestVersion(QString hash, QString hash_format, @@ -28,8 +24,8 @@ class ModrinthAPI : public NetworkResourceAPI { auto latestVersions(const QStringList& hashes, QString hash_format, - std::optional> mcVersions, - std::optional loaders, + std::optional> mcVersions, + std::optional loaders, QByteArray* response) -> Task::Ptr; Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const override; @@ -42,7 +38,7 @@ class ModrinthAPI : public NetworkResourceAPI { static auto getModLoaderStrings(const ModLoaderTypes types) -> const QStringList { QStringList l; - for (auto loader : {Forge, Fabric, Quilt}) { + for (auto loader : { Forge, Fabric, Quilt }) { if (types & loader) { l << getModLoaderString(loader); } @@ -55,8 +51,7 @@ class ModrinthAPI : public NetworkResourceAPI { static auto getModLoaderFilters(ModLoaderTypes types) -> const QString { QStringList l; - for (auto loader : getModLoaderStrings(types)) - { + for (auto loader : getModLoaderStrings(types)) { l << QString("\"categories:%1\"").arg(loader); } return l.join(','); @@ -139,16 +134,22 @@ class ModrinthAPI : public NetworkResourceAPI { auto getGameVersionsArray(std::list mcVersions) const -> QString { QString s; - for(auto& ver : mcVersions){ + for (auto& ver : mcVersions) { s += QString("\"versions:%1\",").arg(ver.toString()); } - s.remove(s.length() - 1, 1); //remove last comma + s.remove(s.length() - 1, 1); // remove last comma return s.isEmpty() ? QString() : s; } - inline auto validateModLoaders(ModLoaderTypes loaders) const -> bool - { - return loaders & (Forge | Fabric | Quilt); - } + inline auto validateModLoaders(ModLoaderTypes loaders) const -> bool { return loaders & (Forge | Fabric | Quilt); } + [[nodiscard]] std::optional getDependecyURL(DependencySearchArgs const& args) const override + { + return args.dependency.version.length() != 0 ? QString("%1/version/%2").arg(BuildConfig.MODRINTH_PROD_URL, args.dependency.version) + : QString("%1/project/%2/version?game_versions=[\"%1\"]&loaders=[\"%1\"]") + .arg(BuildConfig.MODRINTH_PROD_URL) + .arg(args.dependency.addonId.toString()) + .arg(args.mcVersion.toString()) + .arg(getModLoaderStrings(args.loader).join("\",\"")); + }; }; -- cgit From 4fe497cd682258ca80501be2ad616de7a40043d9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Apr 2023 23:02:33 +0300 Subject: First working version with curseforge mods Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 4 ++ launcher/ResourceDownloadTask.h | 51 ++++++++++---------- .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 54 +++++++++++++++------- .../minecraft/mod/tasks/GetModDependenciesTask.h | 16 ++++--- launcher/modplatform/flame/FlameModIndex.cpp | 48 +++++++++++++------ launcher/modplatform/flame/FlameModIndex.h | 6 +-- launcher/modplatform/flame/FlamePackIndex.h | 10 ++-- .../modplatform/modrinth/ModrinthPackIndex.cpp | 19 ++++++++ launcher/modplatform/modrinth/ModrinthPackIndex.h | 3 +- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 40 ++++++++++++---- launcher/ui/pages/modplatform/ModModel.cpp | 16 ++++++- launcher/ui/pages/modplatform/ModModel.h | 2 + launcher/ui/pages/modplatform/ResourceModel.cpp | 39 ++++++++++++++++ launcher/ui/pages/modplatform/ResourceModel.h | 8 ++++ launcher/ui/pages/modplatform/ResourcePackModel.h | 1 + launcher/ui/pages/modplatform/ResourcePage.cpp | 5 ++ launcher/ui/pages/modplatform/ResourcePage.h | 5 +- launcher/ui/pages/modplatform/ShaderPackModel.h | 1 + .../modplatform/flame/FlameResourceModels.cpp | 17 ++++++- .../pages/modplatform/flame/FlameResourceModels.h | 3 ++ .../modrinth/ModrinthResourceModels.cpp | 26 +++++++++-- .../modplatform/modrinth/ModrinthResourceModels.h | 4 ++ 22 files changed, 293 insertions(+), 85 deletions(-) (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 074570e3..fca8c914 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -359,6 +359,10 @@ set(MINECRAFT_SOURCES minecraft/mod/tasks/LocalWorldSaveParseTask.cpp minecraft/mod/tasks/LocalResourceParse.h minecraft/mod/tasks/LocalResourceParse.cpp + minecraft/mod/tasks/GetModDependenciesTask.h + minecraft/mod/tasks/GetModDependenciesTask.cpp + minecraft/mod/tasks/LocalModGetAllTask.h + minecraft/mod/tasks/LocalModGetAllTask.cpp # Assets minecraft/AssetsUtils.h diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h index 73ad2d07..f2118524 100644 --- a/launcher/ResourceDownloadTask.h +++ b/launcher/ResourceDownloadTask.h @@ -1,41 +1,45 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* Prism Launcher - Minecraft Launcher -* Copyright (c) 2022-2023 flowln -* Copyright (C) 2022 Sefa Eyeoglu -* -* 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 . -*/ + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022-2023 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * 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 . + */ #pragma once #include "net/NetJob.h" #include "tasks/SequentialTask.h" -#include "modplatform/ModIndex.h" #include "minecraft/mod/tasks/LocalModUpdateTask.h" +#include "modplatform/ModIndex.h" class ResourceFolderModel; class ResourceDownloadTask : public SequentialTask { Q_OBJECT -public: - explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, ModPlatform::IndexedVersion version, const std::shared_ptr packs, bool is_indexed = true); + public: + explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, + ModPlatform::IndexedVersion version, + const std::shared_ptr packs, + bool is_indexed = true); const QString& getFilename() const { return m_pack_version.fileName; } const QString& getCustomPath() const { return m_pack_version.custom_target_folder; } const QVariant& getVersionID() const { return m_pack_version.fileId; } + const ModPlatform::IndexedVersion& getVersion() const { return m_pack_version; } -private: + private: ModPlatform::IndexedPack m_pack; ModPlatform::IndexedVersion m_pack_version; const std::shared_ptr m_pack_model; @@ -47,11 +51,8 @@ private: void downloadFailed(QString reason); void downloadSucceeded(); - std::tuple to_delete {"", ""}; + std::tuple to_delete{ "", "" }; -private slots: + private slots: void hasOldResource(QString name, QString filename); }; - - - diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index dcff1028..9cc227f2 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -30,11 +30,12 @@ #include #endif -GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList selected, NewDependecyVersionAPITask& api) +GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList selected, NewDependecyVersionAPITask api) : m_selected(selected), m_getDependenciesVersionAPI(api) { m_getAllMods = makeShared(index_dir); m_getNetworkDep = makeShared(this, "GetDepInfo"); + connect(m_getNetworkDep.get(), &Task::finished, &loop, &QEventLoop::quit); QObject::connect(m_getAllMods.get(), &LocalModGetAllTask::getAllMod, [this](QList mods) { m_mods = mods; prepareDependecies(); @@ -49,6 +50,8 @@ void GetModDependenciesTask::executeTask() { setStatus(tr("Geting all mods")); m_getAllMods->start(); + loop.exec(); + emitSucceeded(); } auto GetModDependenciesTask::abort() -> bool @@ -61,22 +64,21 @@ void GetModDependenciesTask::prepareDependecies() { auto c_dependencies = getDependenciesForVersions(m_selected); if (c_dependencies.length() == 0) { - emitSucceeded(); + m_getNetworkDep->start(); return; } for (auto dep : c_dependencies) { - auto task = m_getDependenciesVersionAPI( - dep, 20, [this](QList new_versions, int level) { addDependecies(new_versions, level - 1); }); + auto task = m_getDependenciesVersionAPI(dep, [this](ModPlatform::IndexedVersion new_version) { addDependecies(new_version, 20); }); m_getNetworkDep->addTask(task); } m_getNetworkDep->start(); } -void GetModDependenciesTask::addDependecies(QList new_versions, int level) +void GetModDependenciesTask::addDependecies(ModPlatform::IndexedVersion new_version, int level) { // some mutex? - m_dependencies.append(new_versions); - auto c_dependencies = getDependenciesForVersions(m_selected); + m_dependencies.append(new_version); + auto c_dependencies = getDependenciesForVersion(new_version); if (c_dependencies.length() == 0) { return; } @@ -85,7 +87,7 @@ void GetModDependenciesTask::addDependecies(QList n } for (auto dep : c_dependencies) { auto task = m_getDependenciesVersionAPI( - dep, 20, [this](QList new_versions, int level) { addDependecies(new_versions, level - 1); }); + dep, [this, level](ModPlatform::IndexedVersion new_versions) { addDependecies(new_versions, level - 1); }); m_getNetworkDep->addTask(task); } }; @@ -99,18 +101,36 @@ QList GetModDependenciesTask::getDependenciesForVersion if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); dep == c_dependencies.end()) { // check the current dependency list - c_dependencies.append(ver_dep); - } else if (auto dep = - std::find_if(selected.begin(), selected.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); - dep == selected.end()) { // check the selected versions - c_dependencies.append(ver_dep); - } else if (auto dep = - std::find_if(m_mods.begin(), m_mods.end(), [ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; }); - dep == m_mods.end()) { // check the existing mods - c_dependencies.append(ver_dep); + if (auto dep = + std::find_if(selected.begin(), selected.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); + dep == selected.end()) { // check the selected versions + if (auto dep = + std::find_if(m_mods.begin(), m_mods.end(), [ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; }); + dep == m_mods.end()) { // check the existing mods + c_dependencies.append(ver_dep); + } + } } } } } return c_dependencies; }; + +QList GetModDependenciesTask::getDependenciesForVersion(ModPlatform::IndexedVersion version) +{ + auto c_dependencies = QList(); + for (auto ver_dep : version.dependencies) { + if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) { + if (auto dep = + std::find_if(c_dependencies.begin(), c_dependencies.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); + dep == c_dependencies.end()) { // check the current dependency list + if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), [ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; }); + dep == m_mods.end()) { // check the existing mods + c_dependencies.append(ver_dep); + } + } + } + } + return c_dependencies; +}; \ No newline at end of file diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index 28112bba..4353c1e1 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -18,6 +18,8 @@ #pragma once +#include +#include #include #include @@ -33,24 +35,23 @@ class GetModDependenciesTask : public Task { using Ptr = shared_qobject_ptr; using LocalModGetAllTaskPtr = shared_qobject_ptr; - using NewDependecyVersionAPITask = - std::function, int)>)>; + using NewDependecyVersionAPITask = std::function)>; - explicit GetModDependenciesTask(QDir index_dir, QList selected, NewDependecyVersionAPITask& api); + explicit GetModDependenciesTask(QDir index_dir, QList selected, NewDependecyVersionAPITask api); auto canAbort() const -> bool override { return true; } auto abort() -> bool override; + auto getDependecies() const -> QList { return m_dependencies; } + protected slots: //! Entry point for tasks. void executeTask() override; void prepareDependecies(); - void addDependecies(QList, int); + void addDependecies(ModPlatform::IndexedVersion, int); QList getDependenciesForVersions(QList); - - signals: - void getAllMod(QList); + QList getDependenciesForVersion(ModPlatform::IndexedVersion); private: QList m_selected; @@ -60,4 +61,5 @@ class GetModDependenciesTask : public Task { LocalModGetAllTaskPtr m_getAllMods = nullptr; NewDependecyVersionAPITask m_getDependenciesVersionAPI; SequentialTask::Ptr m_getNetworkDep; + QEventLoop loop; }; diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index a820e3a1..38ecb9ab 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -39,15 +39,15 @@ void FlameMod::loadURLs(ModPlatform::IndexedPack& pack, QJsonObject& obj) auto links_obj = Json::ensureObject(obj, "links"); pack.extraData.issuesUrl = Json::ensureString(links_obj, "issuesUrl"); - if(pack.extraData.issuesUrl.endsWith('/')) + if (pack.extraData.issuesUrl.endsWith('/')) pack.extraData.issuesUrl.chop(1); pack.extraData.sourceUrl = Json::ensureString(links_obj, "sourceUrl"); - if(pack.extraData.sourceUrl.endsWith('/')) + if (pack.extraData.sourceUrl.endsWith('/')) pack.extraData.sourceUrl.chop(1); pack.extraData.wikiUrl = Json::ensureString(links_obj, "wikiUrl"); - if(pack.extraData.wikiUrl.endsWith('/')) + if (pack.extraData.wikiUrl.endsWith('/')) pack.extraData.wikiUrl.chop(1); if (!pack.extraData.body.isEmpty()) @@ -56,7 +56,7 @@ void FlameMod::loadURLs(ModPlatform::IndexedPack& pack, QJsonObject& obj) void FlameMod::loadBody(ModPlatform::IndexedPack& pack, QJsonObject& obj) { - pack.extraData.body = api.getModDescription(pack.addonId.toInt()); + pack.extraData.body = api.getModDescription(pack.addonId.toInt()); if (!pack.extraData.issuesUrl.isEmpty() || !pack.extraData.sourceUrl.isEmpty() || !pack.extraData.wikiUrl.isEmpty()) pack.extraDataLoaded = true; @@ -64,12 +64,12 @@ void FlameMod::loadBody(ModPlatform::IndexedPack& pack, QJsonObject& obj) static QString enumToString(int hash_algorithm) { - switch(hash_algorithm){ - default: - case 1: - return "sha1"; - case 2: - return "md5"; + switch (hash_algorithm) { + default: + case 1: + return "sha1"; + case 2: + return "md5"; } } @@ -84,12 +84,12 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, for (auto versionIter : arr) { auto obj = versionIter.toObject(); - + auto file = loadIndexedPackVersion(obj); - if(!file.addonId.isValid()) + if (!file.addonId.isValid()) file.addonId = pack.addonId; - if(file.fileId.isValid()) // Heuristic to check if the returned value is valid + if (file.fileId.isValid()) // Heuristic to check if the returned value is valid unsortedVersions.append(file); } @@ -169,3 +169,25 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> return file; } + +ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) +{ + QVector unsortedVersions; + for (auto versionIter : arr) { + auto obj = versionIter.toObject(); + + auto file = loadIndexedPackVersion(obj); + if (!file.addonId.isValid()) + file.addonId = m.addonId; + + if (file.fileId.isValid()) // Heuristic to check if the returned value is valid + unsortedVersions.append(file); + } + + auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { + // dates are in RFC 3339 format + return a.date > b.date; + }; + std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); + return unsortedVersions.front(); +}; diff --git a/launcher/modplatform/flame/FlameModIndex.h b/launcher/modplatform/flame/FlameModIndex.h index 33c4a529..306959e0 100644 --- a/launcher/modplatform/flame/FlameModIndex.h +++ b/launcher/modplatform/flame/FlameModIndex.h @@ -6,8 +6,8 @@ #include "modplatform/ModIndex.h" -#include "BaseInstance.h" #include +#include "BaseInstance.h" namespace FlameMod { @@ -19,5 +19,5 @@ void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, const shared_qobject_ptr& network, const BaseInstance* inst); auto loadIndexedPackVersion(QJsonObject& obj, bool load_changelog = false) -> ModPlatform::IndexedVersion; - -} // namespace FlameMod +auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion; +} // namespace FlameMod \ No newline at end of file diff --git a/launcher/modplatform/flame/FlamePackIndex.h b/launcher/modplatform/flame/FlamePackIndex.h index 1ca0fc0e..b089b722 100644 --- a/launcher/modplatform/flame/FlamePackIndex.h +++ b/launcher/modplatform/flame/FlamePackIndex.h @@ -4,6 +4,7 @@ #include #include #include +#include "modplatform/ModIndex.h" namespace Flame { @@ -27,8 +28,7 @@ struct ModpackExtra { QString sourceUrl; }; -struct IndexedPack -{ +struct IndexedPack { int addonId; QString name; QString description; @@ -43,9 +43,9 @@ struct IndexedPack ModpackExtra extra; }; -void loadIndexedPack(IndexedPack & m, QJsonObject & obj); +void loadIndexedPack(IndexedPack& m, QJsonObject& obj); void loadIndexedInfo(IndexedPack&, QJsonObject&); -void loadIndexedPackVersions(IndexedPack & m, QJsonArray & arr); -} +void loadIndexedPackVersions(IndexedPack& m, QJsonArray& arr); +} // namespace Flame Q_DECLARE_METATYPE(Flame::IndexedPack) diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 8e97ee7c..9f898c39 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -214,3 +214,22 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t return {}; } + +auto Modrinth::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +{ + QVector unsortedVersions; + + for (auto versionIter : arr) { + auto obj = versionIter.toObject(); + auto file = loadIndexedPackVersion(obj); + + if (file.fileId.isValid()) // Heuristic to check if the returned value is valid + unsortedVersions.append(file); + } + auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { + // dates are in RFC 3339 format + return a.date > b.date; + }; + std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); + return unsortedVersions.front(); +} \ No newline at end of file diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.h b/launcher/modplatform/modrinth/ModrinthPackIndex.h index e73e4b18..8aa53a11 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.h +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.h @@ -19,8 +19,8 @@ #include "modplatform/ModIndex.h" -#include "BaseInstance.h" #include +#include "BaseInstance.h" namespace Modrinth { @@ -31,5 +31,6 @@ void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, const shared_qobject_ptr& network, const BaseInstance* inst); auto loadIndexedPackVersion(QJsonObject& obj, QString hash_type = "sha512", QString filename_prefer = "") -> ModPlatform::IndexedVersion; +auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion; } // namespace Modrinth diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index edb7d063..e1041d95 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -18,17 +18,22 @@ */ #include "ResourceDownloadDialog.h" +#include +#include #include +#include +#include #include "Application.h" #include "ResourceDownloadTask.h" #include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ResourcePackFolderModel.h" -#include "minecraft/mod/TexturePackFolderModel.h" #include "minecraft/mod/ShaderPackFolderModel.h" +#include "minecraft/mod/TexturePackFolderModel.h" +#include "modplatform/ModIndex.h" #include "ui/dialogs/ReviewMessageBox.h" #include "ui/pages/modplatform/ResourcePage.h" @@ -41,7 +46,10 @@ namespace ResourceDownload { ResourceDownloadDialog::ResourceDownloadDialog(QWidget* parent, const std::shared_ptr base_model) - : QDialog(parent), m_base_model(base_model), m_buttons(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel), m_vertical_layout(this) + : QDialog(parent) + , m_base_model(base_model) + , m_buttons(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel) + , m_vertical_layout(this) { setObjectName(QStringLiteral("ResourceDownloadDialog")); @@ -102,7 +110,8 @@ void ResourceDownloadDialog::initializeContainer() void ResourceDownloadDialog::connectButtons() { auto OkButton = m_buttons.button(QDialogButtonBox::Ok); - OkButton->setToolTip(tr("Opens a new popup to review your selected %1 and confirm your selection. Shortcut: Ctrl+Return").arg(resourcesString())); + OkButton->setToolTip( + tr("Opens a new popup to review your selected %1 and confirm your selection. Shortcut: Ctrl+Return").arg(resourcesString())); connect(OkButton, &QPushButton::clicked, this, &ResourceDownloadDialog::confirm); auto CancelButton = m_buttons.button(QDialogButtonBox::Cancel); @@ -120,6 +129,26 @@ void ResourceDownloadDialog::confirm() auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString())); confirm_dialog->retranslateUi(resourcesString()); + if (auto model = dynamic_cast(getBaseModel().get()); model) { + QList selectedVers; + for (auto& task : keys) { + auto selected = m_selected.constFind(task).value(); + selectedVers.append(selected->getVersion()); + } + + auto dir = model->indexDir(); + auto dependencies = m_selectedPage->getDependecies(dir, selectedVers); + + for (auto dep : dependencies) { + dep.is_currently_selected = true; + auto pack = ModPlatform::IndexedPack{ + .addonId = dep.addonId, .provider = ModPlatform::ResourceProvider::FLAME, .name = dep.fileName, .slug = dep.fileName + }; + m_selected.insert(dep.fileName, makeShared(pack, dep, getBaseModel(), true)); + } + + keys = m_selected.keys(); + } for (auto& task : keys) { auto selected = m_selected.constFind(task).value(); confirm_dialog->appendResource({ task, selected->getFilename(), selected->getCustomPath() }); @@ -205,8 +234,6 @@ void ResourceDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* s m_selectedPage->setSearchTerm(prev_page->getSearchTerm()); } - - ModDownloadDialog::ModDownloadDialog(QWidget* parent, const std::shared_ptr& mods, BaseInstance* instance) : ResourceDownloadDialog(parent, mods), m_instance(instance) { @@ -232,7 +259,6 @@ QList ModDownloadDialog::getPages() return pages; } - ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent, const std::shared_ptr& resource_packs, BaseInstance* instance) @@ -258,7 +284,6 @@ QList ResourcePackDownloadDialog::getPages() return pages; } - TexturePackDownloadDialog::TexturePackDownloadDialog(QWidget* parent, const std::shared_ptr& resource_packs, BaseInstance* instance) @@ -284,7 +309,6 @@ QList TexturePackDownloadDialog::getPages() return pages; } - ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent, const std::shared_ptr& shaders, BaseInstance* instance) diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index 3ffe6cb0..bdbfe460 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -24,7 +24,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments() std::optional> versions{}; - { // Version filter + { // Version filter if (!m_filter->versions.empty()) versions = m_filter->versions; } @@ -49,6 +49,20 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en return { pack, versions, profile->getModLoaders() }; } +ResourceAPI::DependencySearchArgs ModModel::createDependecyArguments(ModPlatform::Dependency& dep) +{ + auto profile = static_cast(m_base_instance).getPackProfile(); + + Q_ASSERT(profile); + Q_ASSERT(m_filter); + + std::optional> versions{}; + if (!m_filter->versions.empty()) + versions = m_filter->versions; + + return { dep, versions->front(), profile->getModLoaders().value() }; +}; + ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry) { auto& pack = m_packs[entry.row()]; diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index 5d4a7785..ca536f8f 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -32,6 +32,7 @@ class ModModel : public ResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override = 0; + ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) override = 0; void setFilter(std::shared_ptr filter) { m_filter = filter; } @@ -39,6 +40,7 @@ class ModModel : public ResourceModel { ResourceAPI::SearchArgs createSearchArguments() override; ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override; ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) override; + ResourceAPI::DependencySearchArgs createDependecyArguments(ModPlatform::Dependency&) override; protected: auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0; diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index db7d26f8..42dd8dae 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -3,6 +3,8 @@ // SPDX-License-Identifier: GPL-3.0-only #include "ResourceModel.h" +#include +#include #include #include @@ -14,6 +16,7 @@ #include "BuildConfig.h" #include "Json.h" +#include "minecraft/mod/tasks/GetModDependenciesTask.h" #include "net/Download.h" #include "net/NetJob.h" @@ -321,6 +324,11 @@ void ResourceModel::loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArra { NEED_FOR_CALLBACK_ASSERT("loadIndexedPackVersions"); } +ModPlatform::IndexedVersion ResourceModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) +{ + NEED_FOR_CALLBACK_ASSERT("loadDependencyVersions"); + return {}; +} /* Default callbacks */ @@ -441,4 +449,35 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe emit projectInfoUpdated(); } +QList ResourceModel::getDependecies(QDir& dir, QList selected) +{ + auto task = new GetModDependenciesTask( + dir, selected, [this](ModPlatform::Dependency dependency, std::function succeeded) -> Task::Ptr { + auto args{ createDependecyArguments(dependency) }; + auto callbacks{ createDependecyCallbacks() }; + + // Use default if no callbacks are set + if (!callbacks.on_succeed) + callbacks.on_succeed = [this, dependency, succeeded](auto& doc, auto pack) { + ModPlatform::IndexedVersion ver; + try { + auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); + ver = loadDependencyVersions(dependency, arr); + } catch (const JSONValidationError& e) { + qDebug() << doc; + qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause(); + return; + } + + succeeded(ver); + }; + + return m_api->getDependencyVersion(std::move(args), std::move(callbacks)); + }); + + task->start(); + + return task->getDependecies(); +}; + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 46a02d6e..0292b84b 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -4,12 +4,14 @@ #pragma once +#include #include #include #include "QObjectPtr.h" +#include "modplatform/ModIndex.h" #include "modplatform/ResourceAPI.h" #include "tasks/ConcurrentTask.h" @@ -68,6 +70,9 @@ class ResourceModel : public QAbstractListModel { virtual ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) = 0; virtual ResourceAPI::ProjectInfoCallbacks createInfoCallbacks(QModelIndex&) { return {}; } + virtual ResourceAPI::DependencySearchArgs createDependecyArguments(ModPlatform::Dependency&) { return {}; }; + virtual ResourceAPI::DependencySearchCallbacks createDependecyCallbacks() { return {}; } + /** Requests the API for more entries. */ virtual void search(); @@ -80,6 +85,8 @@ class ResourceModel : public QAbstractListModel { /** Gets the icon at the URL for the given index. If it's not fetched yet, fetch it and update when fisinhed. */ std::optional getIcon(QModelIndex&, const QUrl&); + QList getDependecies(QDir& dir, QList m_selected); + protected: /** Resets the model's data. */ void clearData(); @@ -104,6 +111,7 @@ class ResourceModel : public QAbstractListModel { virtual void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&); virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&); virtual void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&); + virtual ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr); protected: /* Basic search parameters */ diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.h b/launcher/ui/pages/modplatform/ResourcePackModel.h index e2b4a195..40b271d6 100644 --- a/launcher/ui/pages/modplatform/ResourcePackModel.h +++ b/launcher/ui/pages/modplatform/ResourcePackModel.h @@ -28,6 +28,7 @@ class ResourcePackResourceModel : public ResourceModel { void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0; void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0; void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0; + ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) override = 0; public slots: ResourceAPI::SearchArgs createSearchArguments() override; diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index bbd465bc..ec43521f 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -408,4 +408,9 @@ void ResourcePage::openUrl(const QUrl& url) QDesktopServices::openUrl(url); } +QList ResourcePage::getDependecies(QDir& dir, QList selected) +{ + return m_model->getDependecies(dir, selected); +}; + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index 1896d53e..07f87929 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include @@ -75,9 +76,11 @@ class ResourcePage : public QWidget, public BasePage { virtual void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); virtual void removeResourceFromDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); + QList getDependecies(QDir& dir, QList m_selected); + protected slots: virtual void triggerSearch() {} - + void onSelectionChanged(QModelIndex first, QModelIndex second); void onVersionSelectionChanged(QString data); void onResourceSelected(); diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.h b/launcher/ui/pages/modplatform/ShaderPackModel.h index f3c695e9..60d74777 100644 --- a/launcher/ui/pages/modplatform/ShaderPackModel.h +++ b/launcher/ui/pages/modplatform/ShaderPackModel.h @@ -28,6 +28,7 @@ class ShaderPackResourceModel : public ResourceModel { void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0; void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0; void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0; + ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) override = 0; public slots: ResourceAPI::SearchArgs createSearchArguments() override; diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp index e3d0bc14..563ff963 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp @@ -29,6 +29,11 @@ void FlameModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonAr FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } +auto FlameModModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +{ + return FlameMod::loadDependencyVersions(m, arr); +}; + auto FlameModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray { return Json::ensureArray(obj.object(), "data"); @@ -52,6 +57,11 @@ void FlameResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } +auto FlameResourcePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +{ + return FlameMod::loadDependencyVersions(m, arr); +}; + auto FlameResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray { return Json::ensureArray(obj.object(), "data"); @@ -81,13 +91,18 @@ void FlameTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, auto const& mc_versions = version.mcVersion; if (std::any_of(mc_versions.constBegin(), mc_versions.constEnd(), - [this](auto const& mc_version){ return Version(mc_version) <= maximumTexturePackVersion(); })) + [this](auto const& mc_version) { return Version(mc_version) <= maximumTexturePackVersion(); })) filtered_versions.push_back(version); } m.versions = filtered_versions; } +auto FlameTexturePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +{ + return FlameMod::loadDependencyVersions(m, arr); +}; + ResourceAPI::SearchArgs FlameTexturePackModel::createSearchArguments() { auto args = TexturePackResourceModel::createSearchArguments(); diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h index 0252ac40..2f4413ac 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h @@ -24,6 +24,7 @@ class FlameModModel : public ModModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -42,6 +43,7 @@ class FlameResourcePackModel : public ResourcePackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -60,6 +62,7 @@ class FlameTexturePackModel : public TexturePackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; ResourceAPI::SearchArgs createSearchArguments() override; ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp index f5d1cc28..047e3aaa 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp @@ -42,12 +42,17 @@ void ModrinthModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJso ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } +auto ModrinthModModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +{ + return ::Modrinth::loadDependencyVersions(m, arr); +}; + auto ModrinthModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray { return obj.object().value("hits").toArray(); } -ModrinthResourcePackModel::ModrinthResourcePackModel(const BaseInstance& base) : ResourcePackResourceModel(base, new ModrinthAPI){} +ModrinthResourcePackModel::ModrinthResourcePackModel(const BaseInstance& base) : ResourcePackResourceModel(base, new ModrinthAPI) {} void ModrinthResourcePackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) { @@ -64,12 +69,17 @@ void ModrinthResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } +auto ModrinthResourcePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +{ + return ::Modrinth::loadDependencyVersions(m, arr); +}; + auto ModrinthResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray { return obj.object().value("hits").toArray(); } -ModrinthTexturePackModel::ModrinthTexturePackModel(const BaseInstance& base) : TexturePackResourceModel(base, new ModrinthAPI){} +ModrinthTexturePackModel::ModrinthTexturePackModel(const BaseInstance& base) : TexturePackResourceModel(base, new ModrinthAPI) {} void ModrinthTexturePackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) { @@ -86,12 +96,17 @@ void ModrinthTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } +auto ModrinthTexturePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +{ + return ::Modrinth::loadDependencyVersions(m, arr); +}; + auto ModrinthTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray { return obj.object().value("hits").toArray(); } -ModrinthShaderPackModel::ModrinthShaderPackModel(const BaseInstance& base) : ShaderPackResourceModel(base, new ModrinthAPI){} +ModrinthShaderPackModel::ModrinthShaderPackModel(const BaseInstance& base) : ShaderPackResourceModel(base, new ModrinthAPI) {} void ModrinthShaderPackModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) { @@ -108,6 +123,11 @@ void ModrinthShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } +auto ModrinthShaderPackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +{ + return ::Modrinth::loadDependencyVersions(m, arr); +}; + auto ModrinthShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray { return obj.object().value("hits").toArray(); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h index b351b19b..77157a41 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h @@ -40,6 +40,7 @@ class ModrinthModModel : public ModModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -58,6 +59,7 @@ class ModrinthResourcePackModel : public ResourcePackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -76,6 +78,7 @@ class ModrinthTexturePackModel : public TexturePackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -94,6 +97,7 @@ class ModrinthShaderPackModel : public ShaderPackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; + auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; -- cgit From 5079ce8d64d68d3fd2925baf18976385e44ebdc2 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 14 Apr 2023 23:18:37 +0300 Subject: Fixed headers Signed-off-by: Trial97 --- launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 1 + launcher/minecraft/mod/tasks/GetModDependenciesTask.h | 3 +-- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 4 ++-- launcher/ui/pages/modplatform/ResourceModel.cpp | 4 ++-- launcher/ui/pages/modplatform/ResourceModel.h | 2 +- launcher/ui/pages/modplatform/ResourcePage.h | 3 +-- 6 files changed, 8 insertions(+), 9 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 9cc227f2..1247e763 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -19,6 +19,7 @@ #include "GetModDependenciesTask.h" +#include #include "QObjectPtr.h" #include "minecraft/mod/MetadataHandler.h" #include "minecraft/mod/tasks/LocalModGetAllTask.h" diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index 4353c1e1..1670cb6f 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -18,9 +18,8 @@ #pragma once -#include -#include #include +#include #include #include "minecraft/mod/MetadataHandler.h" diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index e1041d95..143a6e50 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -18,8 +18,8 @@ */ #include "ResourceDownloadDialog.h" -#include -#include +#include +#include #include #include diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 42dd8dae..eb8c1820 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -3,8 +3,8 @@ // SPDX-License-Identifier: GPL-3.0-only #include "ResourceModel.h" -#include -#include +#include +#include #include #include diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 0292b84b..5dbef794 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -4,7 +4,7 @@ #pragma once -#include +#include #include #include diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index 07f87929..4fffd506 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -4,12 +4,11 @@ #pragma once -#include +#include #include #include #include "modplatform/ModIndex.h" -#include "modplatform/ResourceAPI.h" #include "ui/pages/BasePage.h" #include "ui/widgets/ProgressWidget.h" -- cgit From bcea19b957bb0db4270b7573540af40143cca7de Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 15 Apr 2023 00:10:45 +0300 Subject: Tried to fix codeQL Signed-off-by: Trial97 --- launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 17 +++++++++-------- launcher/minecraft/mod/tasks/GetModDependenciesTask.h | 9 +++++---- launcher/ui/pages/modplatform/ModModel.cpp | 2 +- launcher/ui/pages/modplatform/ModModel.h | 2 +- launcher/ui/pages/modplatform/ResourceModel.cpp | 3 ++- launcher/ui/pages/modplatform/ResourceModel.h | 2 +- 6 files changed, 19 insertions(+), 16 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 1247e763..aeaa4b5b 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -75,7 +75,7 @@ void GetModDependenciesTask::prepareDependecies() m_getNetworkDep->start(); } -void GetModDependenciesTask::addDependecies(ModPlatform::IndexedVersion new_version, int level) +void GetModDependenciesTask::addDependecies(const ModPlatform::IndexedVersion& new_version, int level) { // some mutex? m_dependencies.append(new_version); @@ -85,6 +85,7 @@ void GetModDependenciesTask::addDependecies(ModPlatform::IndexedVersion new_vers } if (level == 0) { qWarning() << "Dependency cycle exeeded"; + return; } for (auto dep : c_dependencies) { auto task = m_getDependenciesVersionAPI( @@ -93,20 +94,20 @@ void GetModDependenciesTask::addDependecies(ModPlatform::IndexedVersion new_vers } }; -QList GetModDependenciesTask::getDependenciesForVersions(QList selected) +QList GetModDependenciesTask::getDependenciesForVersions(const QList& selected) { auto c_dependencies = QList(); for (auto version : selected) { for (auto ver_dep : version.dependencies) { if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) { if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), - [ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); + [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); dep == c_dependencies.end()) { // check the current dependency list if (auto dep = - std::find_if(selected.begin(), selected.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); + std::find_if(selected.begin(), selected.end(), [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); dep == selected.end()) { // check the selected versions if (auto dep = - std::find_if(m_mods.begin(), m_mods.end(), [ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; }); + std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; }); dep == m_mods.end()) { // check the existing mods c_dependencies.append(ver_dep); } @@ -118,15 +119,15 @@ QList GetModDependenciesTask::getDependenciesForVersion return c_dependencies; }; -QList GetModDependenciesTask::getDependenciesForVersion(ModPlatform::IndexedVersion version) +QList GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version) { auto c_dependencies = QList(); for (auto ver_dep : version.dependencies) { if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) { if (auto dep = - std::find_if(c_dependencies.begin(), c_dependencies.end(), [ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); + std::find_if(c_dependencies.begin(), c_dependencies.end(), [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); dep == c_dependencies.end()) { // check the current dependency list - if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), [ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; }); + if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; }); dep == m_mods.end()) { // check the existing mods c_dependencies.append(ver_dep); } diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index 1670cb6f..7f7e1fb1 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -34,7 +34,8 @@ class GetModDependenciesTask : public Task { using Ptr = shared_qobject_ptr; using LocalModGetAllTaskPtr = shared_qobject_ptr; - using NewDependecyVersionAPITask = std::function)>; + using NewDependecyVersionAPITask = + std::function)>; explicit GetModDependenciesTask(QDir index_dir, QList selected, NewDependecyVersionAPITask api); @@ -48,9 +49,9 @@ class GetModDependenciesTask : public Task { void executeTask() override; void prepareDependecies(); - void addDependecies(ModPlatform::IndexedVersion, int); - QList getDependenciesForVersions(QList); - QList getDependenciesForVersion(ModPlatform::IndexedVersion); + void addDependecies(const ModPlatform::IndexedVersion&, int); + QList getDependenciesForVersions(const QList&); + QList getDependenciesForVersion(const ModPlatform::IndexedVersion&); private: QList m_selected; diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index bdbfe460..19c20e65 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -49,7 +49,7 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en return { pack, versions, profile->getModLoaders() }; } -ResourceAPI::DependencySearchArgs ModModel::createDependecyArguments(ModPlatform::Dependency& dep) +ResourceAPI::DependencySearchArgs ModModel::createDependecyArguments(const ModPlatform::Dependency& dep) { auto profile = static_cast(m_base_instance).getPackProfile(); diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index ca536f8f..97638902 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -40,7 +40,7 @@ class ModModel : public ResourceModel { ResourceAPI::SearchArgs createSearchArguments() override; ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override; ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) override; - ResourceAPI::DependencySearchArgs createDependecyArguments(ModPlatform::Dependency&) override; + ResourceAPI::DependencySearchArgs createDependecyArguments(const ModPlatform::Dependency&) override; protected: auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0; diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index eb8c1820..75585d6f 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -452,7 +452,8 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe QList ResourceModel::getDependecies(QDir& dir, QList selected) { auto task = new GetModDependenciesTask( - dir, selected, [this](ModPlatform::Dependency dependency, std::function succeeded) -> Task::Ptr { + dir, selected, + [this](const ModPlatform::Dependency& dependency, std::function succeeded) -> Task::Ptr { auto args{ createDependecyArguments(dependency) }; auto callbacks{ createDependecyCallbacks() }; diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 5dbef794..ce327c3b 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -70,7 +70,7 @@ class ResourceModel : public QAbstractListModel { virtual ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) = 0; virtual ResourceAPI::ProjectInfoCallbacks createInfoCallbacks(QModelIndex&) { return {}; } - virtual ResourceAPI::DependencySearchArgs createDependecyArguments(ModPlatform::Dependency&) { return {}; }; + virtual ResourceAPI::DependencySearchArgs createDependecyArguments(const ModPlatform::Dependency&) { return {}; }; virtual ResourceAPI::DependencySearchCallbacks createDependecyCallbacks() { return {}; } /** Requests the API for more entries. */ -- cgit From 7bd26ce4687b498fb91d42594da07fea1eca5552 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 17 Apr 2023 00:49:35 +0300 Subject: Semi fixed the Modrinth dependency implementation Signed-off-by: Trial97 --- .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 22 ++++++++++++---------- launcher/modplatform/ResourceAPI.h | 2 +- .../modplatform/modrinth/ModrinthPackIndex.cpp | 5 +++-- launcher/ui/pages/modplatform/ResourceModel.cpp | 11 +++++++++-- 4 files changed, 25 insertions(+), 15 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index aeaa4b5b..92e652c0 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -69,7 +69,8 @@ void GetModDependenciesTask::prepareDependecies() return; } for (auto dep : c_dependencies) { - auto task = m_getDependenciesVersionAPI(dep, [this](ModPlatform::IndexedVersion new_version) { addDependecies(new_version, 20); }); + auto task = + m_getDependenciesVersionAPI(dep, [this](const ModPlatform::IndexedVersion& new_version) { addDependecies(new_version, 20); }); m_getNetworkDep->addTask(task); } m_getNetworkDep->start(); @@ -89,7 +90,7 @@ void GetModDependenciesTask::addDependecies(const ModPlatform::IndexedVersion& n } for (auto dep : c_dependencies) { auto task = m_getDependenciesVersionAPI( - dep, [this, level](ModPlatform::IndexedVersion new_versions) { addDependecies(new_versions, level - 1); }); + dep, [this, level](const ModPlatform::IndexedVersion& new_versions) { addDependecies(new_versions, level - 1); }); m_getNetworkDep->addTask(task); } }; @@ -101,13 +102,13 @@ QList GetModDependenciesTask::getDependenciesForVersion for (auto ver_dep : version.dependencies) { if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) { if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), - [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); + [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; }); dep == c_dependencies.end()) { // check the current dependency list - if (auto dep = - std::find_if(selected.begin(), selected.end(), [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); + if (auto dep = std::find_if(selected.begin(), selected.end(), + [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; }); dep == selected.end()) { // check the selected versions - if (auto dep = - std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; }); + if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), + [&ver_dep](const auto& i) { return i.project_id == ver_dep.addonId; }); dep == m_mods.end()) { // check the existing mods c_dependencies.append(ver_dep); } @@ -124,10 +125,11 @@ QList GetModDependenciesTask::getDependenciesForVersion auto c_dependencies = QList(); for (auto ver_dep : version.dependencies) { if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) { - if (auto dep = - std::find_if(c_dependencies.begin(), c_dependencies.end(), [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); + if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), + [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; }); dep == c_dependencies.end()) { // check the current dependency list - if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; }); + if (auto dep = + std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](const auto& i) { return i.project_id == ver_dep.addonId; }); dep == m_mods.end()) { // check the existing mods c_dependencies.append(ver_dep); } diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index a8e144dc..c23444b3 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -126,7 +126,7 @@ class ResourceAPI { }; struct DependencySearchCallbacks { - std::function on_succeed; + std::function on_succeed; }; public: diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 9f898c39..ee957680 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -22,6 +22,7 @@ #include "Json.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" +#include "modplatform/ModIndex.h" static ModrinthAPI api; static ModPlatform::ProviderCapabilities ProviderCaps; @@ -144,7 +145,7 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t auto dep = Json::ensureObject(d); ModPlatform::Dependency dependency; dependency.addonId = Json::requireString(dep, "project_id"); - dependency.version = Json::requireString(dep, "version_id"); + dependency.version = Json::ensureString(dep, "version_id"); auto depType = Json::requireString(dep, "dependency_type"); if (depType == "required") @@ -231,5 +232,5 @@ auto Modrinth::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr return a.date > b.date; }; std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); - return unsortedVersions.front(); + return unsortedVersions.length() != 0 ? unsortedVersions.front() : ModPlatform::IndexedVersion(); } \ No newline at end of file diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 75585d6f..c1ffd0da 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -459,11 +459,18 @@ QList ResourceModel::getDependecies(QDir& dir, QLis // Use default if no callbacks are set if (!callbacks.on_succeed) - callbacks.on_succeed = [this, dependency, succeeded](auto& doc, auto pack) { + callbacks.on_succeed = [this, dependency, succeeded](auto& doc, auto& pack) { ModPlatform::IndexedVersion ver; try { - auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); + auto arr = dependency.version.length() != 0 && doc.isObject() + ? Json::toJsonArray(QList() << doc.object()) + : doc.isObject() ? Json::ensureArray(doc.object(), "data") + : doc.array(); ver = loadDependencyVersions(dependency, arr); + if (!ver.addonId.isValid()) { + qWarning() << "Error while reading " << debugName() << " resource version empty "; + qDebug() << doc; + } } catch (const JSONValidationError& e) { qDebug() << doc; qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause(); -- cgit From f3f8f3574af20e279e41d3a02f337d5d59fc4a7e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 17 Apr 2023 01:10:02 +0300 Subject: Small headers removal Signed-off-by: Trial97 --- .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 8 ------ .../minecraft/mod/tasks/LocalModUpdateTask.cpp | 33 +++++++++++----------- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 1 - 3 files changed, 16 insertions(+), 26 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 92e652c0..f1f8581f 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -27,10 +27,6 @@ #include "tasks/ConcurrentTask.h" #include "tasks/SequentialTask.h" -#ifdef Q_OS_WIN32 -#include -#endif - GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList selected, NewDependecyVersionAPITask api) : m_selected(selected), m_getDependenciesVersionAPI(api) { @@ -41,10 +37,6 @@ GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList -* Copyright (C) 2022 Sefa Eyeoglu -* -* 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 . -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * 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 . + */ #include "LocalModUpdateTask.h" -#include "Application.h" #include "FileSystem.h" #include "minecraft/mod/MetadataHandler.h" diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 143a6e50..fe4692d6 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -23,7 +23,6 @@ #include #include -#include #include "Application.h" #include "ResourceDownloadTask.h" -- cgit From 31e84780a882622385dda0c574c128046d625eba Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 17 Apr 2023 20:03:49 +0300 Subject: Hope to fix windows build errors Signed-off-by: Trial97 --- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 4 +--- launcher/ui/pages/modplatform/ResourcePage.cpp | 3 --- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index fe4692d6..610f2449 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -140,9 +140,7 @@ void ResourceDownloadDialog::confirm() for (auto dep : dependencies) { dep.is_currently_selected = true; - auto pack = ModPlatform::IndexedPack{ - .addonId = dep.addonId, .provider = ModPlatform::ResourceProvider::FLAME, .name = dep.fileName, .slug = dep.fileName - }; + auto pack = ModPlatform::IndexedPack{ dep.addonId, ModPlatform::ResourceProvider::FLAME, dep.fileName, dep.fileName }; m_selected.insert(dep.fileName, makeShared(pack, dep, getBaseModel(), true)); } diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index ec43521f..02412fd9 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -43,9 +43,6 @@ #include #include "Markdown.h" -#include "ResourceDownloadTask.h" - -#include "minecraft/MinecraftInstance.h" #include "ui/dialogs/ResourceDownloadDialog.h" #include "ui/pages/modplatform/ResourceModel.h" -- cgit From fac33498dbd50fd9af60164e786534615586d6ac Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 17 Apr 2023 20:41:00 +0300 Subject: Made some copy by reference Signed-off-by: Trial97 --- launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 2 +- launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp | 2 +- launcher/minecraft/mod/tasks/LocalModGetAllTask.h | 2 +- launcher/modplatform/flame/FlameModIndex.cpp | 2 +- launcher/modplatform/flame/FlameModIndex.h | 2 +- launcher/modplatform/modrinth/ModrinthPackIndex.cpp | 2 +- launcher/modplatform/modrinth/ModrinthPackIndex.h | 2 +- launcher/ui/pages/modplatform/ModModel.h | 2 +- launcher/ui/pages/modplatform/ResourceModel.cpp | 15 +++++++++------ launcher/ui/pages/modplatform/ResourceModel.h | 2 +- launcher/ui/pages/modplatform/ResourcePackModel.h | 2 +- launcher/ui/pages/modplatform/ShaderPackModel.h | 2 +- .../ui/pages/modplatform/flame/FlameResourceModels.cpp | 6 +++--- launcher/ui/pages/modplatform/flame/FlameResourceModels.h | 6 +++--- .../pages/modplatform/modrinth/ModrinthResourceModels.cpp | 8 ++++---- .../pages/modplatform/modrinth/ModrinthResourceModels.h | 8 ++++---- 16 files changed, 34 insertions(+), 31 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index f1f8581f..7f184765 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -33,7 +33,7 @@ GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList(index_dir); m_getNetworkDep = makeShared(this, "GetDepInfo"); connect(m_getNetworkDep.get(), &Task::finished, &loop, &QEventLoop::quit); - QObject::connect(m_getAllMods.get(), &LocalModGetAllTask::getAllMod, [this](QList mods) { + QObject::connect(m_getAllMods.get(), &LocalModGetAllTask::getAllMods, [this](QList mods) { m_mods = mods; prepareDependecies(); }); diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp b/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp index 9e4293ff..67058807 100644 --- a/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp @@ -41,7 +41,7 @@ LocalModGetAllTask::LocalModGetAllTask(QDir index_dir) : m_index_dir(index_dir) void LocalModGetAllTask::executeTask() { setStatus(tr("Geting all mods")); - emit getAllMod(Metadata::getAll(m_index_dir)); + emit getAllMods(Metadata::getAll(m_index_dir)); emitSucceeded(); } diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.h b/launcher/minecraft/mod/tasks/LocalModGetAllTask.h index 09e453e4..bf4b78b7 100644 --- a/launcher/minecraft/mod/tasks/LocalModGetAllTask.h +++ b/launcher/minecraft/mod/tasks/LocalModGetAllTask.h @@ -38,7 +38,7 @@ class LocalModGetAllTask : public Task { void executeTask() override; signals: - void getAllMod(QList); + void getAllMods(QList); private: QDir m_index_dir; diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 38ecb9ab..120bfc91 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -170,7 +170,7 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> return file; } -ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) +ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) { QVector unsortedVersions; for (auto versionIter : arr) { diff --git a/launcher/modplatform/flame/FlameModIndex.h b/launcher/modplatform/flame/FlameModIndex.h index 306959e0..aa0d6f81 100644 --- a/launcher/modplatform/flame/FlameModIndex.h +++ b/launcher/modplatform/flame/FlameModIndex.h @@ -19,5 +19,5 @@ void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, const shared_qobject_ptr& network, const BaseInstance* inst); auto loadIndexedPackVersion(QJsonObject& obj, bool load_changelog = false) -> ModPlatform::IndexedVersion; -auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion; +auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion; } // namespace FlameMod \ No newline at end of file diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index ee957680..879260a3 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -216,7 +216,7 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t return {}; } -auto Modrinth::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +auto Modrinth::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { QVector unsortedVersions; diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.h b/launcher/modplatform/modrinth/ModrinthPackIndex.h index 8aa53a11..a8d986c5 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.h +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.h @@ -31,6 +31,6 @@ void loadIndexedPackVersions(ModPlatform::IndexedPack& pack, const shared_qobject_ptr& network, const BaseInstance* inst); auto loadIndexedPackVersion(QJsonObject& obj, QString hash_type = "sha512", QString filename_prefer = "") -> ModPlatform::IndexedVersion; -auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion; +auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion; } // namespace Modrinth diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index 97638902..59b27dda 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -32,7 +32,7 @@ class ModModel : public ResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override = 0; - ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) override = 0; + ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) override = 0; void setFilter(std::shared_ptr filter) { m_filter = filter; } diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index c1ffd0da..c1746d41 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -324,7 +324,7 @@ void ResourceModel::loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArra { NEED_FOR_CALLBACK_ASSERT("loadIndexedPackVersions"); } -ModPlatform::IndexedVersion ResourceModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) +ModPlatform::IndexedVersion ResourceModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) { NEED_FOR_CALLBACK_ASSERT("loadDependencyVersions"); return {}; @@ -451,7 +451,7 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe QList ResourceModel::getDependecies(QDir& dir, QList selected) { - auto task = new GetModDependenciesTask( + auto task = std::make_unique( dir, selected, [this](const ModPlatform::Dependency& dependency, std::function succeeded) -> Task::Ptr { auto args{ createDependecyArguments(dependency) }; @@ -462,14 +462,17 @@ QList ResourceModel::getDependecies(QDir& dir, QLis callbacks.on_succeed = [this, dependency, succeeded](auto& doc, auto& pack) { ModPlatform::IndexedVersion ver; try { - auto arr = dependency.version.length() != 0 && doc.isObject() - ? Json::toJsonArray(QList() << doc.object()) - : doc.isObject() ? Json::ensureArray(doc.object(), "data") - : doc.array(); + QJsonArray arr; + if (dependency.version.length() != 0 && doc.isObject()) { + arr.append(doc.object()); + } else { + arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); + } ver = loadDependencyVersions(dependency, arr); if (!ver.addonId.isValid()) { qWarning() << "Error while reading " << debugName() << " resource version empty "; qDebug() << doc; + return; } } catch (const JSONValidationError& e) { qDebug() << doc; diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index ce327c3b..3b1f4748 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -111,7 +111,7 @@ class ResourceModel : public QAbstractListModel { virtual void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&); virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&); virtual void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&); - virtual ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr); + virtual ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr); protected: /* Basic search parameters */ diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.h b/launcher/ui/pages/modplatform/ResourcePackModel.h index 40b271d6..8ff4d8a2 100644 --- a/launcher/ui/pages/modplatform/ResourcePackModel.h +++ b/launcher/ui/pages/modplatform/ResourcePackModel.h @@ -28,7 +28,7 @@ class ResourcePackResourceModel : public ResourceModel { void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0; void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0; void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0; - ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) override = 0; + ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) override = 0; public slots: ResourceAPI::SearchArgs createSearchArguments() override; diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.h b/launcher/ui/pages/modplatform/ShaderPackModel.h index 60d74777..17a07aa4 100644 --- a/launcher/ui/pages/modplatform/ShaderPackModel.h +++ b/launcher/ui/pages/modplatform/ShaderPackModel.h @@ -28,7 +28,7 @@ class ShaderPackResourceModel : public ResourceModel { void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0; void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0; void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0; - ModPlatform::IndexedVersion loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) override = 0; + ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) override = 0; public slots: ResourceAPI::SearchArgs createSearchArguments() override; diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp index 563ff963..08bf22fe 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp @@ -29,7 +29,7 @@ void FlameModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonAr FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } -auto FlameModModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +auto FlameModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { return FlameMod::loadDependencyVersions(m, arr); }; @@ -57,7 +57,7 @@ void FlameResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } -auto FlameResourcePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +auto FlameResourcePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { return FlameMod::loadDependencyVersions(m, arr); }; @@ -98,7 +98,7 @@ void FlameTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, m.versions = filtered_versions; } -auto FlameTexturePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +auto FlameTexturePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { return FlameMod::loadDependencyVersions(m, arr); }; diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h index 2f4413ac..7871d9aa 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h @@ -24,7 +24,7 @@ class FlameModModel : public ModModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; + auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -43,7 +43,7 @@ class FlameResourcePackModel : public ResourcePackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; + auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -62,7 +62,7 @@ class FlameTexturePackModel : public TexturePackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; + auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; ResourceAPI::SearchArgs createSearchArguments() override; ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp index 047e3aaa..53be2d2c 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp @@ -42,7 +42,7 @@ void ModrinthModModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJso ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } -auto ModrinthModModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +auto ModrinthModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { return ::Modrinth::loadDependencyVersions(m, arr); }; @@ -69,7 +69,7 @@ void ModrinthResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } -auto ModrinthResourcePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +auto ModrinthResourcePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { return ::Modrinth::loadDependencyVersions(m, arr); }; @@ -96,7 +96,7 @@ void ModrinthTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } -auto ModrinthTexturePackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +auto ModrinthTexturePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { return ::Modrinth::loadDependencyVersions(m, arr); }; @@ -123,7 +123,7 @@ void ModrinthShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } -auto ModrinthShaderPackModel::loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion +auto ModrinthShaderPackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { return ::Modrinth::loadDependencyVersions(m, arr); }; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h index 77157a41..0045fe86 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h @@ -40,7 +40,7 @@ class ModrinthModModel : public ModModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; + auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -59,7 +59,7 @@ class ModrinthResourcePackModel : public ResourcePackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; + auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -78,7 +78,7 @@ class ModrinthTexturePackModel : public TexturePackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; + auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -97,7 +97,7 @@ class ModrinthShaderPackModel : public ShaderPackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(ModPlatform::Dependency m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; + auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; -- cgit From c1490cd62703975c5478aea1156d0bbefcc37bc8 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 20 Apr 2023 00:57:09 +0300 Subject: Refator task to work with multiple providers Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 2 - launcher/ResourceDownloadTask.h | 1 + .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 201 +++++++++++++-------- .../minecraft/mod/tasks/GetModDependenciesTask.h | 62 ++++--- .../minecraft/mod/tasks/LocalModGetAllTask.cpp | 52 ------ launcher/minecraft/mod/tasks/LocalModGetAllTask.h | 45 ----- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 69 +++++-- launcher/ui/dialogs/ResourceDownloadDialog.h | 15 +- launcher/ui/pages/modplatform/ResourceModel.cpp | 42 ----- launcher/ui/pages/modplatform/ResourceModel.h | 2 - launcher/ui/pages/modplatform/ResourcePage.cpp | 5 - launcher/ui/pages/modplatform/ResourcePage.h | 2 - 12 files changed, 219 insertions(+), 279 deletions(-) delete mode 100644 launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp delete mode 100644 launcher/minecraft/mod/tasks/LocalModGetAllTask.h (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index fca8c914..19356b94 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -361,8 +361,6 @@ set(MINECRAFT_SOURCES minecraft/mod/tasks/LocalResourceParse.cpp minecraft/mod/tasks/GetModDependenciesTask.h minecraft/mod/tasks/GetModDependenciesTask.cpp - minecraft/mod/tasks/LocalModGetAllTask.h - minecraft/mod/tasks/LocalModGetAllTask.cpp # Assets minecraft/AssetsUtils.h diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h index f2118524..29d3ae0a 100644 --- a/launcher/ResourceDownloadTask.h +++ b/launcher/ResourceDownloadTask.h @@ -38,6 +38,7 @@ class ResourceDownloadTask : public SequentialTask { const QString& getCustomPath() const { return m_pack_version.custom_target_folder; } const QVariant& getVersionID() const { return m_pack_version.fileId; } const ModPlatform::IndexedVersion& getVersion() const { return m_pack_version; } + const ModPlatform::IndexedPack& getPack() const { return m_pack; } private: ModPlatform::IndexedPack m_pack; diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 7f184765..966eea19 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -20,90 +20,74 @@ #include "GetModDependenciesTask.h" #include +#include +#include +#include "Json.h" #include "QObjectPtr.h" #include "minecraft/mod/MetadataHandler.h" -#include "minecraft/mod/tasks/LocalModGetAllTask.h" #include "modplatform/ModIndex.h" +#include "modplatform/flame/FlameAPI.h" +#include "modplatform/modrinth/ModrinthAPI.h" #include "tasks/ConcurrentTask.h" #include "tasks/SequentialTask.h" +#include "ui/pages/modplatform/ModModel.h" +#include "ui/pages/modplatform/flame/FlameResourceModels.h" +#include "ui/pages/modplatform/modrinth/ModrinthResourceModels.h" -GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList selected, NewDependecyVersionAPITask api) - : m_selected(selected), m_getDependenciesVersionAPI(api) +static Version mcVersions(BaseInstance* inst) { - m_getAllMods = makeShared(index_dir); - m_getNetworkDep = makeShared(this, "GetDepInfo"); - connect(m_getNetworkDep.get(), &Task::finished, &loop, &QEventLoop::quit); - QObject::connect(m_getAllMods.get(), &LocalModGetAllTask::getAllMods, [this](QList mods) { - m_mods = mods; - prepareDependecies(); - }); + return static_cast(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion(); } -void GetModDependenciesTask::executeTask() +static ResourceAPI::ModLoaderTypes mcLoaders(BaseInstance* inst) { - setStatus(tr("Geting all mods")); - m_getAllMods->start(); - loop.exec(); - emitSucceeded(); + return static_cast(inst)->getPackProfile()->getModLoaders().value(); } -auto GetModDependenciesTask::abort() -> bool +GetModDependenciesTask::GetModDependenciesTask(QObject* parent, + BaseInstance* instance, + ModFolderModel* folder, + QList> selected) + : SequentialTask(parent, "Get dependencies"), m_selected(selected), m_version(mcVersions(instance)), m_loaderType(mcLoaders(instance)) { - emitAborted(); - return true; -} + m_providers.append(Provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared(*instance), + std::make_shared() }); + m_providers.append(Provider{ ModPlatform::ResourceProvider::MODRINTH, std::make_shared(*instance), + std::make_shared() }); + for (auto mod : folder->allMods()) + m_mods.append(mod->metadata()); + prepare(); +}; -void GetModDependenciesTask::prepareDependecies() +void GetModDependenciesTask::prepare() { - auto c_dependencies = getDependenciesForVersions(m_selected); - if (c_dependencies.length() == 0) { - m_getNetworkDep->start(); - return; - } - for (auto dep : c_dependencies) { - auto task = - m_getDependenciesVersionAPI(dep, [this](const ModPlatform::IndexedVersion& new_version) { addDependecies(new_version, 20); }); - m_getNetworkDep->addTask(task); + for (auto sel : m_selected) { + for (auto dep : getDependenciesForVersion(sel->version, sel->pack.provider)) { + addTask(prepareDependencyTask(dep, sel->pack.provider, 20)); + } } - m_getNetworkDep->start(); } -void GetModDependenciesTask::addDependecies(const ModPlatform::IndexedVersion& new_version, int level) -{ - // some mutex? - m_dependencies.append(new_version); - auto c_dependencies = getDependenciesForVersion(new_version); - if (c_dependencies.length() == 0) { - return; - } - if (level == 0) { - qWarning() << "Dependency cycle exeeded"; - return; - } - for (auto dep : c_dependencies) { - auto task = m_getDependenciesVersionAPI( - dep, [this, level](const ModPlatform::IndexedVersion& new_versions) { addDependecies(new_versions, level - 1); }); - m_getNetworkDep->addTask(task); - } -}; - -QList GetModDependenciesTask::getDependenciesForVersions(const QList& selected) +QList GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version, + const ModPlatform::ResourceProvider providerName) { auto c_dependencies = QList(); - for (auto version : selected) { - for (auto ver_dep : version.dependencies) { - if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) { - if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), - [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; }); - dep == c_dependencies.end()) { // check the current dependency list - if (auto dep = std::find_if(selected.begin(), selected.end(), - [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; }); - dep == selected.end()) { // check the selected versions - if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), - [&ver_dep](const auto& i) { return i.project_id == ver_dep.addonId; }); - dep == m_mods.end()) { // check the existing mods - c_dependencies.append(ver_dep); - } + for (auto ver_dep : version.dependencies) { + if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) { + if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), + [&ver_dep](const ModPlatform::Dependency& i) { return i.addonId == ver_dep.addonId; }); + dep == c_dependencies.end()) { // check the current dependency list + if (auto dep = std::find_if(m_selected.begin(), m_selected.end(), + [&ver_dep, providerName](std::shared_ptr i) { + return i->pack.addonId == ver_dep.addonId && i->pack.provider == providerName; + }); + dep == m_selected.end()) { // check the selected versions + if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), + [&ver_dep, providerName](std::shared_ptr i) { + return i->project_id == ver_dep.addonId && i->provider == providerName; + }); + dep == m_mods.end()) { // check the existing mods + c_dependencies.append(ver_dep); } } } @@ -112,21 +96,80 @@ QList GetModDependenciesTask::getDependenciesForVersion return c_dependencies; }; -QList GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version) +Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Dependency& dep, + const ModPlatform::ResourceProvider providerName, + int level) { - auto c_dependencies = QList(); - for (auto ver_dep : version.dependencies) { - if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) { - if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), - [&ver_dep](const auto& i) { return i.addonId == ver_dep.addonId; }); - dep == c_dependencies.end()) { // check the current dependency list - if (auto dep = - std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](const auto& i) { return i.project_id == ver_dep.addonId; }); - dep == m_mods.end()) { // check the existing mods - c_dependencies.append(ver_dep); - } + auto pDep = std::make_shared(); + pDep->dependency = dep; + pDep->pack = { dep.addonId, providerName }; + m_pack_dependencies.append(pDep); + auto provider = + std::find_if(m_providers.begin(), m_providers.end(), [providerName](const Provider& p) { return p.name == providerName; }); + // if (provider == m_providers.end()) { + // qWarning() << "Unsuported provider for dependency check"; + // return nullptr; + // } + + auto tasks = makeShared(this, QString("DependencyInfo: %1").arg(dep.addonId.toString())); + + auto responseInfo = new QByteArray(); + auto info = provider->api->getProject(dep.addonId.toString(), responseInfo); + QObject::connect(info.get(), &NetJob::succeeded, [responseInfo, provider, pDep] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*responseInfo, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response for mod info at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *responseInfo; + return; + } + try { + auto obj = provider->name == ModPlatform::ResourceProvider::FLAME ? Json::requireObject(Json::requireObject(doc), "data") + : Json::requireObject(doc); + provider->mod->loadIndexedPack(pDep->pack, obj); + } catch (const JSONValidationError& e) { + qDebug() << doc; + qWarning() << "Error while reading mod info: " << e.cause(); + } + }); + tasks->addTask(info); + + ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType }; + ResourceAPI::DependencySearchCallbacks callbacks; + + callbacks.on_succeed = [dep, provider, pDep, level, this](auto& doc, auto& pack) { + try { + QJsonArray arr; + if (dep.version.length() != 0 && doc.isObject()) { + arr.append(doc.object()); + } else { + arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); + } + pDep->version = provider->mod->loadDependencyVersions(dep, arr); + if (!pDep->version.addonId.isValid()) { + qWarning() << "Error while reading mod version empty "; + qDebug() << doc; + return; } + pDep->version.is_currently_selected = true; + pDep->pack.versions = { pDep->version }; + pDep->pack.versionsLoaded = true; + } catch (const JSONValidationError& e) { + qDebug() << doc; + qWarning() << "Error while reading mod version: " << e.cause(); + return; } - } - return c_dependencies; -}; \ No newline at end of file + if (level == 0) { + qWarning() << "Dependency cycle exeeded"; + return; + } + for (auto dep : getDependenciesForVersion(pDep->version, provider->name)) { + addTask(prepareDependencyTask(dep, provider->name, level - 1)); + } + }; + + auto version = provider->api->getDependencyVersion(std::move(args), std::move(callbacks)); + tasks->addTask(version); + return tasks; +}; diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index 7f7e1fb1..d83d6e27 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -18,48 +18,64 @@ #pragma once +#include +#include #include #include +#include #include +#include #include "minecraft/mod/MetadataHandler.h" -#include "minecraft/mod/tasks/LocalModGetAllTask.h" +#include "minecraft/mod/ModFolderModel.h" #include "modplatform/ModIndex.h" +#include "modplatform/ResourceAPI.h" #include "tasks/SequentialTask.h" #include "tasks/Task.h" +#include "ui/pages/modplatform/ModModel.h" -class GetModDependenciesTask : public Task { +class GetModDependenciesTask : public SequentialTask { Q_OBJECT public: using Ptr = shared_qobject_ptr; - using LocalModGetAllTaskPtr = shared_qobject_ptr; - using NewDependecyVersionAPITask = - std::function)>; + struct PackDependecny { + ModPlatform::Dependency dependency; + ModPlatform::IndexedPack pack; + ModPlatform::IndexedVersion version; + PackDependecny(){}; + PackDependecny(const ModPlatform::IndexedPack& p, const ModPlatform::IndexedVersion& v) + { + pack = p; + version = v; + } + }; - explicit GetModDependenciesTask(QDir index_dir, QList selected, NewDependecyVersionAPITask api); + struct Provider { + ModPlatform::ResourceProvider name; + std::shared_ptr mod; + std::shared_ptr api; + }; - auto canAbort() const -> bool override { return true; } - auto abort() -> bool override; + explicit GetModDependenciesTask(QObject* parent, + BaseInstance* instance, + ModFolderModel* folder, + QList> selected); - auto getDependecies() const -> QList { return m_dependencies; } + auto getDependecies() const -> QList> { return m_pack_dependencies; } protected slots: - //! Entry point for tasks. - void executeTask() override; - - void prepareDependecies(); - void addDependecies(const ModPlatform::IndexedVersion&, int); - QList getDependenciesForVersions(const QList&); - QList getDependenciesForVersion(const ModPlatform::IndexedVersion&); + Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider, int); + QList getDependenciesForVersion(const ModPlatform::IndexedVersion&, + const ModPlatform::ResourceProvider providerName); + void prepare(); private: - QList m_selected; - QList m_dependencies; - QList m_mods; + QList> m_pack_dependencies; + QList> m_mods; + QList> m_selected; + QList m_providers; - LocalModGetAllTaskPtr m_getAllMods = nullptr; - NewDependecyVersionAPITask m_getDependenciesVersionAPI; - SequentialTask::Ptr m_getNetworkDep; - QEventLoop loop; + Version m_version; + ResourceAPI::ModLoaderTypes m_loaderType; }; diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp b/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp deleted file mode 100644 index 67058807..00000000 --- a/launcher/minecraft/mod/tasks/LocalModGetAllTask.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * PolyMC - Minecraft Launcher - * Copyright (c) 2022 flowln - * Copyright (C) 2022 Sefa Eyeoglu - * - * 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 . - */ - -#include "LocalModGetAllTask.h" - -#include "FileSystem.h" -#include "minecraft/mod/MetadataHandler.h" - -#ifdef Q_OS_WIN32 -#include -#endif - -LocalModGetAllTask::LocalModGetAllTask(QDir index_dir) : m_index_dir(index_dir) -{ - // Ensure a '.index' folder exists in the mods folder, and create it if it does not - if (!FS::ensureFolderPathExists(index_dir.path())) { - emitFailed(QString("Unable to create index for all mods!")); - } - -#ifdef Q_OS_WIN32 - SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); -#endif -} - -void LocalModGetAllTask::executeTask() -{ - setStatus(tr("Geting all mods")); - emit getAllMods(Metadata::getAll(m_index_dir)); - emitSucceeded(); -} - -auto LocalModGetAllTask::abort() -> bool -{ - emitAborted(); - return true; -} diff --git a/launcher/minecraft/mod/tasks/LocalModGetAllTask.h b/launcher/minecraft/mod/tasks/LocalModGetAllTask.h deleted file mode 100644 index bf4b78b7..00000000 --- a/launcher/minecraft/mod/tasks/LocalModGetAllTask.h +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * PolyMC - Minecraft Launcher - * Copyright (c) 2022 flowln - * - * 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 . - */ - -#pragma once - -#include - -#include "minecraft/mod/MetadataHandler.h" -#include "tasks/Task.h" - -class LocalModGetAllTask : public Task { - Q_OBJECT - public: - using Ptr = shared_qobject_ptr; - - explicit LocalModGetAllTask(QDir index_dir); - - auto canAbort() const -> bool override { return true; } - auto abort() -> bool override; - - protected slots: - //! Entry point for tasks. - void executeTask() override; - - signals: - void getAllMods(QList); - - private: - QDir m_index_dir; -}; diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 610f2449..03466bba 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -23,8 +23,10 @@ #include #include +#include #include "Application.h" +#include "QObjectPtr.h" #include "ResourceDownloadTask.h" #include "minecraft/mod/ModFolderModel.h" @@ -32,7 +34,10 @@ #include "minecraft/mod/ShaderPackFolderModel.h" #include "minecraft/mod/TexturePackFolderModel.h" +#include "minecraft/mod/tasks/GetModDependenciesTask.h" #include "modplatform/ModIndex.h" +#include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/ProgressDialog.h" #include "ui/dialogs/ReviewMessageBox.h" #include "ui/pages/modplatform/ResourcePage.h" @@ -122,30 +127,38 @@ void ResourceDownloadDialog::connectButtons() void ResourceDownloadDialog::confirm() { - auto keys = m_selected.keys(); - keys.sort(Qt::CaseInsensitive); - auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString())); confirm_dialog->retranslateUi(resourcesString()); - if (auto model = dynamic_cast(getBaseModel().get()); model) { - QList selectedVers; - for (auto& task : keys) { - auto selected = m_selected.constFind(task).value(); - selectedVers.append(selected->getVersion()); - } - - auto dir = model->indexDir(); - auto dependencies = m_selectedPage->getDependecies(dir, selectedVers); - - for (auto dep : dependencies) { - dep.is_currently_selected = true; - auto pack = ModPlatform::IndexedPack{ dep.addonId, ModPlatform::ResourceProvider::FLAME, dep.fileName, dep.fileName }; - m_selected.insert(dep.fileName, makeShared(pack, dep, getBaseModel(), true)); - } - - keys = m_selected.keys(); + if (auto task = getModDependenciesTask(); task) { + connect(task.get(), &Task::failed, this, + [&](QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->exec(); }); + + connect(task.get(), &Task::succeeded, this, [&]() { + QStringList warnings = task->warnings(); + if (warnings.count()) { + CustomMessageBox::selectable(this, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->exec(); + } + }); + + // Check for updates + ProgressDialog progress_dialog(this); + progress_dialog.setSkipButton(true, tr("Abort")); + progress_dialog.setWindowTitle(tr("Checking for dependencies...")); + auto ret = progress_dialog.execWithTask(task.get()); + + // If the dialog was skipped / some download error happened + if (ret == QDialog::DialogCode::Rejected) { + QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection); + return; + } else + for (auto dep : task->getDependecies()) { + addResource(dep->pack, dep->version, true); + } } + + auto keys = m_selected.keys(); + keys.sort(Qt::CaseInsensitive); for (auto& task : keys) { auto selected = m_selected.constFind(task).value(); confirm_dialog->appendResource({ task, selected->getFilename(), selected->getCustomPath() }); @@ -173,6 +186,7 @@ ResourcePage* ResourceDownloadDialog::getSelectedPage() void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, bool is_indexed) { + qWarning() << "DebugName: " << pack.name; removeResource(pack, ver); ver.is_currently_selected = true; @@ -256,6 +270,21 @@ QList ModDownloadDialog::getPages() return pages; } +GetModDependenciesTask::Ptr ModDownloadDialog::getModDependenciesTask() +{ + if (auto model = dynamic_cast(getBaseModel().get()); model) { + auto keys = m_selected.keys(); + QList> selectedVers; + for (auto& task : keys) { + auto selected = m_selected.constFind(task).value(); + selectedVers.append(std::make_shared(selected->getPack(), selected->getVersion())); + } + + return makeShared(this, m_instance, model, selectedVers); + } + return nullptr; +}; + ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent, const std::shared_ptr& resource_packs, BaseInstance* instance) diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index 5678dc8b..f498df01 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -25,7 +25,9 @@ #include #include "QObjectPtr.h" +#include "minecraft/mod/tasks/GetModDependenciesTask.h" #include "modplatform/ModIndex.h" +#include "tasks/Task.h" #include "ui/pages/BasePageProvider.h" class BaseInstance; @@ -80,6 +82,8 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { protected: [[nodiscard]] virtual QString geometrySaveKey() const { return ""; } + [[nodiscard]] virtual GetModDependenciesTask::Ptr getModDependenciesTask() { return nullptr; } + protected: const std::shared_ptr m_base_model; @@ -92,8 +96,6 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { QHash m_selected; }; - - class ModDownloadDialog final : public ResourceDownloadDialog { Q_OBJECT @@ -106,6 +108,7 @@ class ModDownloadDialog final : public ResourceDownloadDialog { [[nodiscard]] QString geometrySaveKey() const override { return "ModDownloadGeometry"; } QList getPages() override; + GetModDependenciesTask::Ptr getModDependenciesTask() override; private: BaseInstance* m_instance; @@ -135,8 +138,8 @@ class TexturePackDownloadDialog final : public ResourceDownloadDialog { public: explicit TexturePackDownloadDialog(QWidget* parent, - const std::shared_ptr& resource_packs, - BaseInstance* instance); + const std::shared_ptr& resource_packs, + BaseInstance* instance); ~TexturePackDownloadDialog() override = default; //: String that gets appended to the texture pack download dialog title ("Download " + resourcesString()) @@ -153,9 +156,7 @@ class ShaderPackDownloadDialog final : public ResourceDownloadDialog { Q_OBJECT public: - explicit ShaderPackDownloadDialog(QWidget* parent, - const std::shared_ptr& shader_packs, - BaseInstance* instance); + explicit ShaderPackDownloadDialog(QWidget* parent, const std::shared_ptr& shader_packs, BaseInstance* instance); ~ShaderPackDownloadDialog() override = default; //: String that gets appended to the shader pack download dialog title ("Download " + resourcesString()) diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index c1746d41..97b9efa9 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -449,46 +449,4 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe emit projectInfoUpdated(); } -QList ResourceModel::getDependecies(QDir& dir, QList selected) -{ - auto task = std::make_unique( - dir, selected, - [this](const ModPlatform::Dependency& dependency, std::function succeeded) -> Task::Ptr { - auto args{ createDependecyArguments(dependency) }; - auto callbacks{ createDependecyCallbacks() }; - - // Use default if no callbacks are set - if (!callbacks.on_succeed) - callbacks.on_succeed = [this, dependency, succeeded](auto& doc, auto& pack) { - ModPlatform::IndexedVersion ver; - try { - QJsonArray arr; - if (dependency.version.length() != 0 && doc.isObject()) { - arr.append(doc.object()); - } else { - arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); - } - ver = loadDependencyVersions(dependency, arr); - if (!ver.addonId.isValid()) { - qWarning() << "Error while reading " << debugName() << " resource version empty "; - qDebug() << doc; - return; - } - } catch (const JSONValidationError& e) { - qDebug() << doc; - qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause(); - return; - } - - succeeded(ver); - }; - - return m_api->getDependencyVersion(std::move(args), std::move(callbacks)); - }); - - task->start(); - - return task->getDependecies(); -}; - } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 3b1f4748..3ea567af 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -85,8 +85,6 @@ class ResourceModel : public QAbstractListModel { /** Gets the icon at the URL for the given index. If it's not fetched yet, fetch it and update when fisinhed. */ std::optional getIcon(QModelIndex&, const QUrl&); - QList getDependecies(QDir& dir, QList m_selected); - protected: /** Resets the model's data. */ void clearData(); diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 02412fd9..1baa24ee 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -405,9 +405,4 @@ void ResourcePage::openUrl(const QUrl& url) QDesktopServices::openUrl(url); } -QList ResourcePage::getDependecies(QDir& dir, QList selected) -{ - return m_model->getDependecies(dir, selected); -}; - } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index 4fffd506..a8299728 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -75,8 +75,6 @@ class ResourcePage : public QWidget, public BasePage { virtual void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); virtual void removeResourceFromDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); - QList getDependecies(QDir& dir, QList m_selected); - protected slots: virtual void triggerSearch() {} -- cgit From ffaa47bf54bc5b320049064a897c8ad0737574ee Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 20 Apr 2023 22:35:10 +0300 Subject: Small cleanup Signed-off-by: Trial97 --- launcher/minecraft/mod/MetadataHandler.h | 2 - .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 36 +++++++------- .../minecraft/mod/tasks/GetModDependenciesTask.h | 6 +-- launcher/modplatform/packwiz/Packwiz.cpp | 11 ----- launcher/modplatform/packwiz/Packwiz.h | 57 ++++++++++------------ launcher/ui/dialogs/ResourceDownloadDialog.cpp | 1 - launcher/ui/dialogs/ResourceDownloadDialog.h | 1 - launcher/ui/pages/modplatform/ModModel.cpp | 16 +----- launcher/ui/pages/modplatform/ModModel.h | 3 +- launcher/ui/pages/modplatform/ResourceModel.cpp | 5 -- launcher/ui/pages/modplatform/ResourceModel.h | 4 -- launcher/ui/pages/modplatform/ResourcePackModel.h | 1 - launcher/ui/pages/modplatform/ResourcePage.cpp | 3 ++ launcher/ui/pages/modplatform/ResourcePage.h | 4 +- launcher/ui/pages/modplatform/ShaderPackModel.h | 1 - .../modplatform/flame/FlameResourceModels.cpp | 10 ---- .../pages/modplatform/flame/FlameResourceModels.h | 2 - .../modrinth/ModrinthResourceModels.cpp | 15 ------ .../modplatform/modrinth/ModrinthResourceModels.h | 3 -- 19 files changed, 54 insertions(+), 127 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h index f7f08a79..ea9078e0 100644 --- a/launcher/minecraft/mod/MetadataHandler.h +++ b/launcher/minecraft/mod/MetadataHandler.h @@ -51,6 +51,4 @@ class Metadata { static auto get(QDir& index_dir, QString mod_slug) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_slug); } static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_id); } - - static auto getAll(QDir& index_dir) -> QList { return Packwiz::V1::getAllMods(index_dir); } }; diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 966eea19..e1760f16 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -48,12 +48,15 @@ GetModDependenciesTask::GetModDependenciesTask(QObject* parent, BaseInstance* instance, ModFolderModel* folder, QList> selected) - : SequentialTask(parent, "Get dependencies"), m_selected(selected), m_version(mcVersions(instance)), m_loaderType(mcLoaders(instance)) + : SequentialTask(parent, "Get dependencies") + , m_selected(selected) + , m_flame_provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared(*instance), + std::make_shared() } + , m_modrinth_provider{ ModPlatform::ResourceProvider::MODRINTH, std::make_shared(*instance), + std::make_shared() } + , m_version(mcVersions(instance)) + , m_loaderType(mcLoaders(instance)) { - m_providers.append(Provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared(*instance), - std::make_shared() }); - m_providers.append(Provider{ ModPlatform::ResourceProvider::MODRINTH, std::make_shared(*instance), - std::make_shared() }); for (auto mod : folder->allMods()) m_mods.append(mod->metadata()); prepare(); @@ -104,17 +107,12 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen pDep->dependency = dep; pDep->pack = { dep.addonId, providerName }; m_pack_dependencies.append(pDep); - auto provider = - std::find_if(m_providers.begin(), m_providers.end(), [providerName](const Provider& p) { return p.name == providerName; }); - // if (provider == m_providers.end()) { - // qWarning() << "Unsuported provider for dependency check"; - // return nullptr; - // } + auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider; auto tasks = makeShared(this, QString("DependencyInfo: %1").arg(dep.addonId.toString())); auto responseInfo = new QByteArray(); - auto info = provider->api->getProject(dep.addonId.toString(), responseInfo); + auto info = provider.api->getProject(dep.addonId.toString(), responseInfo); QObject::connect(info.get(), &NetJob::succeeded, [responseInfo, provider, pDep] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*responseInfo, &parse_error); @@ -125,9 +123,9 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen return; } try { - auto obj = provider->name == ModPlatform::ResourceProvider::FLAME ? Json::requireObject(Json::requireObject(doc), "data") - : Json::requireObject(doc); - provider->mod->loadIndexedPack(pDep->pack, obj); + auto obj = provider.name == ModPlatform::ResourceProvider::FLAME ? Json::requireObject(Json::requireObject(doc), "data") + : Json::requireObject(doc); + provider.mod->loadIndexedPack(pDep->pack, obj); } catch (const JSONValidationError& e) { qDebug() << doc; qWarning() << "Error while reading mod info: " << e.cause(); @@ -146,7 +144,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen } else { arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); } - pDep->version = provider->mod->loadDependencyVersions(dep, arr); + pDep->version = provider.mod->loadDependencyVersions(dep, arr); if (!pDep->version.addonId.isValid()) { qWarning() << "Error while reading mod version empty "; qDebug() << doc; @@ -164,12 +162,12 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen qWarning() << "Dependency cycle exeeded"; return; } - for (auto dep : getDependenciesForVersion(pDep->version, provider->name)) { - addTask(prepareDependencyTask(dep, provider->name, level - 1)); + for (auto dep : getDependenciesForVersion(pDep->version, provider.name)) { + addTask(prepareDependencyTask(dep, provider.name, level - 1)); } }; - auto version = provider->api->getDependencyVersion(std::move(args), std::move(callbacks)); + auto version = provider.api->getDependencyVersion(std::move(args), std::move(callbacks)); tasks->addTask(version); return tasks; }; diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index d83d6e27..40f80ebf 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -18,11 +18,10 @@ #pragma once -#include -#include #include #include #include +#include #include #include @@ -74,7 +73,8 @@ class GetModDependenciesTask : public SequentialTask { QList> m_pack_dependencies; QList> m_mods; QList> m_selected; - QList m_providers; + Provider m_flame_provider; + Provider m_modrinth_provider; Version m_version; ResourceAPI::ModLoaderTypes m_loaderType; diff --git a/launcher/modplatform/packwiz/Packwiz.cpp b/launcher/modplatform/packwiz/Packwiz.cpp index 33b5f364..510c7309 100644 --- a/launcher/modplatform/packwiz/Packwiz.cpp +++ b/launcher/modplatform/packwiz/Packwiz.cpp @@ -21,8 +21,6 @@ #include #include #include -#include -#include #include "FileSystem.h" #include "StringUtils.h" @@ -313,13 +311,4 @@ auto V1::getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod return {}; } -auto V1::getAllMods(QDir& index_dir) -> QList -{ - auto files = index_dir.entryList(QDir::Filter::Files); - auto mods = QList(); - std::transform(files.begin(), files.end(), std::back_inserter(mods), - [&index_dir](auto file_name) { return getIndexForMod(index_dir, file_name); }); - return mods; -} - } // namespace Packwiz diff --git a/launcher/modplatform/packwiz/Packwiz.h b/launcher/modplatform/packwiz/Packwiz.h index 2801f5d0..4b096eec 100644 --- a/launcher/modplatform/packwiz/Packwiz.h +++ b/launcher/modplatform/packwiz/Packwiz.h @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher - * Copyright (c) 2022 flowln - * - * 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 . - */ +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ #pragma once @@ -36,22 +36,22 @@ auto getRealIndexName(QDir& index_dir, QString normalized_index_name, bool shoul class V1 { public: struct Mod { - QString slug{}; - QString name{}; - QString filename{}; + QString slug {}; + QString name {}; + QString filename {}; // FIXME: make side an enum - QString side{ "both" }; + QString side {"both"}; // [download] - QString mode{}; - QUrl url{}; - QString hash_format{}; - QString hash{}; + QString mode {}; + QUrl url {}; + QString hash_format {}; + QString hash {}; // [update] - ModPlatform::ResourceProvider provider{}; - QVariant file_id{}; - QVariant project_id{}; + ModPlatform::ResourceProvider provider {}; + QVariant file_id {}; + QVariant project_id {}; public: // This is a totally heuristic, but should work for now. @@ -93,9 +93,6 @@ class V1 { * If the mod doesn't have a metadata, it simply returns an empty Mod object. * */ static auto getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod; - - /* Gets the metadata for all the mods */ - static auto getAllMods(QDir& index_dir) -> QList; }; -} // namespace Packwiz +} // namespace Packwiz diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 03466bba..dc1d927e 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -26,7 +26,6 @@ #include #include "Application.h" -#include "QObjectPtr.h" #include "ResourceDownloadTask.h" #include "minecraft/mod/ModFolderModel.h" diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index f498df01..9610c8b3 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -27,7 +27,6 @@ #include "QObjectPtr.h" #include "minecraft/mod/tasks/GetModDependenciesTask.h" #include "modplatform/ModIndex.h" -#include "tasks/Task.h" #include "ui/pages/BasePageProvider.h" class BaseInstance; diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index 19c20e65..3ffe6cb0 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -24,7 +24,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments() std::optional> versions{}; - { // Version filter + { // Version filter if (!m_filter->versions.empty()) versions = m_filter->versions; } @@ -49,20 +49,6 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en return { pack, versions, profile->getModLoaders() }; } -ResourceAPI::DependencySearchArgs ModModel::createDependecyArguments(const ModPlatform::Dependency& dep) -{ - auto profile = static_cast(m_base_instance).getPackProfile(); - - Q_ASSERT(profile); - Q_ASSERT(m_filter); - - std::optional> versions{}; - if (!m_filter->versions.empty()) - versions = m_filter->versions; - - return { dep, versions->front(), profile->getModLoaders().value() }; -}; - ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry) { auto& pack = m_packs[entry.row()]; diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index 59b27dda..f7563171 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -32,7 +32,7 @@ class ModModel : public ResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override = 0; - ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) override = 0; + virtual ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) = 0; void setFilter(std::shared_ptr filter) { m_filter = filter; } @@ -40,7 +40,6 @@ class ModModel : public ResourceModel { ResourceAPI::SearchArgs createSearchArguments() override; ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override; ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) override; - ResourceAPI::DependencySearchArgs createDependecyArguments(const ModPlatform::Dependency&) override; protected: auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0; diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 97b9efa9..b1e936f8 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -324,11 +324,6 @@ void ResourceModel::loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArra { NEED_FOR_CALLBACK_ASSERT("loadIndexedPackVersions"); } -ModPlatform::IndexedVersion ResourceModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -{ - NEED_FOR_CALLBACK_ASSERT("loadDependencyVersions"); - return {}; -} /* Default callbacks */ diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 3ea567af..c0844589 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -70,9 +70,6 @@ class ResourceModel : public QAbstractListModel { virtual ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) = 0; virtual ResourceAPI::ProjectInfoCallbacks createInfoCallbacks(QModelIndex&) { return {}; } - virtual ResourceAPI::DependencySearchArgs createDependecyArguments(const ModPlatform::Dependency&) { return {}; }; - virtual ResourceAPI::DependencySearchCallbacks createDependecyCallbacks() { return {}; } - /** Requests the API for more entries. */ virtual void search(); @@ -109,7 +106,6 @@ class ResourceModel : public QAbstractListModel { virtual void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&); virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&); virtual void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&); - virtual ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr); protected: /* Basic search parameters */ diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.h b/launcher/ui/pages/modplatform/ResourcePackModel.h index 8ff4d8a2..e2b4a195 100644 --- a/launcher/ui/pages/modplatform/ResourcePackModel.h +++ b/launcher/ui/pages/modplatform/ResourcePackModel.h @@ -28,7 +28,6 @@ class ResourcePackResourceModel : public ResourceModel { void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0; void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0; void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0; - ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) override = 0; public slots: ResourceAPI::SearchArgs createSearchArguments() override; diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 1baa24ee..bbd465bc 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -43,6 +43,9 @@ #include #include "Markdown.h" +#include "ResourceDownloadTask.h" + +#include "minecraft/MinecraftInstance.h" #include "ui/dialogs/ResourceDownloadDialog.h" #include "ui/pages/modplatform/ResourceModel.h" diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index a8299728..1896d53e 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -4,11 +4,11 @@ #pragma once -#include #include #include #include "modplatform/ModIndex.h" +#include "modplatform/ResourceAPI.h" #include "ui/pages/BasePage.h" #include "ui/widgets/ProgressWidget.h" @@ -77,7 +77,7 @@ class ResourcePage : public QWidget, public BasePage { protected slots: virtual void triggerSearch() {} - + void onSelectionChanged(QModelIndex first, QModelIndex second); void onVersionSelectionChanged(QString data); void onResourceSelected(); diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.h b/launcher/ui/pages/modplatform/ShaderPackModel.h index 17a07aa4..f3c695e9 100644 --- a/launcher/ui/pages/modplatform/ShaderPackModel.h +++ b/launcher/ui/pages/modplatform/ShaderPackModel.h @@ -28,7 +28,6 @@ class ShaderPackResourceModel : public ResourceModel { void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&) override = 0; void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&) override = 0; void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&) override = 0; - ModPlatform::IndexedVersion loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) override = 0; public slots: ResourceAPI::SearchArgs createSearchArguments() override; diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp index 08bf22fe..b233a845 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp @@ -57,11 +57,6 @@ void FlameResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } -auto FlameResourcePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion -{ - return FlameMod::loadDependencyVersions(m, arr); -}; - auto FlameResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray { return Json::ensureArray(obj.object(), "data"); @@ -98,11 +93,6 @@ void FlameTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m, m.versions = filtered_versions; } -auto FlameTexturePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion -{ - return FlameMod::loadDependencyVersions(m, arr); -}; - ResourceAPI::SearchArgs FlameTexturePackModel::createSearchArguments() { auto args = TexturePackResourceModel::createSearchArguments(); diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h index 7871d9aa..f3ef918a 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h @@ -43,7 +43,6 @@ class FlameResourcePackModel : public ResourcePackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -62,7 +61,6 @@ class FlameTexturePackModel : public TexturePackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; ResourceAPI::SearchArgs createSearchArguments() override; ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override; diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp index 53be2d2c..e9f09387 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp @@ -69,11 +69,6 @@ void ModrinthResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } -auto ModrinthResourcePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion -{ - return ::Modrinth::loadDependencyVersions(m, arr); -}; - auto ModrinthResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray { return obj.object().value("hits").toArray(); @@ -96,11 +91,6 @@ void ModrinthTexturePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } -auto ModrinthTexturePackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion -{ - return ::Modrinth::loadDependencyVersions(m, arr); -}; - auto ModrinthTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray { return obj.object().value("hits").toArray(); @@ -123,11 +113,6 @@ void ModrinthShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& ::Modrinth::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); } -auto ModrinthShaderPackModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion -{ - return ::Modrinth::loadDependencyVersions(m, arr); -}; - auto ModrinthShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray { return obj.object().value("hits").toArray(); diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h index 0045fe86..6cd19c41 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h @@ -59,7 +59,6 @@ class ModrinthResourcePackModel : public ResourcePackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -78,7 +77,6 @@ class ModrinthTexturePackModel : public TexturePackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; @@ -97,7 +95,6 @@ class ModrinthShaderPackModel : public ShaderPackResourceModel { void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override; void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override; - auto loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion override; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override; }; -- cgit From 2c744da9f7352073e744015a4c1da42794bcd004 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 20 Apr 2023 22:51:20 +0300 Subject: More cleanup Signed-off-by: Trial97 --- launcher/minecraft/mod/MetadataHandler.h | 55 ++++++++++++++++--------- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 1 - launcher/ui/pages/modplatform/ResourceModel.cpp | 3 -- launcher/ui/pages/modplatform/ResourceModel.h | 2 - 4 files changed, 35 insertions(+), 26 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/MetadataHandler.h b/launcher/minecraft/mod/MetadataHandler.h index ea9078e0..39723b49 100644 --- a/launcher/minecraft/mod/MetadataHandler.h +++ b/launcher/minecraft/mod/MetadataHandler.h @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher - * Copyright (c) 2022 flowln - * - * 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 . - */ +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ #pragma once @@ -42,13 +42,28 @@ class Metadata { return Packwiz::V1::createModFormat(index_dir, internal_mod, mod_slug); } - static void update(QDir& index_dir, ModStruct& mod) { Packwiz::V1::updateModIndex(index_dir, mod); } + static void update(QDir& index_dir, ModStruct& mod) + { + Packwiz::V1::updateModIndex(index_dir, mod); + } - static void remove(QDir& index_dir, QString mod_slug) { Packwiz::V1::deleteModIndex(index_dir, mod_slug); } + static void remove(QDir& index_dir, QString mod_slug) + { + Packwiz::V1::deleteModIndex(index_dir, mod_slug); + } - static void remove(QDir& index_dir, QVariant& mod_id) { Packwiz::V1::deleteModIndex(index_dir, mod_id); } + static void remove(QDir& index_dir, QVariant& mod_id) + { + Packwiz::V1::deleteModIndex(index_dir, mod_id); + } - static auto get(QDir& index_dir, QString mod_slug) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_slug); } + static auto get(QDir& index_dir, QString mod_slug) -> ModStruct + { + return Packwiz::V1::getIndexForMod(index_dir, mod_slug); + } - static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct { return Packwiz::V1::getIndexForMod(index_dir, mod_id); } + static auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct + { + return Packwiz::V1::getIndexForMod(index_dir, mod_id); + } }; diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index dc1d927e..38c57361 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -185,7 +185,6 @@ ResourcePage* ResourceDownloadDialog::getSelectedPage() void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, bool is_indexed) { - qWarning() << "DebugName: " << pack.name; removeResource(pack, ver); ver.is_currently_selected = true; diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index b1e936f8..db7d26f8 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -3,8 +3,6 @@ // SPDX-License-Identifier: GPL-3.0-only #include "ResourceModel.h" -#include -#include #include #include @@ -16,7 +14,6 @@ #include "BuildConfig.h" #include "Json.h" -#include "minecraft/mod/tasks/GetModDependenciesTask.h" #include "net/Download.h" #include "net/NetJob.h" diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index c0844589..46a02d6e 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -4,14 +4,12 @@ #pragma once -#include #include #include #include "QObjectPtr.h" -#include "modplatform/ModIndex.h" #include "modplatform/ResourceAPI.h" #include "tasks/ConcurrentTask.h" -- cgit From b4fa6e120a98fde89443b262f351412f36de7566 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 21 Apr 2023 18:41:40 +0300 Subject: Fixed tipo Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameAPI.h | 2 +- launcher/modplatform/helpers/NetworkResourceAPI.cpp | 4 ++-- launcher/modplatform/helpers/NetworkResourceAPI.h | 2 +- launcher/modplatform/modrinth/ModrinthAPI.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 91993e64..3b4af952 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -85,7 +85,7 @@ class FlameAPI : public NetworkResourceAPI { return url + get_parameters.join('&'); }; - [[nodiscard]] std::optional getDependecyURL(DependencySearchArgs const& args) const override + [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override { return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2&modLoaderType=%") .arg(args.dependency.addonId.toString()) diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp index a7f763d3..9f95cde4 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp +++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp @@ -123,13 +123,13 @@ Task::Ptr NetworkResourceAPI::getProject(QString addonId, QByteArray* response) Task::Ptr NetworkResourceAPI::getDependencyVersion(DependencySearchArgs&& args, DependencySearchCallbacks&& callbacks) const { - auto versions_url_optional = getDependecyURL(args); + auto versions_url_optional = getDependencyURL(args); if (!versions_url_optional.has_value()) return nullptr; auto versions_url = versions_url_optional.value(); - auto netJob = makeShared(QString("%1::Dependecy").arg(args.dependency.addonId.toString()), APPLICATION->network()); + auto netJob = makeShared(QString("%1::Dependency").arg(args.dependency.addonId.toString()), APPLICATION->network()); auto response = new QByteArray(); netJob->addNetAction(Net::Download::makeByteArray(versions_url, response)); diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.h b/launcher/modplatform/helpers/NetworkResourceAPI.h index bbe0a2c7..93865713 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.h +++ b/launcher/modplatform/helpers/NetworkResourceAPI.h @@ -20,5 +20,5 @@ class NetworkResourceAPI : public ResourceAPI { [[nodiscard]] virtual auto getSearchURL(SearchArgs const& args) const -> std::optional = 0; [[nodiscard]] virtual auto getInfoURL(QString const& id) const -> std::optional = 0; [[nodiscard]] virtual auto getVersionsURL(VersionSearchArgs const& args) const -> std::optional = 0; - [[nodiscard]] virtual auto getDependecyURL(DependencySearchArgs const& args) const -> std::optional = 0; + [[nodiscard]] virtual auto getDependencyURL(DependencySearchArgs const& args) const -> std::optional = 0; }; diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 2d6049ba..07c8cf2a 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -143,7 +143,7 @@ class ModrinthAPI : public NetworkResourceAPI { inline auto validateModLoaders(ModLoaderTypes loaders) const -> bool { return loaders & (Forge | Fabric | Quilt); } - [[nodiscard]] std::optional getDependecyURL(DependencySearchArgs const& args) const override + [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override { return args.dependency.version.length() != 0 ? QString("%1/version/%2").arg(BuildConfig.MODRINTH_PROD_URL, args.dependency.version) : QString("%1/project/%2/version?game_versions=[\"%1\"]&loaders=[\"%1\"]") -- cgit From 42bc91463e8dc7c078476c8606937552ce623c62 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 21 Apr 2023 20:37:17 +0300 Subject: Updated links Signed-off-by: Trial97 --- launcher/ResourceDownloadTask.h | 3 ++- launcher/modplatform/flame/FlameAPI.h | 2 +- launcher/modplatform/modrinth/ModrinthAPI.h | 2 +- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 12 ++++++++---- launcher/ui/dialogs/ReviewMessageBox.cpp | 12 ++++++++++-- launcher/ui/dialogs/ReviewMessageBox.h | 7 ++++--- 6 files changed, 26 insertions(+), 12 deletions(-) (limited to 'launcher') diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h index 29d3ae0a..a12c05b8 100644 --- a/launcher/ResourceDownloadTask.h +++ b/launcher/ResourceDownloadTask.h @@ -38,7 +38,8 @@ class ResourceDownloadTask : public SequentialTask { const QString& getCustomPath() const { return m_pack_version.custom_target_folder; } const QVariant& getVersionID() const { return m_pack_version.fileId; } const ModPlatform::IndexedVersion& getVersion() const { return m_pack_version; } - const ModPlatform::IndexedPack& getPack() const { return m_pack; } + ModPlatform::IndexedPack& getPack() { return m_pack; } + const ModPlatform::ResourceProvider& getProvider() const { return m_pack.provider; } private: ModPlatform::IndexedPack m_pack; diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 3b4af952..4ffc36d2 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -87,7 +87,7 @@ class FlameAPI : public NetworkResourceAPI { [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override { - return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2&modLoaderType=%") + return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2&modLoaderType=%3") .arg(args.dependency.addonId.toString()) .arg(args.mcVersion.toString()) .arg(getMappedModLoader(args.loader)); diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 07c8cf2a..95722ccb 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -146,7 +146,7 @@ class ModrinthAPI : public NetworkResourceAPI { [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override { return args.dependency.version.length() != 0 ? QString("%1/version/%2").arg(BuildConfig.MODRINTH_PROD_URL, args.dependency.version) - : QString("%1/project/%2/version?game_versions=[\"%1\"]&loaders=[\"%1\"]") + : QString("%1/project/%2/version?game_versions=[\"%3\"]&loaders=[\"%4\"]") .arg(BuildConfig.MODRINTH_PROD_URL) .arg(args.dependency.addonId.toString()) .arg(args.mcVersion.toString()) diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 38c57361..c16dcca7 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -124,6 +124,8 @@ void ResourceDownloadDialog::connectButtons() connect(HelpButton, &QPushButton::clicked, m_container, &PageContainer::help); } +static ModPlatform::ProviderCapabilities ProviderCaps; + void ResourceDownloadDialog::confirm() { auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString())); @@ -160,7 +162,8 @@ void ResourceDownloadDialog::confirm() keys.sort(Qt::CaseInsensitive); for (auto& task : keys) { auto selected = m_selected.constFind(task).value(); - confirm_dialog->appendResource({ task, selected->getFilename(), selected->getCustomPath() }); + confirm_dialog->appendResource( + { task, selected->getFilename(), selected->getCustomPath(), ProviderCaps.name(selected->getProvider()) }); } if (confirm_dialog->exec()) { @@ -206,9 +209,10 @@ void ResourceDownloadDialog::removeResource(ModPlatform::IndexedPack& pack, ModP if (auto selected_task_it = m_selected.find(pack.name); selected_task_it != m_selected.end()) { auto selected_task = *selected_task_it; auto old_version_id = selected_task->getVersionID(); - - // If the new and old version IDs don't match, search for the old one and deselect it. - if (ver.fileId != old_version_id) + if (selected_task->getProvider() != pack.provider) // If the pack name matches but they are different providers search for the + // old one(in the actual pack) and deselect it. + getVersionWithID(selected_task->getPack(), old_version_id).is_currently_selected = false; + else if (ver.fileId != old_version_id) // If the new and old version IDs don't match, search for the old one and deselect it. getVersionWithID(pack, old_version_id).is_currently_selected = false; } diff --git a/launcher/ui/dialogs/ReviewMessageBox.cpp b/launcher/ui/dialogs/ReviewMessageBox.cpp index 7b2df278..86e68aae 100644 --- a/launcher/ui/dialogs/ReviewMessageBox.cpp +++ b/launcher/ui/dialogs/ReviewMessageBox.cpp @@ -40,7 +40,8 @@ void ReviewMessageBox::appendResource(ResourceInformation&& info) auto filenameItem = new QTreeWidgetItem(itemTop); filenameItem->setText(0, tr("Filename: %1").arg(info.filename)); - itemTop->insertChildren(0, { filenameItem }); + auto childIndx = 0; + itemTop->insertChildren(childIndx++, { filenameItem }); if (!info.custom_file_path.isEmpty()) { auto customPathItem = new QTreeWidgetItem(itemTop); @@ -49,9 +50,16 @@ void ReviewMessageBox::appendResource(ResourceInformation&& info) itemTop->insertChildren(1, { customPathItem }); itemTop->setIcon(1, QIcon(APPLICATION->getThemedIcon("status-yellow"))); - itemTop->setToolTip(1, tr("This file will be downloaded to a folder location different from the default, possibly due to its loader requiring it.")); + itemTop->setToolTip( + childIndx++, + tr("This file will be downloaded to a folder location different from the default, possibly due to its loader requiring it.")); } + auto providerItem = new QTreeWidgetItem(itemTop); + providerItem->setText(0, tr("Provider: %1").arg(info.provider)); + + itemTop->insertChildren(childIndx++, { providerItem }); + ui->modTreeWidget->addTopLevelItem(itemTop); } diff --git a/launcher/ui/dialogs/ReviewMessageBox.h b/launcher/ui/dialogs/ReviewMessageBox.h index 5ec2bc23..9579da33 100644 --- a/launcher/ui/dialogs/ReviewMessageBox.h +++ b/launcher/ui/dialogs/ReviewMessageBox.h @@ -13,9 +13,10 @@ class ReviewMessageBox : public QDialog { static auto create(QWidget* parent, QString&& title, QString&& icon = "") -> ReviewMessageBox*; using ResourceInformation = struct res_info { - QString name; - QString filename; - QString custom_file_path {}; + QString name; + QString filename; + QString custom_file_path{}; + QString provider; }; void appendResource(ResourceInformation&& info); -- cgit From 10aac4fe1721c3e1cf83bacefddc086918ca03da Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 21 Apr 2023 21:03:01 +0300 Subject: Fixed assert Signed-off-by: Trial97 --- launcher/ResourceDownloadTask.h | 52 +++++++++++++------------- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 21 ++++++----- 2 files changed, 38 insertions(+), 35 deletions(-) (limited to 'launcher') diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h index 73ad2d07..27c3c2ec 100644 --- a/launcher/ResourceDownloadTask.h +++ b/launcher/ResourceDownloadTask.h @@ -1,41 +1,46 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* Prism Launcher - Minecraft Launcher -* Copyright (c) 2022-2023 flowln -* Copyright (C) 2022 Sefa Eyeoglu -* -* 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 . -*/ + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022-2023 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * 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 . + */ #pragma once #include "net/NetJob.h" #include "tasks/SequentialTask.h" -#include "modplatform/ModIndex.h" #include "minecraft/mod/tasks/LocalModUpdateTask.h" +#include "modplatform/ModIndex.h" class ResourceFolderModel; class ResourceDownloadTask : public SequentialTask { Q_OBJECT -public: - explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, ModPlatform::IndexedVersion version, const std::shared_ptr packs, bool is_indexed = true); + public: + explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, + ModPlatform::IndexedVersion version, + const std::shared_ptr packs, + bool is_indexed = true); const QString& getFilename() const { return m_pack_version.fileName; } const QString& getCustomPath() const { return m_pack_version.custom_target_folder; } const QVariant& getVersionID() const { return m_pack_version.fileId; } + ModPlatform::IndexedPack& getPack() { return m_pack; } + const ModPlatform::ResourceProvider& getProvider() const { return m_pack.provider; } -private: + private: ModPlatform::IndexedPack m_pack; ModPlatform::IndexedVersion m_pack_version; const std::shared_ptr m_pack_model; @@ -47,11 +52,8 @@ private: void downloadFailed(QString reason); void downloadSucceeded(); - std::tuple to_delete {"", ""}; + std::tuple to_delete{ "", "" }; -private slots: + private slots: void hasOldResource(QString name, QString filename); }; - - - diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index edb7d063..7fb4a657 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -26,8 +26,8 @@ #include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ResourcePackFolderModel.h" -#include "minecraft/mod/TexturePackFolderModel.h" #include "minecraft/mod/ShaderPackFolderModel.h" +#include "minecraft/mod/TexturePackFolderModel.h" #include "ui/dialogs/ReviewMessageBox.h" @@ -41,7 +41,10 @@ namespace ResourceDownload { ResourceDownloadDialog::ResourceDownloadDialog(QWidget* parent, const std::shared_ptr base_model) - : QDialog(parent), m_base_model(base_model), m_buttons(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel), m_vertical_layout(this) + : QDialog(parent) + , m_base_model(base_model) + , m_buttons(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel) + , m_vertical_layout(this) { setObjectName(QStringLiteral("ResourceDownloadDialog")); @@ -102,7 +105,8 @@ void ResourceDownloadDialog::initializeContainer() void ResourceDownloadDialog::connectButtons() { auto OkButton = m_buttons.button(QDialogButtonBox::Ok); - OkButton->setToolTip(tr("Opens a new popup to review your selected %1 and confirm your selection. Shortcut: Ctrl+Return").arg(resourcesString())); + OkButton->setToolTip( + tr("Opens a new popup to review your selected %1 and confirm your selection. Shortcut: Ctrl+Return").arg(resourcesString())); connect(OkButton, &QPushButton::clicked, this, &ResourceDownloadDialog::confirm); auto CancelButton = m_buttons.button(QDialogButtonBox::Cancel); @@ -169,8 +173,10 @@ void ResourceDownloadDialog::removeResource(ModPlatform::IndexedPack& pack, ModP auto selected_task = *selected_task_it; auto old_version_id = selected_task->getVersionID(); - // If the new and old version IDs don't match, search for the old one and deselect it. - if (ver.fileId != old_version_id) + if (selected_task->getProvider() != pack.provider) // If the pack name matches but they are different providers search for the + // old one(in the actual pack) and deselect it. + getVersionWithID(selected_task->getPack(), old_version_id).is_currently_selected = false; + else if (ver.fileId != old_version_id) // If the new and old version IDs don't match, search for the old one and deselect it. getVersionWithID(pack, old_version_id).is_currently_selected = false; } @@ -205,8 +211,6 @@ void ResourceDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* s m_selectedPage->setSearchTerm(prev_page->getSearchTerm()); } - - ModDownloadDialog::ModDownloadDialog(QWidget* parent, const std::shared_ptr& mods, BaseInstance* instance) : ResourceDownloadDialog(parent, mods), m_instance(instance) { @@ -232,7 +236,6 @@ QList ModDownloadDialog::getPages() return pages; } - ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent, const std::shared_ptr& resource_packs, BaseInstance* instance) @@ -258,7 +261,6 @@ QList ResourcePackDownloadDialog::getPages() return pages; } - TexturePackDownloadDialog::TexturePackDownloadDialog(QWidget* parent, const std::shared_ptr& resource_packs, BaseInstance* instance) @@ -284,7 +286,6 @@ QList TexturePackDownloadDialog::getPages() return pages; } - ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent, const std::shared_ptr& shaders, BaseInstance* instance) -- cgit From f7931c2ee202025740caf424fa00ffb76743a1d2 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 22 Apr 2023 00:47:51 +0300 Subject: Better version handling Signed-off-by: Trial97 --- launcher/ResourceDownloadTask.h | 1 - launcher/modplatform/ModIndex.h | 37 +++++++++++++----------- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 20 ++----------- launcher/ui/pages/modplatform/ModModel.cpp | 16 ++++++++-- launcher/ui/pages/modplatform/ModPage.cpp | 18 +++++------- launcher/ui/pages/modplatform/ResourceModel.cpp | 30 +++++++++++++++++++ launcher/ui/pages/modplatform/ResourceModel.h | 4 +++ launcher/ui/pages/modplatform/ResourcePage.cpp | 6 ++++ launcher/ui/pages/modplatform/ResourcePage.h | 3 +- launcher/ui/pages/modplatform/ShaderPackPage.cpp | 8 ++--- 10 files changed, 90 insertions(+), 53 deletions(-) (limited to 'launcher') diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h index 27c3c2ec..0d90bd36 100644 --- a/launcher/ResourceDownloadTask.h +++ b/launcher/ResourceDownloadTask.h @@ -37,7 +37,6 @@ class ResourceDownloadTask : public SequentialTask { const QString& getFilename() const { return m_pack_version.fileName; } const QString& getCustomPath() const { return m_pack_version.custom_target_folder; } const QVariant& getVersionID() const { return m_pack_version.fileId; } - ModPlatform::IndexedPack& getPack() { return m_pack; } const ModPlatform::ResourceProvider& getProvider() const { return m_pack.provider; } private: diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 40f1efc4..de0af78c 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -1,23 +1,24 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* 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 . -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * 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 . + */ #pragma once +#include #include #include #include @@ -95,6 +96,7 @@ struct IndexedPack { bool versionsLoaded = false; QVector versions; + QVariant loadedFileId; // to check for already downloaded mods // Don't load by default, since some modplatform don't have that info bool extraDataLoaded = true; @@ -110,11 +112,12 @@ struct IndexedPack { } [[nodiscard]] bool isAnyVersionSelected() const { + if (loadedFileId.isValid()) + return true; if (!versionsLoaded) return false; - return std::any_of(versions.constBegin(), versions.constEnd(), - [](auto const& v) { return v.is_currently_selected; }); + return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); } }; diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 7fb4a657..562dda33 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -159,26 +159,10 @@ void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlat m_buttons.button(QDialogButtonBox::Ok)->setEnabled(!m_selected.isEmpty()); } -static ModPlatform::IndexedVersion& getVersionWithID(ModPlatform::IndexedPack& pack, QVariant id) -{ - Q_ASSERT(pack.versionsLoaded); - auto it = std::find_if(pack.versions.begin(), pack.versions.end(), [id](auto const& v) { return v.fileId == id; }); - Q_ASSERT(it != pack.versions.end()); - return *it; -} - void ResourceDownloadDialog::removeResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver) { - if (auto selected_task_it = m_selected.find(pack.name); selected_task_it != m_selected.end()) { - auto selected_task = *selected_task_it; - auto old_version_id = selected_task->getVersionID(); - - if (selected_task->getProvider() != pack.provider) // If the pack name matches but they are different providers search for the - // old one(in the actual pack) and deselect it. - getVersionWithID(selected_task->getPack(), old_version_id).is_currently_selected = false; - else if (ver.fileId != old_version_id) // If the new and old version IDs don't match, search for the old one and deselect it. - getVersionWithID(pack, old_version_id).is_currently_selected = false; - } + dynamic_cast(m_container->getPage(Modrinth::id()))->removeResourceFromPage(pack.name); + dynamic_cast(m_container->getPage(Flame::id()))->removeResourceFromPage(pack.name); // Deselect the new version too, since all versions of that pack got removed. ver.is_currently_selected = false; diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index 3ffe6cb0..b69d2cf9 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -6,12 +6,24 @@ #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" +#include "minecraft/mod/ModFolderModel.h" +#include "modplatform/ModIndex.h" #include namespace ResourceDownload { -ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) {} +ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) +{ + auto folder = static_cast(m_base_instance).loaderModList(); + for (auto mod : folder->allMods()) { + auto meta = mod->metadata(); + ModPlatform::IndexedPack pack{ meta->project_id, meta->provider, meta->name, meta->slug }; + pack.loadedFileId = meta->file_id; + qWarning() << pack.loadedFileId; + addPack(pack); + } +} /******** Make data requests ********/ @@ -24,7 +36,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments() std::optional> versions{}; - { // Version filter + { // Version filter if (!m_filter->versions.empty()) versions = m_filter->versions; } diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 04be43ad..efff1ff4 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -55,8 +55,7 @@ namespace ResourceDownload { -ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance& instance) - : ResourcePage(dialog, instance) +ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance) { connect(m_ui->searchButton, &QPushButton::clicked, this, &ModPage::triggerSearch); connect(m_ui->resourceFilterButton, &QPushButton::clicked, this, &ModPage::filterMods); @@ -75,12 +74,10 @@ void ModPage::setFilterWidget(unique_qobject_ptr& widget) m_filter_widget->setInstance(&static_cast(m_base_instance)); m_filter = m_filter_widget->getFilter(); - connect(m_filter_widget.get(), &ModFilterWidget::filterChanged, this, [&]{ - m_ui->searchButton->setStyleSheet("text-decoration: underline"); - }); - connect(m_filter_widget.get(), &ModFilterWidget::filterUnchanged, this, [&]{ - m_ui->searchButton->setStyleSheet("text-decoration: none"); - }); + connect(m_filter_widget.get(), &ModFilterWidget::filterChanged, this, + [&] { m_ui->searchButton->setStyleSheet("text-decoration: underline"); }); + connect(m_filter_widget.get(), &ModFilterWidget::filterUnchanged, this, + [&] { m_ui->searchButton->setStyleSheet("text-decoration: none"); }); } /******** Callbacks to events in the UI (set up in the derived classes) ********/ @@ -128,8 +125,8 @@ void ModPage::updateVersionList() for (int i = 0; i < current_pack.versions.size(); i++) { auto version = current_pack.versions[i]; bool valid = false; - for(auto& mcVer : m_filter->versions){ - //NOTE: Flame doesn't care about loader, so passing it changes nothing. + for (auto& mcVer : m_filter->versions) { + // NOTE: Flame doesn't care about loader, so passing it changes nothing. if (validateVersion(version, mcVer.toString(), packProfile->getModLoaders())) { valid = true; break; @@ -151,6 +148,7 @@ void ModPage::updateVersionList() void ModPage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); + m_model->addPack(pack); m_parent_dialog->addResource(pack, version, is_indexed); } diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index db7d26f8..c7c34a7c 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -3,12 +3,14 @@ // SPDX-License-Identifier: GPL-3.0-only #include "ResourceModel.h" +#include #include #include #include #include #include +#include #include "Application.h" #include "BuildConfig.h" @@ -335,6 +337,14 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc) ModPlatform::IndexedPack pack; try { loadIndexedPack(pack, packObj); + if (auto sel = + std::find_if(m_selected.begin(), m_selected.end(), + [&pack](ModPlatform::IndexedPack& i) { return i.provider == pack.provider && i.addonId == pack.addonId; }); + sel != m_selected.end()) { + pack.versionsLoaded = sel->versionsLoaded; + pack.versions = sel->versions; + pack.loadedFileId = sel->loadedFileId; + } newList.append(pack); } catch (const JSONValidationError& e) { qWarning() << "Error while loading resource from " << debugName() << ": " << e.cause(); @@ -398,6 +408,11 @@ void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::Ind try { auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); loadIndexedPackVersions(current_pack, arr); + if (current_pack.loadedFileId.isValid()) + if (auto ver = std::find_if(current_pack.versions.begin(), current_pack.versions.end(), + [¤t_pack](ModPlatform::IndexedVersion v) { return v.fileId == current_pack.loadedFileId; }); + ver != current_pack.versions.end()) + ver->is_currently_selected = true; } catch (const JSONValidationError& e) { qDebug() << doc; qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause(); @@ -441,4 +456,19 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe emit projectInfoUpdated(); } +void ResourceModel::removePack(QString& rem) +{ + m_selected.removeIf([&rem](ModPlatform::IndexedPack i) { return rem == i.name; }); + auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](ModPlatform::IndexedPack i) { return rem == i.name; }); + if (pack == m_packs.end()) { // ignore it if is not in the current search + return; + } + if (!pack->versionsLoaded) { + pack->loadedFileId = {}; + return; + } + for (auto& ver : pack->versions) + ver.is_currently_selected = false; +} + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 46a02d6e..5eb63901 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -80,6 +80,9 @@ class ResourceModel : public QAbstractListModel { /** Gets the icon at the URL for the given index. If it's not fetched yet, fetch it and update when fisinhed. */ std::optional getIcon(QModelIndex&, const QUrl&); + void addPack(ModPlatform::IndexedPack& add) { m_selected.append(add); } + void removePack(QString& rem); + protected: /** Resets the model's data. */ void clearData(); @@ -124,6 +127,7 @@ class ResourceModel : public QAbstractListModel { QSet m_failed_icon_actions; QList m_packs; + QList m_selected; // HACK: We need this to prevent callbacks from calling the model after it has already been deleted. // This leaks a tiny bit of memory per time the user has opened a resource dialog. How to make this better? diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index bbd465bc..24347dbd 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -308,6 +308,7 @@ void ResourcePage::onVersionSelectionChanged(QString data) void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) { + m_model->addPack(pack); m_parent_dialog->addResource(pack, version); } @@ -316,6 +317,11 @@ void ResourcePage::removeResourceFromDialog(ModPlatform::IndexedPack& pack, ModP m_parent_dialog->removeResource(pack, version); } +void ResourcePage::removeResourceFromPage(QString& name) +{ + m_model->removePack(name); +} + void ResourcePage::onResourceSelected() { if (m_selected_version_index < 0) diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index 1896d53e..a9db52e3 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -74,10 +74,11 @@ class ResourcePage : public QWidget, public BasePage { virtual void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); virtual void removeResourceFromDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); + virtual void removeResourceFromPage(QString& name); protected slots: virtual void triggerSearch() {} - + void onSelectionChanged(QModelIndex first, QModelIndex second); void onVersionSelectionChanged(QString data); void onResourceSelected(); diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.cpp b/launcher/ui/pages/modplatform/ShaderPackPage.cpp index 251c07e7..1b9b2b83 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackPage.cpp @@ -13,8 +13,7 @@ namespace ResourceDownload { -ShaderPackResourcePage::ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) - : ResourcePage(dialog, instance) +ShaderPackResourcePage::ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance) { connect(m_ui->searchButton, &QPushButton::clicked, this, &ShaderPackResourcePage::triggerSearch); connect(m_ui->packView, &QListView::doubleClicked, this, &ShaderPackResourcePage::onResourceSelected); @@ -38,7 +37,8 @@ QMap ShaderPackResourcePage::urlHandlers() const { QMap map; map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/shaders\\/([^\\/]+)\\/?"), "modrinth"); - map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/customization\\/([^\\/]+)\\/?"), "curseforge"); + map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/customization\\/([^\\/]+)\\/?"), + "curseforge"); map.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge"); return map; } @@ -47,7 +47,7 @@ void ShaderPackResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, { if (version.loaders.contains(QStringLiteral("canvas"))) version.custom_target_folder = QStringLiteral("resourcepacks"); - + m_model->addPack(pack); m_parent_dialog->addResource(pack, version); } -- cgit From 75116364c6daea5affb029038d2a7d20bc601beb Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 22 Apr 2023 00:55:11 +0300 Subject: Small Cleanup Signed-off-by: Trial97 --- launcher/modplatform/ModIndex.h | 1 - launcher/ui/pages/modplatform/ModModel.cpp | 1 - launcher/ui/pages/modplatform/ResourceModel.cpp | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index de0af78c..b736aaf4 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -18,7 +18,6 @@ #pragma once -#include #include #include #include diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index b69d2cf9..251200f7 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -20,7 +20,6 @@ ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceMo auto meta = mod->metadata(); ModPlatform::IndexedPack pack{ meta->project_id, meta->provider, meta->name, meta->slug }; pack.loadedFileId = meta->file_id; - qWarning() << pack.loadedFileId; addPack(pack); } } diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index c7c34a7c..0e74395f 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -3,10 +3,10 @@ // SPDX-License-Identifier: GPL-3.0-only #include "ResourceModel.h" -#include #include #include +#include #include #include #include -- cgit From 460e83207f9ae087846fc9ca210799e41f51a326 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 22 Apr 2023 01:18:27 +0300 Subject: Fixed removeIf for Qt version Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/ResourceModel.cpp | 34 ++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 0e74395f..459c8c72 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -458,7 +458,39 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe void ResourceModel::removePack(QString& rem) { - m_selected.removeIf([&rem](ModPlatform::IndexedPack i) { return rem == i.name; }); + auto pred = [&rem](ModPlatform::IndexedPack i) { return rem == i.name; }; +#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) + m_selected.removeIf(pred); +#else + { // well partial implementation of remove_if in case the QT Version is not high enough + const auto cbegin = m_selected.cbegin(); + const auto cend = m_selected.cend(); + const auto t_it = std::find_if(cbegin, cend, pred); + auto result = std::distance(cbegin, t_it); + if (result != m_selected.size()) { + // now detach: + const auto e = m_selected.end(); + + auto it = std::next(m_selected.begin(), result); + auto dest = it; + + // Loop Invariants: + // - it != e + // - [next(it), e[ still to be checked + // - [c.begin(), dest[ are result + while (++it != e) { + if (!pred(*it)) { + *dest = std::move(*it); + ++dest; + } + } + + result = std::distance(dest, e); + m_selected.erase(dest, e); + } + } +#endif + // m_selected.removeAt(qsizetype i) auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](ModPlatform::IndexedPack i) { return rem == i.name; }); if (pack == m_packs.end()) { // ignore it if is not in the current search return; -- cgit From f738d7566e45f618634c4d40ec45f78f96fac588 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 22 Apr 2023 22:27:33 +0300 Subject: Fixed code qulity Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/ResourceModel.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 459c8c72..a58ce549 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -337,9 +337,9 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc) ModPlatform::IndexedPack pack; try { loadIndexedPack(pack, packObj); - if (auto sel = - std::find_if(m_selected.begin(), m_selected.end(), - [&pack](ModPlatform::IndexedPack& i) { return i.provider == pack.provider && i.addonId == pack.addonId; }); + if (auto sel = std::find_if( + m_selected.begin(), m_selected.end(), + [&pack](const ModPlatform::IndexedPack& i) { return i.provider == pack.provider && i.addonId == pack.addonId; }); sel != m_selected.end()) { pack.versionsLoaded = sel->versionsLoaded; pack.versions = sel->versions; @@ -409,8 +409,9 @@ void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::Ind auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); loadIndexedPackVersions(current_pack, arr); if (current_pack.loadedFileId.isValid()) - if (auto ver = std::find_if(current_pack.versions.begin(), current_pack.versions.end(), - [¤t_pack](ModPlatform::IndexedVersion v) { return v.fileId == current_pack.loadedFileId; }); + if (auto ver = + std::find_if(current_pack.versions.begin(), current_pack.versions.end(), + [¤t_pack](const ModPlatform::IndexedVersion& v) { return v.fileId == current_pack.loadedFileId; }); ver != current_pack.versions.end()) ver->is_currently_selected = true; } catch (const JSONValidationError& e) { @@ -458,7 +459,7 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe void ResourceModel::removePack(QString& rem) { - auto pred = [&rem](ModPlatform::IndexedPack i) { return rem == i.name; }; + auto pred = [&rem](const ModPlatform::IndexedPack& i) { return rem == i.name; }; #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) m_selected.removeIf(pred); #else @@ -491,7 +492,7 @@ void ResourceModel::removePack(QString& rem) } #endif // m_selected.removeAt(qsizetype i) - auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](ModPlatform::IndexedPack i) { return rem == i.name; }); + auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](const ModPlatform::IndexedPack& i) { return rem == i.name; }); if (pack == m_packs.end()) { // ignore it if is not in the current search return; } -- cgit From 248920a2211db0c55d01273cc36c735a629b0325 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 27 Apr 2023 01:33:46 +0300 Subject: Removed extra code Signed-off-by: Trial97 --- launcher/modplatform/ModIndex.h | 3 -- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 4 +-- launcher/ui/pages/modplatform/ModModel.cpp | 11 +------ launcher/ui/pages/modplatform/ModPage.cpp | 2 +- launcher/ui/pages/modplatform/ResourceModel.cpp | 41 ++++-------------------- launcher/ui/pages/modplatform/ResourcePage.cpp | 2 +- launcher/ui/pages/modplatform/ShaderPackPage.cpp | 2 +- launcher/ui/widgets/PageContainer.cpp | 5 +++ launcher/ui/widgets/PageContainer.h | 1 + 9 files changed, 18 insertions(+), 53 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index b736aaf4..4497088c 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -95,7 +95,6 @@ struct IndexedPack { bool versionsLoaded = false; QVector versions; - QVariant loadedFileId; // to check for already downloaded mods // Don't load by default, since some modplatform don't have that info bool extraDataLoaded = true; @@ -111,8 +110,6 @@ struct IndexedPack { } [[nodiscard]] bool isAnyVersionSelected() const { - if (loadedFileId.isValid()) - return true; if (!versionsLoaded) return false; diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 562dda33..4ba38374 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -161,8 +161,8 @@ void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlat void ResourceDownloadDialog::removeResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver) { - dynamic_cast(m_container->getPage(Modrinth::id()))->removeResourceFromPage(pack.name); - dynamic_cast(m_container->getPage(Flame::id()))->removeResourceFromPage(pack.name); + for (auto page : m_container->getPages()) + static_cast(page)->removeResourceFromPage(pack.name); // Deselect the new version too, since all versions of that pack got removed. ver.is_currently_selected = false; diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index 251200f7..6a206a7c 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -13,16 +13,7 @@ namespace ResourceDownload { -ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) -{ - auto folder = static_cast(m_base_instance).loaderModList(); - for (auto mod : folder->allMods()) { - auto meta = mod->metadata(); - ModPlatform::IndexedPack pack{ meta->project_id, meta->provider, meta->name, meta->slug }; - pack.loadedFileId = meta->file_id; - addPack(pack); - } -} +ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) {} /******** Make data requests ********/ diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index efff1ff4..8a4f55cb 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -148,8 +148,8 @@ void ModPage::updateVersionList() void ModPage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); - m_model->addPack(pack); m_parent_dialog->addResource(pack, version, is_indexed); + m_model->addPack(pack); } } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index a58ce549..b83cad0d 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -343,7 +343,6 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc) sel != m_selected.end()) { pack.versionsLoaded = sel->versionsLoaded; pack.versions = sel->versions; - pack.loadedFileId = sel->loadedFileId; } newList.append(pack); } catch (const JSONValidationError& e) { @@ -408,12 +407,6 @@ void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::Ind try { auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); loadIndexedPackVersions(current_pack, arr); - if (current_pack.loadedFileId.isValid()) - if (auto ver = - std::find_if(current_pack.versions.begin(), current_pack.versions.end(), - [¤t_pack](const ModPlatform::IndexedVersion& v) { return v.fileId == current_pack.loadedFileId; }); - ver != current_pack.versions.end()) - ver->is_currently_selected = true; } catch (const JSONValidationError& e) { qDebug() << doc; qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause(); @@ -463,41 +456,19 @@ void ResourceModel::removePack(QString& rem) #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) m_selected.removeIf(pred); #else - { // well partial implementation of remove_if in case the QT Version is not high enough - const auto cbegin = m_selected.cbegin(); - const auto cend = m_selected.cend(); - const auto t_it = std::find_if(cbegin, cend, pred); - auto result = std::distance(cbegin, t_it); - if (result != m_selected.size()) { - // now detach: - const auto e = m_selected.end(); - - auto it = std::next(m_selected.begin(), result); - auto dest = it; - - // Loop Invariants: - // - it != e - // - [next(it), e[ still to be checked - // - [c.begin(), dest[ are result - while (++it != e) { - if (!pred(*it)) { - *dest = std::move(*it); - ++dest; - } - } - - result = std::distance(dest, e); - m_selected.erase(dest, e); - } + { + for (auto it = m_selected.begin(); it != m_selected.end();) + if (pred(*it)) + it = m_selected.erase(it); + else + ++it; } #endif - // m_selected.removeAt(qsizetype i) auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](const ModPlatform::IndexedPack& i) { return rem == i.name; }); if (pack == m_packs.end()) { // ignore it if is not in the current search return; } if (!pack->versionsLoaded) { - pack->loadedFileId = {}; return; } for (auto& ver : pack->versions) diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 24347dbd..d41503e8 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -308,8 +308,8 @@ void ResourcePage::onVersionSelectionChanged(QString data) void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) { - m_model->addPack(pack); m_parent_dialog->addResource(pack, version); + m_model->addPack(pack); } void ResourcePage::removeResourceFromDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.cpp b/launcher/ui/pages/modplatform/ShaderPackPage.cpp index 1b9b2b83..729e714c 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackPage.cpp @@ -47,8 +47,8 @@ void ShaderPackResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, { if (version.loaders.contains(QStringLiteral("canvas"))) version.custom_target_folder = QStringLiteral("resourcepacks"); - m_model->addPack(pack); m_parent_dialog->addResource(pack, version); + m_model->addPack(pack); } } // namespace ResourceDownload diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index 0a06a351..84a4e0de 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -135,6 +135,11 @@ BasePage* PageContainer::getPage(QString pageId) return m_model->findPageEntryById(pageId); } +const QList PageContainer::getPages() const +{ + return m_model->pages(); +} + void PageContainer::refreshContainer() { m_proxyModel->invalidate(); diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index 97e294dc..ad74d43a 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -80,6 +80,7 @@ public: virtual bool selectPage(QString pageId) override; BasePage* getPage(QString pageId) override; + const QList getPages() const; void refreshContainer() override; virtual void setParentContainer(BasePageContainer * container) -- cgit From 61a235561896fc82a19da00126e361bb56d61c69 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 27 Apr 2023 01:41:26 +0300 Subject: Removed formated but not used files Signed-off-by: Trial97 --- launcher/ResourceDownloadTask.h | 51 +++++++++++++++--------------- launcher/modplatform/ModIndex.h | 33 +++++++++---------- launcher/ui/pages/modplatform/ModModel.cpp | 4 +-- 3 files changed, 43 insertions(+), 45 deletions(-) (limited to 'launcher') diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h index 0d90bd36..73ad2d07 100644 --- a/launcher/ResourceDownloadTask.h +++ b/launcher/ResourceDownloadTask.h @@ -1,45 +1,41 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2022-2023 flowln - * Copyright (C) 2022 Sefa Eyeoglu - * - * 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 . - */ +* Prism Launcher - Minecraft Launcher +* Copyright (c) 2022-2023 flowln +* Copyright (C) 2022 Sefa Eyeoglu +* +* 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 . +*/ #pragma once #include "net/NetJob.h" #include "tasks/SequentialTask.h" -#include "minecraft/mod/tasks/LocalModUpdateTask.h" #include "modplatform/ModIndex.h" +#include "minecraft/mod/tasks/LocalModUpdateTask.h" class ResourceFolderModel; class ResourceDownloadTask : public SequentialTask { Q_OBJECT - public: - explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, - ModPlatform::IndexedVersion version, - const std::shared_ptr packs, - bool is_indexed = true); +public: + explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, ModPlatform::IndexedVersion version, const std::shared_ptr packs, bool is_indexed = true); const QString& getFilename() const { return m_pack_version.fileName; } const QString& getCustomPath() const { return m_pack_version.custom_target_folder; } const QVariant& getVersionID() const { return m_pack_version.fileId; } - const ModPlatform::ResourceProvider& getProvider() const { return m_pack.provider; } - private: +private: ModPlatform::IndexedPack m_pack; ModPlatform::IndexedVersion m_pack_version; const std::shared_ptr m_pack_model; @@ -51,8 +47,11 @@ class ResourceDownloadTask : public SequentialTask { void downloadFailed(QString reason); void downloadSucceeded(); - std::tuple to_delete{ "", "" }; + std::tuple to_delete {"", ""}; - private slots: +private slots: void hasOldResource(QString name, QString filename); }; + + + diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 4497088c..40f1efc4 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher - * Copyright (c) 2022 flowln - * - * 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 . - */ +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* 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 . +*/ #pragma once @@ -113,7 +113,8 @@ struct IndexedPack { if (!versionsLoaded) return false; - return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); + return std::any_of(versions.constBegin(), versions.constEnd(), + [](auto const& v) { return v.is_currently_selected; }); } }; diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index 6a206a7c..3ffe6cb0 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -6,8 +6,6 @@ #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" -#include "minecraft/mod/ModFolderModel.h" -#include "modplatform/ModIndex.h" #include @@ -26,7 +24,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments() std::optional> versions{}; - { // Version filter + { // Version filter if (!m_filter->versions.empty()) versions = m_filter->versions; } -- cgit From 495103f72e85e3664458e6425172bfeb8acf7a97 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 29 Apr 2023 14:30:57 -0700 Subject: fix: set `x-xbl-contract-version` header during xbox auth step Refrencing GDlauncher and ATLauncher code for auth as well as https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/reference/live/rest/additional/httpstandardheaders it is possible some of microsoft's server's are rejecting our request because of this missing header? Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/auth/steps/XboxUserStep.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'launcher') diff --git a/launcher/minecraft/auth/steps/XboxUserStep.cpp b/launcher/minecraft/auth/steps/XboxUserStep.cpp index 53069597..842eb60f 100644 --- a/launcher/minecraft/auth/steps/XboxUserStep.cpp +++ b/launcher/minecraft/auth/steps/XboxUserStep.cpp @@ -38,6 +38,10 @@ void XboxUserStep::perform() { QNetworkRequest request = QNetworkRequest(QUrl("https://user.auth.xboxlive.com/user/authenticate")); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Accept", "application/json"); + // set contract-verison header (prevent err 400 bad-request?) + // https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/reference/live/rest/additional/httpstandardheaders + request.setRawHeader("x-xbl-contract-version", "1"); + auto *requestor = new AuthRequest(this); connect(requestor, &AuthRequest::finished, this, &XboxUserStep::onRequestDone); requestor->post(request, xbox_auth_data.toUtf8()); -- cgit From e0380960fda706a70bef6f63610bcfa68775e21d Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 2 May 2023 14:23:27 +0100 Subject: Change to use future Signed-off-by: TheKodeToad --- .../modrinth/ModrinthPackExportTask.cpp | 57 +++++++++++++--------- .../modplatform/modrinth/ModrinthPackExportTask.h | 8 ++- 2 files changed, 40 insertions(+), 25 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 54932131..d2ef0653 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -62,8 +62,11 @@ bool ModrinthPackExportTask::abort() return true; } - pendingAbort = true; - return true; + if (buildZipFuture.isRunning()) { + buildZipFuture.cancel(); + return true; + } + return false; } void ModrinthPackExportTask::collectFiles() @@ -190,44 +193,37 @@ void ModrinthPackExportTask::parseApiResponse(const QByteArray* response) void ModrinthPackExportTask::buildZip() { - static_cast(QtConcurrent::run(QThreadPool::globalInstance(), [this]() { - setStatus("Adding files..."); + setStatus("Adding files..."); + + buildZipFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { QuaZip zip(output); if (!zip.open(QuaZip::mdCreate)) { QFile::remove(output); - emitFailed(tr("Could not create file")); - return; + return BuildZipResult(tr("Could not create file")); } - if (pendingAbort) { - QMetaObject::invokeMethod(this, &ModrinthPackExportTask::emitAborted, Qt::QueuedConnection); - return; - } + if (buildZipFuture.isCanceled()) + return BuildZipResult(); QuaZipFile indexFile(&zip); if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) { QFile::remove(output); - QMetaObject::invokeMethod( - this, [this]() { emitFailed(tr("Could not create index")); }, Qt::QueuedConnection); - return; + return BuildZipResult(tr("Could not create index")); } indexFile.write(generateIndex()); size_t progress = 0; for (const QFileInfo& file : files) { - if (pendingAbort) { + if (buildZipFuture.isCanceled()) { QFile::remove(output); - QMetaObject::invokeMethod(this, &ModrinthPackExportTask::emitAborted, Qt::QueuedConnection); - return; + return BuildZipResult(); } setProgress(progress, files.length()); const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) { QFile::remove(output); - QMetaObject::invokeMethod( - this, [this, relative]() { emitFailed(tr("Could not read and compress %1").arg(relative)); }, Qt::QueuedConnection); - return; + return BuildZipResult(tr("Could not read and compress %1").arg(relative)); } progress++; } @@ -236,13 +232,26 @@ void ModrinthPackExportTask::buildZip() if (zip.getZipError() != 0) { QFile::remove(output); - QMetaObject::invokeMethod( - this, [this]() { emitFailed(tr("A zip error occurred")); }, Qt::QueuedConnection); - return; + return BuildZipResult(tr("A zip error occurred")); } - QMetaObject::invokeMethod(this, &ModrinthPackExportTask::emitSucceeded, Qt::QueuedConnection); - })); + return BuildZipResult(); + }); + connect(&buildZipWatcher, &QFutureWatcher::finished, this, &ModrinthPackExportTask::finish); + buildZipWatcher.setFuture(buildZipFuture); +} + +void ModrinthPackExportTask::finish() +{ + if (buildZipFuture.isCanceled()) + emitAborted(); + else { + const BuildZipResult result = buildZipFuture.result(); + if (result.has_value()) + emitFailed(result.value()); + else + emitSucceeded(); + } } QByteArray ModrinthPackExportTask::generateIndex() diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index 25045cf2..5426d6da 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -18,6 +18,8 @@ #pragma once +#include +#include #include "BaseInstance.h" #include "MMCZip.h" #include "minecraft/MinecraftInstance.h" @@ -54,18 +56,22 @@ class ModrinthPackExportTask : public Task { const QString output; const MMCZip::FilterFunction filter; + typedef std::optional BuildZipResult; + ModrinthAPI api; QFileInfoList files; QMap pendingHashes; QMap resolvedFiles; Task::Ptr task; - bool pendingAbort = false; + QFuture buildZipFuture; + QFutureWatcher buildZipWatcher; void collectFiles(); void collectHashes(); void makeApiRequest(); void parseApiResponse(const QByteArray* response); void buildZip(); + void finish(); QByteArray generateIndex(); }; -- cgit From f8bf71e152aba15d23b5b92382bb112de125d4d1 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 3 May 2023 00:49:54 +0300 Subject: Moved the selected resources to one list Signed-off-by: Trial97 --- launcher/ResourceDownloadTask.cpp | 11 +++-- launcher/ResourceDownloadTask.h | 25 ++++++---- launcher/modplatform/ModIndex.h | 1 - launcher/ui/dialogs/ResourceDownloadDialog.cpp | 59 ++++++++++++++---------- launcher/ui/dialogs/ResourceDownloadDialog.h | 9 ++-- launcher/ui/pages/modplatform/ModPage.cpp | 7 +-- launcher/ui/pages/modplatform/ModPage.h | 2 +- launcher/ui/pages/modplatform/ResourceModel.cpp | 29 ++++++++---- launcher/ui/pages/modplatform/ResourceModel.h | 14 ++++-- launcher/ui/pages/modplatform/ResourcePage.cpp | 17 +++++-- launcher/ui/pages/modplatform/ResourcePage.h | 13 ++++-- launcher/ui/pages/modplatform/ShaderPackPage.cpp | 10 ++-- launcher/ui/pages/modplatform/ShaderPackPage.h | 2 +- 13 files changed, 124 insertions(+), 75 deletions(-) (limited to 'launcher') diff --git a/launcher/ResourceDownloadTask.cpp b/launcher/ResourceDownloadTask.cpp index 98bcf259..f7d3487a 100644 --- a/launcher/ResourceDownloadTask.cpp +++ b/launcher/ResourceDownloadTask.cpp @@ -27,8 +27,9 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack pack, ModPlatform::IndexedVersion version, const std::shared_ptr packs, - bool is_indexed) - : m_pack(std::move(pack)), m_pack_version(std::move(version)), m_pack_model(packs) + bool is_indexed, + QString custom_target_folder) + : m_pack(std::move(pack)), m_pack_version(std::move(version)), m_pack_model(packs), m_custom_target_folder(custom_target_folder) { if (auto model = dynamic_cast(m_pack_model.get()); model && is_indexed) { m_update_task.reset(new LocalModUpdateTask(model->indexDir(), m_pack, m_pack_version)); @@ -40,13 +41,13 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack pack, m_filesNetJob.reset(new NetJob(tr("Resource download"), APPLICATION->network())); m_filesNetJob->setStatus(tr("Downloading resource:\n%1").arg(m_pack_version.downloadUrl)); - QDir dir { m_pack_model->dir() }; + QDir dir{ m_pack_model->dir() }; { // FIXME: Make this more generic. May require adding additional info to IndexedVersion, // or adquiring a reference to the base instance. - if (!m_pack_version.custom_target_folder.isEmpty()) { + if (!m_custom_target_folder.isEmpty()) { dir.cdUp(); - dir.cd(m_pack_version.custom_target_folder); + dir.cd(m_custom_target_folder); } } diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h index 73ad2d07..fe41170a 100644 --- a/launcher/ResourceDownloadTask.h +++ b/launcher/ResourceDownloadTask.h @@ -22,23 +22,31 @@ #include "net/NetJob.h" #include "tasks/SequentialTask.h" -#include "modplatform/ModIndex.h" #include "minecraft/mod/tasks/LocalModUpdateTask.h" +#include "modplatform/ModIndex.h" class ResourceFolderModel; class ResourceDownloadTask : public SequentialTask { Q_OBJECT -public: - explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, ModPlatform::IndexedVersion version, const std::shared_ptr packs, bool is_indexed = true); + public: + explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, + ModPlatform::IndexedVersion version, + const std::shared_ptr packs, + bool is_indexed = true, + QString custom_target_folder = {}); const QString& getFilename() const { return m_pack_version.fileName; } - const QString& getCustomPath() const { return m_pack_version.custom_target_folder; } + const QString& getCustomPath() const { return m_custom_target_folder; } const QVariant& getVersionID() const { return m_pack_version.fileId; } + const QString& getName() const { return m_pack.name; } + ModPlatform::IndexedPack& getPack() { return m_pack; } + // void setSelectedVersion(ModPlatform::IndexedVersion version) { m_pack_version = std::move(version); } -private: + private: ModPlatform::IndexedPack m_pack; ModPlatform::IndexedVersion m_pack_version; const std::shared_ptr m_pack_model; + QString m_custom_target_folder; NetJob::Ptr m_filesNetJob; LocalModUpdateTask::Ptr m_update_task; @@ -47,11 +55,8 @@ private: void downloadFailed(QString reason); void downloadSucceeded(); - std::tuple to_delete {"", ""}; + std::tuple to_delete{ "", "" }; -private slots: + private slots: void hasOldResource(QString name, QString filename); }; - - - diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 40f1efc4..1b99a88e 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -68,7 +68,6 @@ struct IndexedVersion { // For internal use, not provided by APIs bool is_currently_selected = false; - QString custom_target_folder; }; struct ExtraPackData { diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 4ba38374..ef3200a2 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -20,6 +20,7 @@ #include "ResourceDownloadDialog.h" #include +#include #include "Application.h" #include "ResourceDownloadTask.h" @@ -118,21 +119,24 @@ void ResourceDownloadDialog::connectButtons() void ResourceDownloadDialog::confirm() { - auto keys = m_selected.keys(); - keys.sort(Qt::CaseInsensitive); + auto selected = getTasks(); + std::sort(selected.begin(), selected.end(), [](const DownloadTaskPtr& a, const DownloadTaskPtr& b) { + return QString::compare(a->getName(), b->getName(), Qt::CaseInsensitive) < 0; + }); auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString())); confirm_dialog->retranslateUi(resourcesString()); - for (auto& task : keys) { - auto selected = m_selected.constFind(task).value(); - confirm_dialog->appendResource({ task, selected->getFilename(), selected->getCustomPath() }); + for (auto& task : selected) { + confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath() }); } if (confirm_dialog->exec()) { auto deselected = confirm_dialog->deselectedResources(); - for (auto name : deselected) { - m_selected.remove(name); + for (auto page : m_container->getPages()) { + auto res = static_cast(page); + for (auto name : deselected) + res->removeResourceFromPage(name); } this->accept(); @@ -149,32 +153,39 @@ ResourcePage* ResourceDownloadDialog::getSelectedPage() return m_selectedPage; } -void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, bool is_indexed) +void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver) { - removeResource(pack, ver); - - ver.is_currently_selected = true; - m_selected.insert(pack.name, makeShared(pack, ver, getBaseModel(), is_indexed)); - - m_buttons.button(QDialogButtonBox::Ok)->setEnabled(!m_selected.isEmpty()); + removeResource(pack.name); + m_selectedPage->addResourceToPage(pack, ver, getBaseModel()); + setButtonStatus(); } -void ResourceDownloadDialog::removeResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver) +void ResourceDownloadDialog::removeResource(const QString& pack_name) { - for (auto page : m_container->getPages()) - static_cast(page)->removeResourceFromPage(pack.name); - - // Deselect the new version too, since all versions of that pack got removed. - ver.is_currently_selected = false; - - m_selected.remove(pack.name); + for (auto page : m_container->getPages()) { + static_cast(page)->removeResourceFromPage(pack_name); + } + setButtonStatus(); +} - m_buttons.button(QDialogButtonBox::Ok)->setEnabled(!m_selected.isEmpty()); +void ResourceDownloadDialog::setButtonStatus() +{ + bool selected; + for (auto page : m_container->getPages()) { + auto res = static_cast(page); + selected = selected || res->hasSelectedPacks(); + } + m_buttons.button(QDialogButtonBox::Ok)->setEnabled(selected); } const QList ResourceDownloadDialog::getTasks() { - return m_selected.values(); + QList selected; + for (auto page : m_container->getPages()) { + auto res = static_cast(page); + selected.append(res->selectedPacks()); + } + return selected; } void ResourceDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* selected) diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index 5678dc8b..204e870f 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -62,8 +62,8 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { bool selectPage(QString pageId); ResourcePage* getSelectedPage(); - void addResource(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, bool is_indexed = false); - void removeResource(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); + void addResource(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); + void removeResource(const QString&); const QList getTasks(); [[nodiscard]] const std::shared_ptr getBaseModel() const { return m_base_model; } @@ -79,6 +79,7 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { protected: [[nodiscard]] virtual QString geometrySaveKey() const { return ""; } + void setButtonStatus(); protected: const std::shared_ptr m_base_model; @@ -88,12 +89,8 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { QDialogButtonBox m_buttons; QVBoxLayout m_vertical_layout; - - QHash m_selected; }; - - class ModDownloadDialog final : public ResourceDownloadDialog { Q_OBJECT diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 8a4f55cb..a6186d89 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -145,11 +145,12 @@ void ModPage::updateVersionList() updateSelectionButton(); } -void ModPage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) +void ModPage::addResourceToPage(ModPlatform::IndexedPack& pack, + ModPlatform::IndexedVersion& version, + const std::shared_ptr base_model) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); - m_parent_dialog->addResource(pack, version, is_indexed); - m_model->addPack(pack); + m_model->addPack(pack, version, base_model, is_indexed); } } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h index c3b58cd6..6ecf8a94 100644 --- a/launcher/ui/pages/modplatform/ModPage.h +++ b/launcher/ui/pages/modplatform/ModPage.h @@ -50,7 +50,7 @@ class ModPage : public ResourcePage { [[nodiscard]] QMap urlHandlers() const override; - void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&) override; + void addResourceToPage(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, const std::shared_ptr) override; virtual auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders = {}) const -> bool = 0; diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index b83cad0d..056b28cc 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -337,14 +337,15 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc) ModPlatform::IndexedPack pack; try { loadIndexedPack(pack, packObj); - if (auto sel = std::find_if( - m_selected.begin(), m_selected.end(), - [&pack](const ModPlatform::IndexedPack& i) { return i.provider == pack.provider && i.addonId == pack.addonId; }); + if (auto sel = std::find_if(m_selected.begin(), m_selected.end(), + [&pack](const DownloadTaskPtr i) { + const auto ipack = i->getPack(); + return ipack.provider == pack.provider && ipack.addonId == pack.addonId; + }); sel != m_selected.end()) { - pack.versionsLoaded = sel->versionsLoaded; - pack.versions = sel->versions; - } - newList.append(pack); + newList.append(sel->get()->getPack()); + } else + newList.append(pack); } catch (const JSONValidationError& e) { qWarning() << "Error while loading resource from " << debugName() << ": " << e.cause(); continue; @@ -450,9 +451,19 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe emit projectInfoUpdated(); } -void ResourceModel::removePack(QString& rem) +void ResourceModel::addPack(ModPlatform::IndexedPack& pack, + ModPlatform::IndexedVersion& version, + const std::shared_ptr packs, + bool is_indexed, + QString custom_target_folder) +{ + version.is_currently_selected = true; + m_selected.append(makeShared(pack, version, packs, is_indexed, custom_target_folder)); +} + +void ResourceModel::removePack(const QString& rem) { - auto pred = [&rem](const ModPlatform::IndexedPack& i) { return rem == i.name; }; + auto pred = [&rem](const DownloadTaskPtr i) { return rem == i->getName(); }; #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) m_selected.removeIf(pred); #else diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 5eb63901..735d1687 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -10,6 +10,7 @@ #include "QObjectPtr.h" +#include "ResourceDownloadTask.h" #include "modplatform/ResourceAPI.h" #include "tasks/ConcurrentTask.h" @@ -29,6 +30,8 @@ class ResourceModel : public QAbstractListModel { Q_PROPERTY(QString search_term MEMBER m_search_term WRITE setSearchTerm) public: + using DownloadTaskPtr = shared_qobject_ptr; + ResourceModel(ResourceAPI* api); ~ResourceModel() override; @@ -80,8 +83,13 @@ class ResourceModel : public QAbstractListModel { /** Gets the icon at the URL for the given index. If it's not fetched yet, fetch it and update when fisinhed. */ std::optional getIcon(QModelIndex&, const QUrl&); - void addPack(ModPlatform::IndexedPack& add) { m_selected.append(add); } - void removePack(QString& rem); + void addPack(ModPlatform::IndexedPack& pack, + ModPlatform::IndexedVersion& version, + const std::shared_ptr packs, + bool is_indexed = false, + QString custom_target_folder = {}); + void removePack(const QString& rem); + QList selectedPacks() { return m_selected; } protected: /** Resets the model's data. */ @@ -127,7 +135,7 @@ class ResourceModel : public QAbstractListModel { QSet m_failed_icon_actions; QList m_packs; - QList m_selected; + QList m_selected; // HACK: We need this to prevent callbacks from calling the model after it has already been deleted. // This leaks a tiny bit of memory per time the user has opened a resource dialog. How to make this better? diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index d41503e8..4ebdea56 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -37,6 +37,7 @@ */ #include "ResourcePage.h" +#include "modplatform/ModIndex.h" #include "ui_ResourcePage.h" #include @@ -309,15 +310,21 @@ void ResourcePage::onVersionSelectionChanged(QString data) void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) { m_parent_dialog->addResource(pack, version); - m_model->addPack(pack); } -void ResourcePage::removeResourceFromDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) +void ResourcePage::removeResourceFromDialog(const QString& pack_name) { - m_parent_dialog->removeResource(pack, version); + m_parent_dialog->removeResource(pack_name); } -void ResourcePage::removeResourceFromPage(QString& name) +void ResourcePage::addResourceToPage(ModPlatform::IndexedPack& pack, + ModPlatform::IndexedVersion& ver, + const std::shared_ptr base_model) +{ + m_model->addPack(pack, ver, base_model); +} + +void ResourcePage::removeResourceFromPage(const QString& name) { m_model->removePack(name); } @@ -333,7 +340,7 @@ void ResourcePage::onResourceSelected() auto& version = current_pack.versions[m_selected_version_index]; if (version.is_currently_selected) - removeResourceFromDialog(current_pack, version); + removeResourceFromDialog(current_pack.name); else addResourceToDialog(current_pack, version); diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index a9db52e3..df68e6fd 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -7,10 +7,12 @@ #include #include +#include "ResourceDownloadTask.h" #include "modplatform/ModIndex.h" #include "modplatform/ResourceAPI.h" #include "ui/pages/BasePage.h" +#include "ui/pages/modplatform/ResourceModel.h" #include "ui/widgets/ProgressWidget.h" namespace Ui { @@ -27,6 +29,7 @@ class ResourceModel; class ResourcePage : public QWidget, public BasePage { Q_OBJECT public: + using DownloadTaskPtr = shared_qobject_ptr; ~ResourcePage() override; /* Affects what the user sees */ @@ -72,9 +75,13 @@ class ResourcePage : public QWidget, public BasePage { virtual void updateSelectionButton(); virtual void updateVersionList(); - virtual void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); - virtual void removeResourceFromDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); - virtual void removeResourceFromPage(QString& name); + void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); + void removeResourceFromDialog(const QString& pack_name); + virtual void removeResourceFromPage(const QString& name); + virtual void addResourceToPage(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, const std::shared_ptr); + + QList selectedPacks() { return m_model->selectedPacks(); } + bool hasSelectedPacks() { return !(m_model->selectedPacks().isEmpty()); } protected slots: virtual void triggerSearch() {} diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.cpp b/launcher/ui/pages/modplatform/ShaderPackPage.cpp index 729e714c..c7a69418 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackPage.cpp @@ -43,12 +43,14 @@ QMap ShaderPackResourcePage::urlHandlers() const return map; } -void ShaderPackResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) +void ShaderPackResourcePage::addResourceToPage(ModPlatform::IndexedPack& pack, + ModPlatform::IndexedVersion& version, + const std::shared_ptr base_model) { + QString custom_target_folder; if (version.loaders.contains(QStringLiteral("canvas"))) - version.custom_target_folder = QStringLiteral("resourcepacks"); - m_parent_dialog->addResource(pack, version); - m_model->addPack(pack); + custom_target_folder = QStringLiteral("resourcepacks"); + m_model->addPack(pack, version, base_model, false, custom_target_folder); } } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.h b/launcher/ui/pages/modplatform/ShaderPackPage.h index 972419a8..8a293f74 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.h +++ b/launcher/ui/pages/modplatform/ShaderPackPage.h @@ -40,7 +40,7 @@ class ShaderPackResourcePage : public ResourcePage { [[nodiscard]] bool supportsFiltering() const override { return false; }; - void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&) override; + void addResourceToPage(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, const std::shared_ptr) override; [[nodiscard]] QMap urlHandlers() const override; -- cgit From f6ed2036b34177d7f932007dc5b3cc3d59f99aea Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 3 May 2023 00:55:18 +0300 Subject: Removed comment Signed-off-by: Trial97 --- launcher/ResourceDownloadTask.h | 1 - 1 file changed, 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h index fe41170a..32b1120c 100644 --- a/launcher/ResourceDownloadTask.h +++ b/launcher/ResourceDownloadTask.h @@ -40,7 +40,6 @@ class ResourceDownloadTask : public SequentialTask { const QVariant& getVersionID() const { return m_pack_version.fileId; } const QString& getName() const { return m_pack.name; } ModPlatform::IndexedPack& getPack() { return m_pack; } - // void setSelectedVersion(ModPlatform::IndexedVersion version) { m_pack_version = std::move(version); } private: ModPlatform::IndexedPack m_pack; -- cgit From e4449a0ba32593b4fd76e3f2ced176e5b3bbd952 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 3 May 2023 09:09:07 +0300 Subject: Initialized variable Signed-off-by: Trial97 --- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index ef3200a2..90922c8e 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -170,7 +170,7 @@ void ResourceDownloadDialog::removeResource(const QString& pack_name) void ResourceDownloadDialog::setButtonStatus() { - bool selected; + auto selected = false; for (auto page : m_container->getPages()) { auto res = static_cast(page); selected = selected || res->hasSelectedPacks(); -- cgit From f7b912fc9d804902a725fa903be8574e1e202f69 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 4 May 2023 21:52:48 +0300 Subject: Fixed comments Signed-off-by: Trial97 --- .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 32 +++++++++++++++------- .../minecraft/mod/tasks/GetModDependenciesTask.h | 20 +++++++------- .../minecraft/mod/tasks/LocalModUpdateTask.cpp | 2 +- launcher/modplatform/ModIndex.h | 4 ++- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 23 ++++++++++++++-- launcher/ui/dialogs/ResourceDownloadDialog.h | 2 ++ launcher/ui/dialogs/ReviewMessageBox.cpp | 12 ++++++++ launcher/ui/dialogs/ReviewMessageBox.h | 1 + 8 files changed, 71 insertions(+), 25 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index e1760f16..2f08ae6d 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -1,8 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher - * Copyright (c) 2022 flowln - * Copyright (C) 2022 Sefa Eyeoglu + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 * * 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 @@ -47,7 +46,7 @@ static ResourceAPI::ModLoaderTypes mcLoaders(BaseInstance* inst) GetModDependenciesTask::GetModDependenciesTask(QObject* parent, BaseInstance* instance, ModFolderModel* folder, - QList> selected) + QList> selected) : SequentialTask(parent, "Get dependencies") , m_selected(selected) , m_flame_provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared(*instance), @@ -66,7 +65,7 @@ void GetModDependenciesTask::prepare() { for (auto sel : m_selected) { for (auto dep : getDependenciesForVersion(sel->version, sel->pack.provider)) { - addTask(prepareDependencyTask(dep, sel->pack.provider, 20)); + addTask(prepareDependencyTask(dep, sel->pack.provider, sel->pack.addonId, 20)); } } } @@ -81,7 +80,7 @@ QList GetModDependenciesTask::getDependenciesForVersion [&ver_dep](const ModPlatform::Dependency& i) { return i.addonId == ver_dep.addonId; }); dep == c_dependencies.end()) { // check the current dependency list if (auto dep = std::find_if(m_selected.begin(), m_selected.end(), - [&ver_dep, providerName](std::shared_ptr i) { + [&ver_dep, providerName](std::shared_ptr i) { return i->pack.addonId == ver_dep.addonId && i->pack.provider == providerName; }); dep == m_selected.end()) { // check the selected versions @@ -90,7 +89,15 @@ QList GetModDependenciesTask::getDependenciesForVersion return i->project_id == ver_dep.addonId && i->provider == providerName; }); dep == m_mods.end()) { // check the existing mods - c_dependencies.append(ver_dep); + if (auto dep = std::find_if(m_pack_dependencies.begin(), m_pack_dependencies.end(), + [&ver_dep, providerName](std::shared_ptr i) { + return i->pack.addonId == ver_dep.addonId && i->pack.provider == providerName; + }); + dep == m_pack_dependencies.end()) { // check loaded dependencies + c_dependencies.append(ver_dep); + } else { // already there just append the required_by + dep->get()->version.required_by.append(version.addonId); + } } } } @@ -101,11 +108,13 @@ QList GetModDependenciesTask::getDependenciesForVersion Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Dependency& dep, const ModPlatform::ResourceProvider providerName, + QVariant required_by, int level) { - auto pDep = std::make_shared(); + auto pDep = std::make_shared(); pDep->dependency = dep; pDep->pack = { dep.addonId, providerName }; + pDep->version.required_by.append(required_by); m_pack_dependencies.append(pDep); auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider; @@ -136,7 +145,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType }; ResourceAPI::DependencySearchCallbacks callbacks; - callbacks.on_succeed = [dep, provider, pDep, level, this](auto& doc, auto& pack) { + callbacks.on_succeed = [dep, provider, pDep, level, required_by, this](auto& doc, auto& pack) { try { QJsonArray arr; if (dep.version.length() != 0 && doc.isObject()) { @@ -144,6 +153,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen } else { arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); } + auto required_by = pDep->version.required_by; pDep->version = provider.mod->loadDependencyVersions(dep, arr); if (!pDep->version.addonId.isValid()) { qWarning() << "Error while reading mod version empty "; @@ -151,8 +161,10 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen return; } pDep->version.is_currently_selected = true; + pDep->version.required_by = required_by; pDep->pack.versions = { pDep->version }; pDep->pack.versionsLoaded = true; + } catch (const JSONValidationError& e) { qDebug() << doc; qWarning() << "Error while reading mod version: " << e.cause(); @@ -163,7 +175,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen return; } for (auto dep : getDependenciesForVersion(pDep->version, provider.name)) { - addTask(prepareDependencyTask(dep, provider.name, level - 1)); + addTask(prepareDependencyTask(dep, provider.name, pDep->pack.addonId, level - 1)); } }; diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index 40f80ebf..c8d378ef 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher - * Copyright (c) 2022 flowln + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 * * 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 @@ -38,12 +38,12 @@ class GetModDependenciesTask : public SequentialTask { public: using Ptr = shared_qobject_ptr; - struct PackDependecny { + struct PackDependency { ModPlatform::Dependency dependency; ModPlatform::IndexedPack pack; ModPlatform::IndexedVersion version; - PackDependecny(){}; - PackDependecny(const ModPlatform::IndexedPack& p, const ModPlatform::IndexedVersion& v) + PackDependency(){}; + PackDependency(const ModPlatform::IndexedPack& p, const ModPlatform::IndexedVersion& v) { pack = p; version = v; @@ -59,20 +59,20 @@ class GetModDependenciesTask : public SequentialTask { explicit GetModDependenciesTask(QObject* parent, BaseInstance* instance, ModFolderModel* folder, - QList> selected); + QList> selected); - auto getDependecies() const -> QList> { return m_pack_dependencies; } + auto getDependecies() const -> QList> { return m_pack_dependencies; } protected slots: - Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider, int); + Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider, QVariant, int); QList getDependenciesForVersion(const ModPlatform::IndexedVersion&, const ModPlatform::ResourceProvider providerName); void prepare(); private: - QList> m_pack_dependencies; + QList> m_pack_dependencies; QList> m_mods; - QList> m_selected; + QList> m_selected; Provider m_flame_provider; Provider m_modrinth_provider; diff --git a/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp b/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp index 6b139ca1..4352fad9 100644 --- a/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModUpdateTask.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 5ff7bbc9..5b439935 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln + * Copyright (c) 2023 Trial97 * * 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 @@ -78,6 +79,7 @@ struct IndexedVersion { // For internal use, not provided by APIs bool is_currently_selected = false; QString custom_target_folder; + QList required_by; }; struct ExtraPackData { diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 9c28acd9..ca2d409c 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -126,6 +126,22 @@ void ResourceDownloadDialog::connectButtons() static ModPlatform::ProviderCapabilities ProviderCaps; +QStringList ResourceDownloadDialog::getReqiredBy(QList req_by) +{ + auto req = QStringList(); + auto keys = m_selected.keys(); + for (auto r : req_by) { + for (auto& task : keys) { + auto selected = m_selected.constFind(task).value()->getPack(); + if (selected.addonId == r) { + req.append(selected.name); + break; + } + } + } + return req; +} + void ResourceDownloadDialog::confirm() { auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString())); @@ -162,8 +178,9 @@ void ResourceDownloadDialog::confirm() keys.sort(Qt::CaseInsensitive); for (auto& task : keys) { auto selected = m_selected.constFind(task).value(); + auto required_by = getReqiredBy(selected->getVersion().required_by); confirm_dialog->appendResource( - { task, selected->getFilename(), selected->getCustomPath(), ProviderCaps.name(selected->getProvider()) }); + { task, selected->getFilename(), selected->getCustomPath(), ProviderCaps.name(selected->getProvider()), required_by }); } if (confirm_dialog->exec()) { @@ -261,10 +278,10 @@ GetModDependenciesTask::Ptr ModDownloadDialog::getModDependenciesTask() { if (auto model = dynamic_cast(getBaseModel().get()); model) { auto keys = m_selected.keys(); - QList> selectedVers; + QList> selectedVers; for (auto& task : keys) { auto selected = m_selected.constFind(task).value(); - selectedVers.append(std::make_shared(selected->getPack(), selected->getVersion())); + selectedVers.append(std::make_shared(selected->getPack(), selected->getVersion())); } return makeShared(this, m_instance, model, selectedVers); diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index 9610c8b3..1145f63a 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -83,6 +83,8 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { [[nodiscard]] virtual GetModDependenciesTask::Ptr getModDependenciesTask() { return nullptr; } + QStringList getReqiredBy(QList req_by); + protected: const std::shared_ptr m_base_model; diff --git a/launcher/ui/dialogs/ReviewMessageBox.cpp b/launcher/ui/dialogs/ReviewMessageBox.cpp index 86e68aae..e18519c3 100644 --- a/launcher/ui/dialogs/ReviewMessageBox.cpp +++ b/launcher/ui/dialogs/ReviewMessageBox.cpp @@ -60,6 +60,18 @@ void ReviewMessageBox::appendResource(ResourceInformation&& info) itemTop->insertChildren(childIndx++, { providerItem }); + if (!info.required_by.isEmpty()) { + auto requiredByItem = new QTreeWidgetItem(itemTop); + QString req; + if (info.required_by.length() == 1) + req = info.required_by.back(); + else + req = QString("[%1]").arg(info.required_by.join(", ")); + requiredByItem->setText(0, tr("Required by: %1").arg(req)); + + itemTop->insertChildren(childIndx++, { requiredByItem }); + } + ui->modTreeWidget->addTopLevelItem(itemTop); } diff --git a/launcher/ui/dialogs/ReviewMessageBox.h b/launcher/ui/dialogs/ReviewMessageBox.h index 9579da33..a520cc2a 100644 --- a/launcher/ui/dialogs/ReviewMessageBox.h +++ b/launcher/ui/dialogs/ReviewMessageBox.h @@ -17,6 +17,7 @@ class ReviewMessageBox : public QDialog { QString filename; QString custom_file_path{}; QString provider; + QStringList required_by; }; void appendResource(ResourceInformation&& info); -- cgit From 107b4702895afdbaf9912006d91c910bb6634361 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 4 May 2023 23:54:46 +0300 Subject: Updated required_by as dependency Signed-off-by: Trial97 --- .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 12 +++--------- launcher/minecraft/mod/tasks/GetModDependenciesTask.h | 2 +- launcher/modplatform/ModIndex.h | 1 - launcher/ui/dialogs/ResourceDownloadDialog.cpp | 19 ++++++++++--------- launcher/ui/dialogs/ReviewMessageBox.cpp | 17 +++++++++++------ 5 files changed, 25 insertions(+), 26 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 2f08ae6d..96d343a1 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -65,7 +65,7 @@ void GetModDependenciesTask::prepare() { for (auto sel : m_selected) { for (auto dep : getDependenciesForVersion(sel->version, sel->pack.provider)) { - addTask(prepareDependencyTask(dep, sel->pack.provider, sel->pack.addonId, 20)); + addTask(prepareDependencyTask(dep, sel->pack.provider, 20)); } } } @@ -95,8 +95,6 @@ QList GetModDependenciesTask::getDependenciesForVersion }); dep == m_pack_dependencies.end()) { // check loaded dependencies c_dependencies.append(ver_dep); - } else { // already there just append the required_by - dep->get()->version.required_by.append(version.addonId); } } } @@ -108,13 +106,11 @@ QList GetModDependenciesTask::getDependenciesForVersion Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Dependency& dep, const ModPlatform::ResourceProvider providerName, - QVariant required_by, int level) { auto pDep = std::make_shared(); pDep->dependency = dep; pDep->pack = { dep.addonId, providerName }; - pDep->version.required_by.append(required_by); m_pack_dependencies.append(pDep); auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider; @@ -145,7 +141,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType }; ResourceAPI::DependencySearchCallbacks callbacks; - callbacks.on_succeed = [dep, provider, pDep, level, required_by, this](auto& doc, auto& pack) { + callbacks.on_succeed = [dep, provider, pDep, level, this](auto& doc, auto& pack) { try { QJsonArray arr; if (dep.version.length() != 0 && doc.isObject()) { @@ -153,7 +149,6 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen } else { arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); } - auto required_by = pDep->version.required_by; pDep->version = provider.mod->loadDependencyVersions(dep, arr); if (!pDep->version.addonId.isValid()) { qWarning() << "Error while reading mod version empty "; @@ -161,7 +156,6 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen return; } pDep->version.is_currently_selected = true; - pDep->version.required_by = required_by; pDep->pack.versions = { pDep->version }; pDep->pack.versionsLoaded = true; @@ -175,7 +169,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen return; } for (auto dep : getDependenciesForVersion(pDep->version, provider.name)) { - addTask(prepareDependencyTask(dep, provider.name, pDep->pack.addonId, level - 1)); + addTask(prepareDependencyTask(dep, provider.name, level - 1)); } }; diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index c8d378ef..aca3c004 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -64,7 +64,7 @@ class GetModDependenciesTask : public SequentialTask { auto getDependecies() const -> QList> { return m_pack_dependencies; } protected slots: - Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider, QVariant, int); + Task::Ptr prepareDependencyTask(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider, int); QList getDependenciesForVersion(const ModPlatform::IndexedVersion&, const ModPlatform::ResourceProvider providerName); void prepare(); diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index edf92416..a19fc0eb 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -78,7 +78,6 @@ struct IndexedVersion { // For internal use, not provided by APIs bool is_currently_selected = false; - QList required_by; }; struct ExtraPackData { diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index c74aaace..b65f2ffd 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -125,16 +125,17 @@ void ResourceDownloadDialog::connectButtons() static ModPlatform::ProviderCapabilities ProviderCaps; -QStringList getReqiredBy(QList tasks, QList req_by) +QStringList getReqiredBy(QList tasks, QVariant addonId) { auto req = QStringList(); - for (auto r : req_by) { - for (auto& task : tasks) { - auto selected = task->getPack(); - if (selected.addonId == r) { - req.append(selected.name); - break; - } + for (auto& task : tasks) { + auto deps = task->getVersion().dependencies; + if (auto dep = std::find_if(deps.begin(), deps.end(), + [addonId](const ModPlatform::Dependency& d) { + return d.addonId == addonId && d.type == ModPlatform::DependencyType::REQUIRED; + }); + dep) { + req.append(task->getName()); } } return req; @@ -178,7 +179,7 @@ void ResourceDownloadDialog::confirm() }); for (auto& task : selected) { confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath(), - ProviderCaps.name(task->getProvider()), getReqiredBy(selected, task->getVersion().required_by) }); + ProviderCaps.name(task->getProvider()), getReqiredBy(selected, task->getPack().addonId) }); } if (confirm_dialog->exec()) { diff --git a/launcher/ui/dialogs/ReviewMessageBox.cpp b/launcher/ui/dialogs/ReviewMessageBox.cpp index e18519c3..7b33765f 100644 --- a/launcher/ui/dialogs/ReviewMessageBox.cpp +++ b/launcher/ui/dialogs/ReviewMessageBox.cpp @@ -62,12 +62,17 @@ void ReviewMessageBox::appendResource(ResourceInformation&& info) if (!info.required_by.isEmpty()) { auto requiredByItem = new QTreeWidgetItem(itemTop); - QString req; - if (info.required_by.length() == 1) - req = info.required_by.back(); - else - req = QString("[%1]").arg(info.required_by.join(", ")); - requiredByItem->setText(0, tr("Required by: %1").arg(req)); + if (info.required_by.length() == 1) { + requiredByItem->setText(0, tr("Required by: %1").arg(info.required_by.back())); + } else { + requiredByItem->setText(0, tr("Required by:")); + auto i = 0; + for (auto req : info.required_by) { + auto reqItem = new QTreeWidgetItem(requiredByItem); + reqItem->setText(0, req); + reqItem->insertChildren(i++, { reqItem }); + } + } itemTop->insertChildren(childIndx++, { requiredByItem }); } -- cgit From 469ef3e06d93f9b00d7c23ac03f4eff07385e446 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 5 May 2023 00:04:24 +0300 Subject: Fixed code error Signed-off-by: Trial97 --- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index b65f2ffd..18106701 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -134,7 +134,7 @@ QStringList getReqiredBy(QList tasks, Q [addonId](const ModPlatform::Dependency& d) { return d.addonId == addonId && d.type == ModPlatform::DependencyType::REQUIRED; }); - dep) { + dep != deps.end()) { req.append(task->getName()); } } -- cgit From ec157b766efd9eb781a8ca85fb9c28674e073da0 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 4 May 2023 23:42:42 -0700 Subject: feat(mod parsing): load extra mod details - (image, license, issuetracker) Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/Mod.cpp | 46 +++++ launcher/minecraft/mod/Mod.h | 20 ++ launcher/minecraft/mod/ModDetails.h | 90 +++++++++ launcher/minecraft/mod/tasks/LocalModParseTask.cpp | 210 +++++++++++++++++++++ launcher/minecraft/mod/tasks/LocalModParseTask.h | 3 + 5 files changed, 369 insertions(+) (limited to 'launcher') diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index c495cd47..392f7f2e 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -41,9 +41,11 @@ #include #include +#include "MTPixmapCache.h" #include "MetadataHandler.h" #include "Version.h" #include "minecraft/mod/ModDetails.h" +#include "minecraft/mod/tasks/LocalModParseTask.h" static ModPlatform::ProviderCapabilities ProviderCaps; @@ -201,6 +203,9 @@ void Mod::finishResolvingWithDetails(ModDetails&& details) m_local_details = std::move(details); if (metadata) setMetadata(std::move(metadata)); + if (!iconPath().isEmpty()) { + m_pack_image_cache_key.was_read_attempt = false; + } }; auto Mod::provider() const -> std::optional @@ -210,6 +215,47 @@ auto Mod::provider() const -> std::optional return {}; } + +void Mod::setIcon(QImage new_image) const +{ + QMutexLocker locker(&m_data_lock); + + Q_ASSERT(!new_image.isNull()); + + if (m_pack_image_cache_key.key.isValid()) + PixmapCache::remove(m_pack_image_cache_key.key); + + // scale the image to avoid flooding the pixmapcache + auto pixmap = QPixmap::fromImage(new_image.scaled({128, 128}, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + + m_pack_image_cache_key.key = PixmapCache::insert(pixmap); + m_pack_image_cache_key.was_ever_used = true; + m_pack_image_cache_key.was_read_attempt = true; +} + +QPixmap Mod::icon(QSize size, Qt::AspectRatioMode mode) const +{ + QPixmap cached_image; + if (PixmapCache::find(m_pack_image_cache_key.key, &cached_image)) { + if (size.isNull()) + return cached_image; + return cached_image.scaled(size, mode); + } + + // No valid image we can get + if ((!m_pack_image_cache_key.was_ever_used && m_pack_image_cache_key.was_read_attempt) || iconPath().isEmpty()) + return {}; + + if (m_pack_image_cache_key.was_ever_used) { + qDebug() << "Mod" << name() << "Had it's icon evicted form the cache. reloading..."; + PixmapCache::markCacheMissByEviciton(); + } + // Imaged got evicted from the cache or an attmept to load it has not been made. load it and retry. + m_pack_image_cache_key.was_read_attempt = true; + ModUtils::loadIconFile(*this); + return icon(size); +} + bool Mod::valid() const { return !m_local_details.mod_id.isEmpty(); diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index c4032538..4be0842f 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -38,6 +38,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -65,6 +69,13 @@ public: auto status() const -> ModStatus; auto provider() const -> std::optional; + /** Get the intneral path to the mod's icon file*/ + QString iconPath() const { return m_local_details.icon_file; }; + /** Gets the icon of the mod, converted to a QPixmap for drawing, and scaled to size. */ + [[nodiscard]] QPixmap icon(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const; + /** Thread-safe. */ + void setIcon(QImage new_image) const; + auto metadata() -> std::shared_ptr; auto metadata() const -> const std::shared_ptr; @@ -85,4 +96,13 @@ public: protected: ModDetails m_local_details; + + mutable QMutex m_data_lock; + + struct { + QPixmapCache::Key key; + bool was_ever_used = false; + bool was_read_attempt = false; + } mutable m_pack_image_cache_key; + }; diff --git a/launcher/minecraft/mod/ModDetails.h b/launcher/minecraft/mod/ModDetails.h index 176e4fc1..eb3770d6 100644 --- a/launcher/minecraft/mod/ModDetails.h +++ b/launcher/minecraft/mod/ModDetails.h @@ -39,6 +39,7 @@ #include #include +#include #include "minecraft/mod/MetadataHandler.h" @@ -49,6 +50,77 @@ enum class ModStatus { Unknown, // Default status }; +struct ModLicense { + QString name = {}; + QString id = {}; + QString url = {}; + QString description = {}; + + ModLicense() {} + + ModLicense(const QString license) { + // FIXME: come up with a better license parseing. + // handle SPDX identifiers? https://spdx.org/licenses/ + auto parts = license.split(' '); + QStringList notNameParts = {}; + for (auto part : parts) { + auto url = QUrl::fromUserInput(part); + if (url.isValid()) { + this->url = url.toString(); + notNameParts.append(part); + continue; + } + } + + for (auto part : notNameParts) { + parts.removeOne(part); + } + + auto licensePart = parts.join(' '); + this->name = licensePart; + this->description = licensePart; + + if (parts.size() == 1) { + this->id = parts.first(); + } + + } + + ModLicense(const QString name, const QString id, const QString url, const QString description) { + this->name = name; + this->id = id; + this->url = url; + this->description = description; + } + + ModLicense(const ModLicense& other) + : name(other.name) + , id(other.id) + , url(other.url) + , description(other.description) + {} + + ModLicense& operator=(const ModLicense& other) + { + this->name = other.name; + this->id = other.id; + this->url = other.url; + this->description = other.description; + + return *this; + } + + ModLicense& operator=(const ModLicense&& other) + { + this->name = other.name; + this->id = other.id; + this->url = other.url; + this->description = other.description; + + return *this; + } +}; + struct ModDetails { /* Mod ID as defined in the ModLoader-specific metadata */ @@ -72,6 +144,15 @@ struct ModDetails /* List of the author's names */ QStringList authors = {}; + /* Issue Tracker URL */ + QString issue_tracker = {}; + + /* License */ + QList licenses = {}; + + /* Path of mod logo */ + QString icon_file = {}; + /* Installation status of the mod */ ModStatus status = ModStatus::Unknown; @@ -89,6 +170,9 @@ struct ModDetails , homeurl(other.homeurl) , description(other.description) , authors(other.authors) + , issue_tracker(other.issue_tracker) + , licenses(other.licenses) + , icon_file(other.icon_file) , status(other.status) {} @@ -101,6 +185,9 @@ struct ModDetails this->homeurl = other.homeurl; this->description = other.description; this->authors = other.authors; + this->issue_tracker = other.issue_tracker; + this->licenses = other.licenses; + this->icon_file = other.icon_file; this->status = other.status; return *this; @@ -115,6 +202,9 @@ struct ModDetails this->homeurl = other.homeurl; this->description = other.description; this->authors = other.authors; + this->issue_tracker = other.issue_tracker; + this->licenses = other.licenses; + this->icon_file = other.icon_file; this->status = other.status; return *this; diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp index 5342d693..084b0afb 100644 --- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp @@ -52,6 +52,10 @@ ModDetails ReadMCModInfo(QByteArray contents) authors = firstObj.value("authors").toArray(); } + if (firstObj.contains("logoFile")) { + details.icon_file = firstObj.value("logoFile").toString(); + } + for (auto author : authors) { details.authors.append(author.toString()); } @@ -166,6 +170,30 @@ ModDetails ReadMCModTOML(QByteArray contents) } details.homeurl = homeurl; + QString issueTrackerURL = ""; + if (auto issueTrackerURLDatum = tomlData["issueTrackerURL"].as_string()) { + issueTrackerURL = QString::fromStdString(issueTrackerURLDatum->get()); + } else if (auto issueTrackerURLDatum = (*modsTable)["issueTrackerURL"].as_string()) { + issueTrackerURL = QString::fromStdString(issueTrackerURLDatum->get()); + } + details.issue_tracker = issueTrackerURL; + + QString license = ""; + if (auto licenseDatum = tomlData["license"].as_string()) { + license = QString::fromStdString(licenseDatum->get()); + } else if (auto licenseDatum =(*modsTable)["license"].as_string()) { + license = QString::fromStdString(licenseDatum->get()); + } + details.licenses.push_back(ModLicense(license)); + + QString logoFile = ""; + if (auto logoFileDatum = tomlData["logoFile"].as_string()) { + logoFile = QString::fromStdString(logoFileDatum->get()); + } else if (auto logoFileDatum =(*modsTable)["logoFile"].as_string()) { + logoFile = QString::fromStdString(logoFileDatum->get()); + } + details.icon_file = logoFile; + return details; } @@ -201,6 +229,57 @@ ModDetails ReadFabricModInfo(QByteArray contents) if (contact.contains("homepage")) { details.homeurl = contact.value("homepage").toString(); } + if (contact.contains("issues")) { + details.issue_tracker = contact.value("issues").toString(); + } + } + + if (object.contains("license")) { + auto license = object.value("license"); + if (license.isArray()) { + for (auto l : license.toArray()) { + if (l.isString()) { + details.licenses.append(ModLicense(l.toString())); + } else if (l.isObject()) { + auto obj = l.toObject(); + details.licenses.append(ModLicense(obj.value("name").toString(), obj.value("id").toString(), + obj.value("url").toString(), obj.value("description").toString())); + } + } + } else if (license.isString()) { + details.licenses.append(ModLicense(license.toString())); + } else if (license.isObject()) { + auto obj = license.toObject(); + details.licenses.append(ModLicense(obj.value("name").toString(), obj.value("id").toString(), obj.value("url").toString(), + obj.value("description").toString())); + } + } + + if (object.contains("icon")) { + auto icon = object.value("icon"); + if (icon.isObject()) { + auto obj = icon.toObject(); + // take the largest icon + int largest = 0; + for (auto key : obj.keys()) { + auto size = key.split('x').first().toInt(); + if (size > largest) { + largest = size; + } + } + if (largest > 0) { + auto key = QString::number(largest) + "x" + largest; + details.icon_file = obj.value(key).toString(); + } else { // parsing the sizes failed + // take the first + for (auto icon : obj) { + details.icon_file = icon.toString(); + break; + } + } + } else if (icon.isString()) { + details.icon_file = icon.toString(); + } } } return details; @@ -238,6 +317,58 @@ ModDetails ReadQuiltModInfo(QByteArray contents) if (modContact.contains("homepage")) { details.homeurl = Json::requireString(modContact.value("homepage")); } + if (modContact.contains("issues")) { + details.issue_tracker = Json::requireString(modContact.value("issues")); + } + + if (modMetadata.contains("license")) { + auto license = modMetadata.value("license"); + if (license.isArray()) { + for (auto l : license.toArray()) { + if (l.isString()) { + details.licenses.append(ModLicense(l.toString())); + } else if (l.isObject()) { + auto obj = l.toObject(); + details.licenses.append(ModLicense(obj.value("name").toString(), obj.value("id").toString(), + obj.value("url").toString(), obj.value("description").toString())); + } + } + } else if (license.isString()) { + details.licenses.append(ModLicense(license.toString())); + } else if (license.isObject()) { + auto obj = license.toObject(); + details.licenses.append(ModLicense(obj.value("name").toString(), obj.value("id").toString(), obj.value("url").toString(), + obj.value("description").toString())); + } + } + + if (modMetadata.contains("icon")) { + auto icon = modMetadata.value("icon"); + if (icon.isObject()) { + auto obj = icon.toObject(); + // take the largest icon + int largest = 0; + for (auto key : obj.keys()) { + auto size = key.split('x').first().toInt(); + if (size > largest) { + largest = size; + } + } + if (largest > 0) { + auto key = QString::number(largest) + "x" + largest; + details.icon_file = obj.value(key).toString(); + } else { // parsing the sizes failed + // take the first + for (auto icon : obj) { + details.icon_file = icon.toString(); + break; + } + } + } else if (icon.isString()) { + details.icon_file = icon.toString(); + } + } + } return details; } @@ -515,6 +646,85 @@ bool validate(QFileInfo file) return ModUtils::process(mod, ProcessingLevel::BasicInfoOnly) && mod.valid(); } +bool processIconPNG(const Mod& mod, QByteArray&& raw_data) +{ + auto img = QImage::fromData(raw_data); + if (!img.isNull()) { + mod.setIcon(img); + } else { + qWarning() << "Failed to parse mod logo:" << mod.iconPath() << "from" << mod.name(); + return false; + } + return true; +} + +bool loadIconFile(const Mod& mod) { + if (mod.iconPath().isEmpty()) { + qWarning() << "No Iconfile set, be sure to parse the mod first"; + return false; + } + + auto png_invalid = [&mod]() { + qWarning() << "Mod at" << mod.fileinfo().filePath() << "does not have a valid icon"; + return false; + }; + + switch (mod.type()) { + case ResourceType::FOLDER: + { + QFileInfo icon_info(FS::PathCombine(mod.fileinfo().filePath(), mod.iconPath())); + if (icon_info.exists() && icon_info.isFile()) { + QFile icon(icon_info.filePath()); + if (!icon.open(QIODevice::ReadOnly)) + return false; + auto data = icon.readAll(); + + bool icon_result = ModUtils::processIconPNG(mod, std::move(data)); + + icon.close(); + + if (!icon_result) { + return png_invalid(); // icon invalid + } + } + } + case ResourceType::ZIPFILE: + { + QuaZip zip(mod.fileinfo().filePath()); + if (!zip.open(QuaZip::mdUnzip)) + return false; + + QuaZipFile file(&zip); + + if (zip.setCurrentFile(mod.iconPath())) { + if (!file.open(QIODevice::ReadOnly)) { + qCritical() << "Failed to open file in zip."; + zip.close(); + return png_invalid(); + } + + auto data = file.readAll(); + + bool icon_result = ModUtils::processIconPNG(mod, std::move(data)); + + file.close(); + if (!icon_result) { + return png_invalid(); // icon png invalid + } + } else { + return png_invalid(); // could not set icon as current file. + } + } + case ResourceType::LITEMOD: + { + return false; // can lightmods even have icons? + } + default: + qWarning() << "Invalid type for mod, can not load icon."; + return false; + } +} + } // namespace ModUtils LocalModParseTask::LocalModParseTask(int token, ResourceType type, const QFileInfo& modFile) diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.h b/launcher/minecraft/mod/tasks/LocalModParseTask.h index 38dae135..a0321709 100644 --- a/launcher/minecraft/mod/tasks/LocalModParseTask.h +++ b/launcher/minecraft/mod/tasks/LocalModParseTask.h @@ -25,6 +25,9 @@ bool processLitemod(Mod& mod, ProcessingLevel level = ProcessingLevel::Full); /** Checks whether a file is valid as a mod or not. */ bool validate(QFileInfo file); + +bool processIconPNG(const Mod& mod, QByteArray&& raw_data); +bool loadIconFile(const Mod& mod); } // namespace ModUtils class LocalModParseTask : public Task { -- cgit From 9913080a829acb4ca921c3a68e0caefad0ebcaa1 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 4 May 2023 23:44:28 -0700 Subject: feat(modpage): mod icon in description and column Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/ModFolderModel.cpp | 8 ++++++-- launcher/minecraft/mod/ModFolderModel.h | 1 + launcher/ui/widgets/InfoFrame.cpp | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 6ae25d33..8a58b9d7 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -57,7 +57,7 @@ ModFolderModel::ModFolderModel(const QString& dir, std::shared_ptr instance, bool is_indexed, bool create_dir) : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed) { - m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER }; + m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER, SortType::NAME }; } QVariant ModFolderModel::data(const QModelIndex &index, int role) const @@ -118,7 +118,9 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const case Qt::DecorationRole: { if (column == NAME_COLUMN && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink())) return APPLICATION->getThemedIcon("status-yellow"); - + if (column == ImageColumn) { + return at(row)->icon(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding); + } return {}; } case Qt::CheckStateRole: @@ -151,6 +153,8 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in return tr("Last changed"); case ProviderColumn: return tr("Provider"); + case ImageColumn: + return tr("Image"); default: return QVariant(); } diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index 46f5087f..20018e9c 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -68,6 +68,7 @@ public: VersionColumn, DateColumn, ProviderColumn, + ImageColumn, NUM_COLUMNS }; enum ModStatusAction { diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index fdc581b4..6f4036a2 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -88,7 +88,7 @@ void InfoFrame::updateWithMod(Mod const& m) setDescription(m.description()); } - setImage(); + setImage(m.icon({64,64})); } void InfoFrame::updateWithResource(const Resource& resource) -- cgit From d384d991fad80cdadf6486d61e5c06a692a0031d Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 4 May 2023 23:45:24 -0700 Subject: feat(texturepackPage): icon column Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/TexturePack.cpp | 25 +++-- launcher/minecraft/mod/TexturePack.h | 6 +- launcher/minecraft/mod/TexturePackFolderModel.cpp | 102 ++++++++++++++++++++- launcher/minecraft/mod/TexturePackFolderModel.h | 20 ++++ .../mod/tasks/LocalTexturePackParseTask.cpp | 67 +++++++++++++- .../mod/tasks/LocalTexturePackParseTask.h | 5 +- 6 files changed, 211 insertions(+), 14 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/TexturePack.cpp b/launcher/minecraft/mod/TexturePack.cpp index 99d55584..8ff1e852 100644 --- a/launcher/minecraft/mod/TexturePack.cpp +++ b/launcher/minecraft/mod/TexturePack.cpp @@ -23,6 +23,8 @@ #include #include +#include "MTPixmapCache.h" + #include "minecraft/mod/tasks/LocalTexturePackParseTask.h" void TexturePack::setDescription(QString new_description) @@ -32,34 +34,41 @@ void TexturePack::setDescription(QString new_description) m_description = new_description; } -void TexturePack::setImage(QImage new_image) +void TexturePack::setImage(QImage new_image) const { QMutexLocker locker(&m_data_lock); Q_ASSERT(!new_image.isNull()); if (m_pack_image_cache_key.key.isValid()) - QPixmapCache::remove(m_pack_image_cache_key.key); + PixmapCache::remove(m_pack_image_cache_key.key); + + // scale the image to avoid flooding the pixmapcache + auto pixmap = QPixmap::fromImage(new_image.scaled(QSize(128, 128), Qt::AspectRatioMode::KeepAspectRatioByExpanding)); - m_pack_image_cache_key.key = QPixmapCache::insert(QPixmap::fromImage(new_image)); + m_pack_image_cache_key.key = PixmapCache::insert(pixmap); m_pack_image_cache_key.was_ever_used = true; } -QPixmap TexturePack::image(QSize size) +QPixmap TexturePack::image(QSize size, Qt::AspectRatioMode mode) const { QPixmap cached_image; - if (QPixmapCache::find(m_pack_image_cache_key.key, &cached_image)) { + if (PixmapCache::find(m_pack_image_cache_key.key, &cached_image)) { if (size.isNull()) return cached_image; - return cached_image.scaled(size); + return cached_image.scaled(size, mode); } // No valid image we can get - if (!m_pack_image_cache_key.was_ever_used) + if (!m_pack_image_cache_key.was_ever_used) { return {}; + } else { + qDebug() << "Texture Pack" << name() << "Had it's image evicted from the cache. reloading..."; + PixmapCache::markCacheMissByEviciton(); + } // Imaged got evicted from the cache. Re-process it and retry. - TexturePackUtils::process(*this); + TexturePackUtils::processPackPNG(*this); return image(size); } diff --git a/launcher/minecraft/mod/TexturePack.h b/launcher/minecraft/mod/TexturePack.h index 81bd5c69..57700565 100644 --- a/launcher/minecraft/mod/TexturePack.h +++ b/launcher/minecraft/mod/TexturePack.h @@ -40,13 +40,13 @@ class TexturePack : public Resource { [[nodiscard]] QString description() const { return m_description; } /** Gets the image of the texture pack, converted to a QPixmap for drawing, and scaled to size. */ - [[nodiscard]] QPixmap image(QSize size); + [[nodiscard]] QPixmap image(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const; /** Thread-safe. */ void setDescription(QString new_description); /** Thread-safe. */ - void setImage(QImage new_image); + void setImage(QImage new_image) const; bool valid() const override; @@ -65,5 +65,5 @@ class TexturePack : public Resource { struct { QPixmapCache::Key key; bool was_ever_used = false; - } m_pack_image_cache_key; + } mutable m_pack_image_cache_key; }; diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index 1e218537..dd93a469 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -33,6 +33,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include + +#include "Application.h" #include "TexturePackFolderModel.h" @@ -41,7 +44,9 @@ TexturePackFolderModel::TexturePackFolderModel(const QString& dir, std::shared_ptr instance) : ResourceFolderModel(QDir(dir), instance) -{} +{ + m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE, SortType::NAME }; +} Task* TexturePackFolderModel::createUpdateTask() { @@ -52,3 +57,98 @@ Task* TexturePackFolderModel::createParseTask(Resource& resource) { return new LocalTexturePackParseTask(m_next_resolution_ticket, static_cast(resource)); } + + +QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const +{ + if (!validateIndex(index)) + return {}; + + int row = index.row(); + int column = index.column(); + + switch (role) { + case Qt::DisplayRole: + switch (column) { + case NameColumn: + return m_resources[row]->name(); + case DateColumn: + return m_resources[row]->dateTimeChanged(); + default: + return {}; + } + case Qt::ToolTipRole: + if (column == NameColumn) { + if (at(row)->isSymLinkUnder(instDirPath())) { + return m_resources[row]->internal_id() + + tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." + "\nCanonical Path: %1") + .arg(at(row)->fileinfo().canonicalFilePath());; + } + if (at(row)->isMoreThanOneHardLink()) { + return m_resources[row]->internal_id() + + tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original."); + } + } + + return m_resources[row]->internal_id(); + case Qt::DecorationRole: { + if (column == NameColumn && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink())) + return APPLICATION->getThemedIcon("status-yellow"); + if (column == ImageColumn) { + return at(row)->image(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding); + } + return {}; + } + case Qt::CheckStateRole: + switch (column) { + case ActiveColumn: + return m_resources[row]->enabled() ? Qt::Checked : Qt::Unchecked; + default: + return {}; + } + default: + return {}; + } +} + +QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + switch (role) { + case Qt::DisplayRole: + switch (section) { + case NameColumn: + return tr("Name"); + case DateColumn: + return tr("Last modified"); + case ImageColumn: + return tr("Image"); + default: + return {}; + } + case Qt::ToolTipRole: { + switch (section) { + case ActiveColumn: + //: Here, resource is a generic term for external resources, like Mods, Resource Packs, Shader Packs, etc. + return tr("Is the resource enabled?"); + case NameColumn: + //: Here, resource is a generic term for external resources, like Mods, Resource Packs, Shader Packs, etc. + return tr("The name of the resource."); + case DateColumn: + //: Here, resource is a generic term for external resources, like Mods, Resource Packs, Shader Packs, etc. + return tr("The date and time this resource was last changed (or added)."); + default: + return {}; + } + } + default: + break; + } + + return {}; +} + +int TexturePackFolderModel::columnCount(const QModelIndex& parent) const +{ + return parent.isValid() ? 0 : NUM_COLUMNS; +} \ No newline at end of file diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h index 246997bd..4467691a 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.h +++ b/launcher/minecraft/mod/TexturePackFolderModel.h @@ -38,12 +38,32 @@ #include "ResourceFolderModel.h" +#include "TexturePack.h" + class TexturePackFolderModel : public ResourceFolderModel { Q_OBJECT public: + + enum Columns + { + ActiveColumn = 0, + NameColumn, + DateColumn, + ImageColumn, + NUM_COLUMNS + }; + explicit TexturePackFolderModel(const QString &dir, std::shared_ptr instance); + + [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + + [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + [[nodiscard]] int columnCount(const QModelIndex &parent) const override; + [[nodiscard]] Task* createUpdateTask() override; [[nodiscard]] Task* createParseTask(Resource&) override; + + RESOURCE_HELPERS(TexturePack) }; diff --git a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp index 38f1d7c1..a72e8115 100644 --- a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp @@ -131,6 +131,7 @@ bool processZIP(TexturePack& pack, ProcessingLevel level) bool packPNG_result = TexturePackUtils::processPackPNG(pack, std::move(data)); file.close(); + zip.close(); if (!packPNG_result) { return false; } @@ -147,7 +148,7 @@ bool processPackTXT(TexturePack& pack, QByteArray&& raw_data) return true; } -bool processPackPNG(TexturePack& pack, QByteArray&& raw_data) +bool processPackPNG(const TexturePack& pack, QByteArray&& raw_data) { auto img = QImage::fromData(raw_data); if (!img.isNull()) { @@ -159,6 +160,70 @@ bool processPackPNG(TexturePack& pack, QByteArray&& raw_data) return true; } +bool processPackPNG(const TexturePack& pack) +{ + auto png_invalid = [&pack]() { + qWarning() << "Texture pack at" << pack.fileinfo().filePath() << "does not have a valid pack.png"; + return false; + }; + + switch (pack.type()) { + case ResourceType::FOLDER: + { + QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png")); + if (image_file_info.exists() && image_file_info.isFile()) { + QFile pack_png_file(image_file_info.filePath()); + if (!pack_png_file.open(QIODevice::ReadOnly)) + return png_invalid(); // can't open pack.png file + + auto data = pack_png_file.readAll(); + + bool pack_png_result = TexturePackUtils::processPackPNG(pack, std::move(data)); + + pack_png_file.close(); + if (!pack_png_result) { + return png_invalid(); // pack.png invalid + } + } else { + return png_invalid(); // pack.png does not exists or is not a valid file. + } + } + case ResourceType::ZIPFILE: + { + Q_ASSERT(pack.type() == ResourceType::ZIPFILE); + + QuaZip zip(pack.fileinfo().filePath()); + if (!zip.open(QuaZip::mdUnzip)) + return false; // can't open zip file + + QuaZipFile file(&zip); + if (zip.setCurrentFile("pack.png")) { + if (!file.open(QIODevice::ReadOnly)) { + qCritical() << "Failed to open file in zip."; + zip.close(); + return png_invalid(); + } + + auto data = file.readAll(); + + bool pack_png_result = TexturePackUtils::processPackPNG(pack, std::move(data)); + + file.close(); + if (!pack_png_result) { + zip.close(); + return png_invalid(); // pack.png invalid + } + } else { + zip.close(); + return png_invalid(); // could not set pack.mcmeta as current file. + } + } + default: + qWarning() << "Invalid type for resource pack parse task!"; + return false; + } +} + bool validate(QFileInfo file) { TexturePack rp{ file }; diff --git a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h index 1589f8cb..6b91565a 100644 --- a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h +++ b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h @@ -36,7 +36,10 @@ bool processZIP(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full bool processFolder(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full); bool processPackTXT(TexturePack& pack, QByteArray&& raw_data); -bool processPackPNG(TexturePack& pack, QByteArray&& raw_data); +bool processPackPNG(const TexturePack& pack, QByteArray&& raw_data); + +/// processes ONLY the pack.png (rest of the pack may be invalid) +bool processPackPNG(const TexturePack& pack); /** Checks whether a file is valid as a texture pack or not. */ bool validate(QFileInfo file); -- cgit From ed185f047fa2efc80cc622165583e57f21ffa560 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 4 May 2023 23:46:00 -0700 Subject: feat(resourcePackPage): icon column Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/ResourcePack.cpp | 19 ++++-- launcher/minecraft/mod/ResourcePack.h | 6 +- launcher/minecraft/mod/ResourcePackFolderModel.cpp | 21 +++++-- launcher/minecraft/mod/ResourcePackFolderModel.h | 1 + .../mod/tasks/LocalResourcePackParseTask.cpp | 67 +++++++++++++++++++++- .../mod/tasks/LocalResourcePackParseTask.h | 5 +- 6 files changed, 103 insertions(+), 16 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp index 876d5c3e..5fc9d7a6 100644 --- a/launcher/minecraft/mod/ResourcePack.cpp +++ b/launcher/minecraft/mod/ResourcePack.cpp @@ -39,7 +39,7 @@ void ResourcePack::setDescription(QString new_description) m_description = new_description; } -void ResourcePack::setImage(QImage new_image) +void ResourcePack::setImage(QImage new_image) const { QMutexLocker locker(&m_data_lock); @@ -48,7 +48,10 @@ void ResourcePack::setImage(QImage new_image) if (m_pack_image_cache_key.key.isValid()) PixmapCache::instance().remove(m_pack_image_cache_key.key); - m_pack_image_cache_key.key = PixmapCache::instance().insert(QPixmap::fromImage(new_image)); + // scale the image to avoid flooding the pixmapcache + auto pixmap = QPixmap::fromImage(new_image.scaled(QSize(128, 128), Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + + m_pack_image_cache_key.key = PixmapCache::instance().insert(pixmap); m_pack_image_cache_key.was_ever_used = true; // This can happen if the pixmap is too big to fit in the cache :c @@ -58,21 +61,25 @@ void ResourcePack::setImage(QImage new_image) } } -QPixmap ResourcePack::image(QSize size) +QPixmap ResourcePack::image(QSize size, Qt::AspectRatioMode mode) const { QPixmap cached_image; if (PixmapCache::instance().find(m_pack_image_cache_key.key, &cached_image)) { if (size.isNull()) return cached_image; - return cached_image.scaled(size); + return cached_image.scaled(size, mode); } // No valid image we can get - if (!m_pack_image_cache_key.was_ever_used) + if (!m_pack_image_cache_key.was_ever_used) { return {}; + } else { + qDebug() << "Resource Pack" << name() << "Had it's image evicted from the cache. reloading..."; + PixmapCache::markCacheMissByEviciton(); + } // Imaged got evicted from the cache. Re-process it and retry. - ResourcePackUtils::process(*this); + ResourcePackUtils::processPackPNG(*this); return image(size); } diff --git a/launcher/minecraft/mod/ResourcePack.h b/launcher/minecraft/mod/ResourcePack.h index 7cb414d8..da354bc1 100644 --- a/launcher/minecraft/mod/ResourcePack.h +++ b/launcher/minecraft/mod/ResourcePack.h @@ -31,7 +31,7 @@ class ResourcePack : public Resource { [[nodiscard]] QString description() const { return m_description; } /** Gets the image of the resource pack, converted to a QPixmap for drawing, and scaled to size. */ - [[nodiscard]] QPixmap image(QSize size); + [[nodiscard]] QPixmap image(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const; /** Thread-safe. */ void setPackFormat(int new_format_id); @@ -40,7 +40,7 @@ class ResourcePack : public Resource { void setDescription(QString new_description); /** Thread-safe. */ - void setImage(QImage new_image); + void setImage(QImage new_image) const; bool valid() const override; @@ -67,5 +67,5 @@ class ResourcePack : public Resource { struct { QPixmapCache::Key key; bool was_ever_used = false; - } m_pack_image_cache_key; + } mutable m_pack_image_cache_key; }; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 6eba4e2e..c8c0c773 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -35,6 +35,8 @@ */ #include "ResourcePackFolderModel.h" +#include +#include #include #include @@ -48,7 +50,7 @@ ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, std::shared_ptr instance) : ResourceFolderModel(QDir(dir), instance) { - m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE }; + m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE, SortType::NAME }; } QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const @@ -84,9 +86,11 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const return {}; } case Qt::DecorationRole: { - if (column == NAME_COLUMN && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink())) + if (column == NameColumn && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink())) return APPLICATION->getThemedIcon("status-yellow"); - + if (column == ImageColumn) { + return at(row)->image(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding); + } return {}; } case Qt::ToolTipRole: { @@ -94,7 +98,7 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const //: The string being explained by this is in the format: ID (Lower version - Upper version) return tr("The resource pack format ID, as well as the Minecraft versions it was designed for."); } - if (column == NAME_COLUMN) { + if (column == NameColumn) { if (at(row)->isSymLinkUnder(instDirPath())) { return m_resources[row]->internal_id() + tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." @@ -133,6 +137,8 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient return tr("Pack Format"); case DateColumn: return tr("Last changed"); + case ImageColumn: + return tr("Image"); default: return {}; } @@ -151,6 +157,13 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient default: return {}; } + case Qt::SizeHintRole: + switch (section) { + case ImageColumn: + return QSize(64,0); + default: + return {}; + } default: return {}; } diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.h b/launcher/minecraft/mod/ResourcePackFolderModel.h index 66d5a074..71532f30 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.h +++ b/launcher/minecraft/mod/ResourcePackFolderModel.h @@ -14,6 +14,7 @@ public: NameColumn, PackFormatColumn, DateColumn, + ImageColumn, NUM_COLUMNS }; diff --git a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp index 4bf0b80d..a67c56a8 100644 --- a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp @@ -165,15 +165,16 @@ bool processZIP(ResourcePack& pack, ProcessingLevel level) bool pack_png_result = ResourcePackUtils::processPackPNG(pack, std::move(data)); file.close(); + zip.close(); if (!pack_png_result) { return png_invalid(); // pack.png invalid } } else { + zip.close(); return png_invalid(); // could not set pack.mcmeta as current file. } zip.close(); - return true; } @@ -193,7 +194,7 @@ bool processMCMeta(ResourcePack& pack, QByteArray&& raw_data) return true; } -bool processPackPNG(ResourcePack& pack, QByteArray&& raw_data) +bool processPackPNG(const ResourcePack& pack, QByteArray&& raw_data) { auto img = QImage::fromData(raw_data); if (!img.isNull()) { @@ -205,6 +206,68 @@ bool processPackPNG(ResourcePack& pack, QByteArray&& raw_data) return true; } +bool processPackPNG(const ResourcePack& pack) +{ + auto png_invalid = [&pack]() { + qWarning() << "Resource pack at" << pack.fileinfo().filePath() << "does not have a valid pack.png"; + return false; + }; + + switch (pack.type()) { + case ResourceType::FOLDER: + { + QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png")); + if (image_file_info.exists() && image_file_info.isFile()) { + QFile pack_png_file(image_file_info.filePath()); + if (!pack_png_file.open(QIODevice::ReadOnly)) + return png_invalid(); // can't open pack.png file + + auto data = pack_png_file.readAll(); + + bool pack_png_result = ResourcePackUtils::processPackPNG(pack, std::move(data)); + + pack_png_file.close(); + if (!pack_png_result) { + return png_invalid(); // pack.png invalid + } + } else { + return png_invalid(); // pack.png does not exists or is not a valid file. + } + } + case ResourceType::ZIPFILE: + { + Q_ASSERT(pack.type() == ResourceType::ZIPFILE); + + QuaZip zip(pack.fileinfo().filePath()); + if (!zip.open(QuaZip::mdUnzip)) + return false; // can't open zip file + + QuaZipFile file(&zip); + if (zip.setCurrentFile("pack.png")) { + if (!file.open(QIODevice::ReadOnly)) { + qCritical() << "Failed to open file in zip."; + zip.close(); + return png_invalid(); + } + + auto data = file.readAll(); + + bool pack_png_result = ResourcePackUtils::processPackPNG(pack, std::move(data)); + + file.close(); + if (!pack_png_result) { + return png_invalid(); // pack.png invalid + } + } else { + return png_invalid(); // could not set pack.mcmeta as current file. + } + } + default: + qWarning() << "Invalid type for resource pack parse task!"; + return false; + } +} + bool validate(QFileInfo file) { ResourcePack rp{ file }; diff --git a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h index d0c24c2b..58d90b3b 100644 --- a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h +++ b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.h @@ -35,7 +35,10 @@ bool processZIP(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Ful bool processFolder(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Full); bool processMCMeta(ResourcePack& pack, QByteArray&& raw_data); -bool processPackPNG(ResourcePack& pack, QByteArray&& raw_data); +bool processPackPNG(const ResourcePack& pack, QByteArray&& raw_data); + +/// processes ONLY the pack.png (rest of the pack may be invalid) +bool processPackPNG(const ResourcePack& pack); /** Checks whether a file is valid as a resource pack or not. */ bool validate(QFileInfo file); -- cgit From fd7338d3f3f72ca9532f11c9759ad02bbc759c7c Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 4 May 2023 23:47:27 -0700 Subject: fix: grow pixmapcache if it is evicting too fast Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/MTPixmapCache.h | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'launcher') diff --git a/launcher/MTPixmapCache.h b/launcher/MTPixmapCache.h index 57847a0e..271788c0 100644 --- a/launcher/MTPixmapCache.h +++ b/launcher/MTPixmapCache.h @@ -3,6 +3,8 @@ #include #include #include +#include +#include #define GET_TYPE() \ Qt::ConnectionType type; \ @@ -60,6 +62,8 @@ class PixmapCache final : public QObject { DEFINE_FUNC_ONE_PARAM(remove, bool, const QPixmapCache::Key&) DEFINE_FUNC_TWO_PARAM(replace, bool, const QPixmapCache::Key&, const QPixmap&) DEFINE_FUNC_ONE_PARAM(setCacheLimit, bool, int) + DEFINE_FUNC_NO_PARAM(markCacheMissByEviciton, bool) + DEFINE_FUNC_ONE_PARAM(setFastEvictionThreshold, bool, int) // NOTE: Every function returns something non-void to simplify the macros. private slots: @@ -90,6 +94,43 @@ class PixmapCache final : public QObject { return true; } + /** + * Mark that a cach miss occured because of a eviciton if too man of these occure to fast the cache size is increased + * @return if the cache size was increased + */ + bool _markCacheMissByEviciton() + { + auto now = QTime::currentTime(); + if (!m_last_cache_miss_by_eviciton.isNull()) { + auto diff = m_last_cache_miss_by_eviciton.msecsTo(now); + if (diff < 1000) { // less than a second ago + ++m_consecutive_fast_evicitons; + } else { + m_consecutive_fast_evicitons = 0; + } + } + m_last_cache_miss_by_eviciton = now; + if (m_consecutive_fast_evicitons >= m_consecutive_fast_evicitons_threshold) { + // double the cache size + auto newSize = _cacheLimit() * 2; + qDebug() << m_consecutive_fast_evicitons << "pixmap cache misses by eviction happened too fast, doubling cache size to" + << newSize; + _setCacheLimit(newSize); + m_consecutive_fast_evicitons = 0; + return true; + } + return false; + } + + bool _setFastEvictionThreshold(int threshold) + { + m_consecutive_fast_evicitons_threshold = threshold; + return true; + } + private: static PixmapCache* s_instance; + QTime m_last_cache_miss_by_eviciton; + int m_consecutive_fast_evicitons = 0; + int m_consecutive_fast_evicitons_threshold = 15; }; -- cgit From 2fe3dc5960a6cc231891a91dd68fcc8b159e9365 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 5 May 2023 11:13:36 -0700 Subject: fix: fix qchar conversion and codeql Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/MTPixmapCache.h | 2 +- launcher/minecraft/mod/Mod.cpp | 4 ++-- launcher/minecraft/mod/ResourcePackFolderModel.cpp | 8 +++----- launcher/minecraft/mod/TexturePackFolderModel.cpp | 8 +++----- launcher/minecraft/mod/tasks/LocalModParseTask.cpp | 12 ++++++------ 5 files changed, 15 insertions(+), 19 deletions(-) (limited to 'launcher') diff --git a/launcher/MTPixmapCache.h b/launcher/MTPixmapCache.h index 271788c0..65cbe032 100644 --- a/launcher/MTPixmapCache.h +++ b/launcher/MTPixmapCache.h @@ -95,7 +95,7 @@ class PixmapCache final : public QObject { } /** - * Mark that a cach miss occured because of a eviciton if too man of these occure to fast the cache size is increased + * Mark that a cache miss occurred because of a eviction if too many of these occur too fast the cache size is increased * @return if the cache size was increased */ bool _markCacheMissByEviciton() diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index 392f7f2e..aabc2db4 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -206,7 +206,7 @@ void Mod::finishResolvingWithDetails(ModDetails&& details) if (!iconPath().isEmpty()) { m_pack_image_cache_key.was_read_attempt = false; } -}; +} auto Mod::provider() const -> std::optional { @@ -250,7 +250,7 @@ QPixmap Mod::icon(QSize size, Qt::AspectRatioMode mode) const qDebug() << "Mod" << name() << "Had it's icon evicted form the cache. reloading..."; PixmapCache::markCacheMissByEviciton(); } - // Imaged got evicted from the cache or an attmept to load it has not been made. load it and retry. + // Image got evicted from the cache or an attempt to load it has not been made. load it and retry. m_pack_image_cache_key.was_read_attempt = true; ModUtils::loadIconFile(*this); return icon(size); diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index c8c0c773..349353a5 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -158,12 +158,10 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient return {}; } case Qt::SizeHintRole: - switch (section) { - case ImageColumn: - return QSize(64,0); - default: - return {}; + if (section == ImageColumn) { + return QSize(64,0); } + return {}; default: return {}; } diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index dd93a469..f053eab1 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -101,12 +101,10 @@ QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const return {}; } case Qt::CheckStateRole: - switch (column) { - case ActiveColumn: - return m_resources[row]->enabled() ? Qt::Checked : Qt::Unchecked; - default: - return {}; + if (column == ActiveColumn) { + return m_resources[row]->enabled() ? Qt::Checked : Qt::Unchecked; } + return {}; default: return {}; } diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp index 084b0afb..f045bde3 100644 --- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp @@ -268,12 +268,12 @@ ModDetails ReadFabricModInfo(QByteArray contents) } } if (largest > 0) { - auto key = QString::number(largest) + "x" + largest; + auto key = QString::number(largest) + "x" + QString::number(largest); details.icon_file = obj.value(key).toString(); } else { // parsing the sizes failed // take the first - for (auto icon : obj) { - details.icon_file = icon.toString(); + for (auto i : obj) { + details.icon_file = i.toString(); break; } } @@ -355,12 +355,12 @@ ModDetails ReadQuiltModInfo(QByteArray contents) } } if (largest > 0) { - auto key = QString::number(largest) + "x" + largest; + auto key = QString::number(largest) + "x" + QString::number(largest); details.icon_file = obj.value(key).toString(); } else { // parsing the sizes failed // take the first - for (auto icon : obj) { - details.icon_file = icon.toString(); + for (auto i : obj) { + details.icon_file = i.toString(); break; } } -- cgit From ee94be624eb11a12d4eb3e07c32ea4734b3ba6dc Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 5 May 2023 11:28:19 -0700 Subject: use 32x32 images for image column Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/Mod.cpp | 2 +- launcher/minecraft/mod/ModFolderModel.cpp | 2 +- launcher/minecraft/mod/ResourcePack.cpp | 2 +- launcher/minecraft/mod/ResourcePackFolderModel.cpp | 2 +- launcher/minecraft/mod/TexturePack.cpp | 2 +- launcher/minecraft/mod/TexturePackFolderModel.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index aabc2db4..f236d2ac 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -226,7 +226,7 @@ void Mod::setIcon(QImage new_image) const PixmapCache::remove(m_pack_image_cache_key.key); // scale the image to avoid flooding the pixmapcache - auto pixmap = QPixmap::fromImage(new_image.scaled({128, 128}, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + auto pixmap = QPixmap::fromImage(new_image.scaled({64, 64}, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); m_pack_image_cache_key.key = PixmapCache::insert(pixmap); m_pack_image_cache_key.was_ever_used = true; diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 8a58b9d7..f1c26e68 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -119,7 +119,7 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const if (column == NAME_COLUMN && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink())) return APPLICATION->getThemedIcon("status-yellow"); if (column == ImageColumn) { - return at(row)->icon(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding); + return at(row)->icon({32, 32}, Qt::AspectRatioMode::KeepAspectRatioByExpanding); } return {}; } diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp index 5fc9d7a6..9aea22ef 100644 --- a/launcher/minecraft/mod/ResourcePack.cpp +++ b/launcher/minecraft/mod/ResourcePack.cpp @@ -49,7 +49,7 @@ void ResourcePack::setImage(QImage new_image) const PixmapCache::instance().remove(m_pack_image_cache_key.key); // scale the image to avoid flooding the pixmapcache - auto pixmap = QPixmap::fromImage(new_image.scaled(QSize(128, 128), Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + auto pixmap = QPixmap::fromImage(new_image.scaled({64, 64}, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); m_pack_image_cache_key.key = PixmapCache::instance().insert(pixmap); m_pack_image_cache_key.was_ever_used = true; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 349353a5..b11e2262 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -89,7 +89,7 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const if (column == NameColumn && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink())) return APPLICATION->getThemedIcon("status-yellow"); if (column == ImageColumn) { - return at(row)->image(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding); + return at(row)->image({32, 32}, Qt::AspectRatioMode::KeepAspectRatioByExpanding); } return {}; } diff --git a/launcher/minecraft/mod/TexturePack.cpp b/launcher/minecraft/mod/TexturePack.cpp index 8ff1e852..c7a50a97 100644 --- a/launcher/minecraft/mod/TexturePack.cpp +++ b/launcher/minecraft/mod/TexturePack.cpp @@ -44,7 +44,7 @@ void TexturePack::setImage(QImage new_image) const PixmapCache::remove(m_pack_image_cache_key.key); // scale the image to avoid flooding the pixmapcache - auto pixmap = QPixmap::fromImage(new_image.scaled(QSize(128, 128), Qt::AspectRatioMode::KeepAspectRatioByExpanding)); + auto pixmap = QPixmap::fromImage(new_image.scaled({64, 64}, Qt::AspectRatioMode::KeepAspectRatioByExpanding)); m_pack_image_cache_key.key = PixmapCache::insert(pixmap); m_pack_image_cache_key.was_ever_used = true; diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index f053eab1..e115cce6 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -96,7 +96,7 @@ QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const if (column == NameColumn && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink())) return APPLICATION->getThemedIcon("status-yellow"); if (column == ImageColumn) { - return at(row)->image(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding); + return at(row)->image({32, 32}, Qt::AspectRatioMode::KeepAspectRatioByExpanding); } return {}; } -- cgit From 3cfcc83ea99e8f42dba8848b5ef885c296b4566a Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 5 May 2023 13:46:01 -0700 Subject: change: don't toggle a resource's enabeling just by selecting it. only if they are on the checkbox. Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/pages/instance/ExternalResourcesPage.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index 1115ddc3..6c11b85b 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -96,7 +96,6 @@ void ExternalResourcesPage::itemActivated(const QModelIndex&) return; auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); - m_model->setResourceEnabled(selection.indexes(), EnableAction::TOGGLE); } void ExternalResourcesPage::filterTextChanged(const QString& newContents) -- cgit From 74e7c13a177afdb503a642cb9c97d71e72249291 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 5 May 2023 13:46:38 -0700 Subject: feat: display license and issue tracker Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/Mod.cpp | 9 ++ launcher/minecraft/mod/Mod.h | 2 + launcher/minecraft/mod/ModDetails.h | 11 +- launcher/minecraft/mod/ModFolderModel.cpp | 1 - launcher/minecraft/mod/tasks/LocalModParseTask.cpp | 3 +- launcher/ui/widgets/InfoFrame.cpp | 120 ++++++++++++++++++++- launcher/ui/widgets/InfoFrame.h | 4 + launcher/ui/widgets/InfoFrame.ui | 92 +++++++++++----- 8 files changed, 209 insertions(+), 33 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index f236d2ac..e613ddeb 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -215,6 +215,15 @@ auto Mod::provider() const -> std::optional return {}; } +auto Mod::licenses() const -> const QList& +{ + return details().licenses; +} + + auto Mod::issueTracker() const -> QString +{ + return details().issue_tracker; +} void Mod::setIcon(QImage new_image) const { diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 4be0842f..d4e419f4 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -68,6 +68,8 @@ public: auto authors() const -> QStringList; auto status() const -> ModStatus; auto provider() const -> std::optional; + auto licenses() const -> const QList&; + auto issueTracker() const -> QString; /** Get the intneral path to the mod's icon file*/ QString iconPath() const { return m_local_details.icon_file; }; diff --git a/launcher/minecraft/mod/ModDetails.h b/launcher/minecraft/mod/ModDetails.h index eb3770d6..b4e59d52 100644 --- a/launcher/minecraft/mod/ModDetails.h +++ b/launcher/minecraft/mod/ModDetails.h @@ -64,8 +64,11 @@ struct ModLicense { auto parts = license.split(' '); QStringList notNameParts = {}; for (auto part : parts) { - auto url = QUrl::fromUserInput(part); - if (url.isValid()) { + auto url = QUrl(part); + if (part.startsWith("(") && part.endsWith(")")) + url = QUrl(part.mid(1, part.size() - 2)); + + if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) { this->url = url.toString(); notNameParts.append(part); continue; @@ -119,6 +122,10 @@ struct ModLicense { return *this; } + + bool isEmpty() { + return this->name.isEmpty() && this->id.isEmpty() && this->url.isEmpty() && this->description.isEmpty(); + } }; struct ModDetails diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index f1c26e68..8843f79f 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -52,7 +52,6 @@ #include "minecraft/mod/tasks/LocalModParseTask.h" #include "minecraft/mod/tasks/ModFolderLoadTask.h" -#include "modplatform/ModIndex.h" ModFolderModel::ModFolderModel(const QString& dir, std::shared_ptr instance, bool is_indexed, bool create_dir) : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed) diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp index f045bde3..264019f8 100644 --- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp @@ -184,7 +184,8 @@ ModDetails ReadMCModTOML(QByteArray contents) } else if (auto licenseDatum =(*modsTable)["license"].as_string()) { license = QString::fromStdString(licenseDatum->get()); } - details.licenses.push_back(ModLicense(license)); + if (!license.isEmpty()) + details.licenses.append(ModLicense(license)); QString logoFile = ""; if (auto logoFileDatum = tomlData["logoFile"].as_string()) { diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 6f4036a2..9c041bfe 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -47,6 +47,8 @@ InfoFrame::InfoFrame(QWidget *parent) : ui->setupUi(this); ui->descriptionLabel->setHidden(true); ui->nameLabel->setHidden(true); + ui->licenseLabel->setHidden(true); + ui->issueTrackerLabel->setHidden(true); updateHiddenState(); } @@ -89,6 +91,40 @@ void InfoFrame::updateWithMod(Mod const& m) } setImage(m.icon({64,64})); + + auto licenses = m.licenses(); + QString licenseText = ""; + if (!licenses.empty()) { + for (auto l : licenses) { + if (!licenseText.isEmpty()) { + licenseText += "\n"; // add newline between licenses + } + if (!l.name.isEmpty()) { + if (l.url.isEmpty()) { + licenseText += l.name; + } else { + licenseText += "" + l.name + ""; + } + } else if (!l.url.isEmpty()) { + licenseText += "" + l.url + ""; + } + if (!l.description.isEmpty() && l.description != l.name) { + licenseText += " " + l.description; + } + } + } + if (!licenseText.isEmpty()) { + setLicense(tr("License: %1").arg(licenseText)); + } else { + setLicense(); + } + + QString issueTracker = ""; + if (!m.issueTracker().isEmpty()) { + issueTracker += tr("Report issues to: "); + issueTracker += "" + m.issueTracker() + ""; + } + setIssueTracker(issueTracker); } void InfoFrame::updateWithResource(const Resource& resource) @@ -177,16 +213,16 @@ void InfoFrame::clear() setName(); setDescription(); setImage(); + setLicense(); + setIssueTracker(); } void InfoFrame::updateHiddenState() { - if(ui->descriptionLabel->isHidden() && ui->nameLabel->isHidden()) - { + if (ui->descriptionLabel->isHidden() && ui->nameLabel->isHidden() && ui->licenseLabel->isHidden() && + ui->issueTrackerLabel->isHidden()) { setHidden(true); - } - else - { + } else { setHidden(false); } } @@ -251,6 +287,66 @@ void InfoFrame::setDescription(QString text) ui->descriptionLabel->setText(labeltext); } +void InfoFrame::setLicense(QString text) +{ + if(text.isEmpty()) + { + ui->licenseLabel->setHidden(true); + updateHiddenState(); + return; + } + else + { + ui->licenseLabel->setHidden(false); + updateHiddenState(); + } + ui->licenseLabel->setToolTip(""); + QString intermediatetext = text.trimmed(); + bool prev(false); + QChar rem('\n'); + QString finaltext; + finaltext.reserve(intermediatetext.size()); + foreach(const QChar& c, intermediatetext) + { + if(c == rem && prev){ + continue; + } + prev = c == rem; + finaltext += c; + } + QString labeltext; + labeltext.reserve(300); + if(finaltext.length() > 290) + { + ui->licenseLabel->setOpenExternalLinks(false); + ui->licenseLabel->setTextFormat(Qt::TextFormat::RichText); + m_description = text; + // This allows injecting HTML here. + labeltext.append("" + finaltext.left(287) + "..."); + QObject::connect(ui->licenseLabel, &QLabel::linkActivated, this, &InfoFrame::licenseEllipsisHandler); + } + else + { + ui->licenseLabel->setTextFormat(Qt::TextFormat::AutoText); + labeltext.append(finaltext); + } + ui->licenseLabel->setText(labeltext); +} + +void InfoFrame::setIssueTracker(QString text) +{ + if(text.isEmpty()) + { + ui->issueTrackerLabel->setHidden(true); + } + else + { + ui->issueTrackerLabel->setText(text); + ui->issueTrackerLabel->setHidden(false); + } + updateHiddenState(); +} + void InfoFrame::setImage(QPixmap img) { if (img.isNull()) { @@ -275,6 +371,20 @@ void InfoFrame::descriptionEllipsisHandler(QString link) } } +void InfoFrame::licenseEllipsisHandler(QString link) +{ + if(!m_current_box) + { + m_current_box = CustomMessageBox::selectable(this, "", m_license); + connect(m_current_box, &QMessageBox::finished, this, &InfoFrame::boxClosed); + m_current_box->show(); + } + else + { + m_current_box->setText(m_license); + } +} + void InfoFrame::boxClosed(int result) { m_current_box = nullptr; diff --git a/launcher/ui/widgets/InfoFrame.h b/launcher/ui/widgets/InfoFrame.h index 84523e28..7eb679a9 100644 --- a/launcher/ui/widgets/InfoFrame.h +++ b/launcher/ui/widgets/InfoFrame.h @@ -36,6 +36,8 @@ class InfoFrame : public QFrame { void setName(QString text = {}); void setDescription(QString text = {}); void setImage(QPixmap img = {}); + void setLicense(QString text = {}); + void setIssueTracker(QString text = {}); void clear(); @@ -48,6 +50,7 @@ class InfoFrame : public QFrame { public slots: void descriptionEllipsisHandler(QString link); + void licenseEllipsisHandler(QString link); void boxClosed(int result); private: @@ -56,5 +59,6 @@ class InfoFrame : public QFrame { private: Ui::InfoFrame* ui; QString m_description; + QString m_license; class QMessageBox* m_current_box = nullptr; }; diff --git a/launcher/ui/widgets/InfoFrame.ui b/launcher/ui/widgets/InfoFrame.ui index 9e407ce9..c4d8c83d 100644 --- a/launcher/ui/widgets/InfoFrame.ui +++ b/launcher/ui/widgets/InfoFrame.ui @@ -35,8 +35,36 @@ 0 - - + + + + + 0 + 0 + + + + + 64 + 64 + + + + + + + false + + + 0 + + + + + + + + @@ -57,11 +85,8 @@ - - - - - + + @@ -82,28 +107,47 @@ - - - - - 0 - 0 - + + + + - - - 64 - 64 - + + Qt::RichText + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + true + + + Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + - + - - false + + Qt::RichText - - 0 + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + true + + + Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse -- cgit From 0b251fa7545dbe7e61a2a57f5f3e0ff2198b2314 Mon Sep 17 00:00:00 2001 From: Redson Date: Mon, 8 May 2023 19:57:30 -0300 Subject: feat: Add the launcher root folder to the Folders menu Signed-off-by: Redson --- launcher/ui/MainWindow.cpp | 8 ++++++++ launcher/ui/MainWindow.h | 2 ++ launcher/ui/MainWindow.ui | 13 +++++++++++++ 3 files changed, 23 insertions(+) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 72b7db64..8d62dcd6 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1201,6 +1201,14 @@ void MainWindow::on_actionViewInstanceFolder_triggered() DesktopServices::openDirectory(str); } +void MainWindow::on_actionViewLauncherRootFolder_triggered() +{ + QDir rootDir(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "..")); + QString DataPath = rootDir.absolutePath(); + + DesktopServices::openDirectory(DataPath); +} + void MainWindow::refreshInstances() { APPLICATION->instances()->loadList(); diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 3a42c34e..08efb8a1 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -112,6 +112,8 @@ private slots: void on_actionViewInstanceFolder_triggered(); + void on_actionViewLauncherRootFolder_triggered(); + void on_actionViewSelectedInstFolder_triggered(); void refreshInstances(); diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index 2b6a10b1..7c53e294 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -187,6 +187,7 @@ true + @@ -528,6 +529,18 @@ Open the instance folder in a file browser. + + + + .. + + + &View Launcher Root Folder + + + Open the launcher's root folder in a file browser. + + -- cgit From 475761b295b3c77aa852af254f783340055090f6 Mon Sep 17 00:00:00 2001 From: Redson Date: Tue, 9 May 2023 06:36:21 -0300 Subject: fix: Prism sets the data dir to the working directory. Signed-off-by: Redson --- launcher/ui/MainWindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 8d62dcd6..629ace83 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1203,10 +1203,10 @@ void MainWindow::on_actionViewInstanceFolder_triggered() void MainWindow::on_actionViewLauncherRootFolder_triggered() { - QDir rootDir(FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "..")); - QString DataPath = rootDir.absolutePath(); + QDir dataDir = QDir::current(); + QString dataPath = dataDir.absolutePath(); - DesktopServices::openDirectory(DataPath); + DesktopServices::openDirectory(dataPath); } void MainWindow::refreshInstances() -- cgit From 37a6ef95f05b474da1ce449bef696258d22a9d9b Mon Sep 17 00:00:00 2001 From: Redson Date: Wed, 10 May 2023 08:25:13 -0300 Subject: feat: Don't hide the settings tab when an instance is running Signed-off-by: Redson --- launcher/ui/pages/instance/InstanceSettingsPage.cpp | 11 ++++++++++- launcher/ui/pages/instance/InstanceSettingsPage.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 4b4c73dc..97939461 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -60,11 +60,15 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) m_settings = inst->settings(); ui->setupUi(this); + // As the signal will (probably) not be triggered once we click edit, let's update it manually instead. + updateRunningStatus(m_instance->isRunning()); + accountMenu = new QMenu(this); // Use undocumented property... https://stackoverflow.com/questions/7121718/create-a-scrollbar-in-a-submenu-qt accountMenu->setStyleSheet("QMenu { menu-scrollable: 1; }"); ui->instanceAccountSelector->setMenu(accountMenu); + connect(m_instance, &BaseInstance::runningStatusChanged, this, &InstanceSettingsPage::updateRunningStatus); connect(ui->openGlobalJavaSettingsButton, &QCommandLinkButton::clicked, this, &InstanceSettingsPage::globalSettingsButtonClicked); connect(APPLICATION, &Application::globalSettingsAboutToOpen, this, &InstanceSettingsPage::applySettings); connect(APPLICATION, &Application::globalSettingsClosed, this, &InstanceSettingsPage::loadSettings); @@ -74,7 +78,7 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) bool InstanceSettingsPage::shouldDisplay() const { - return !m_instance->isRunning(); + return true; } InstanceSettingsPage::~InstanceSettingsPage() @@ -552,3 +556,8 @@ void InstanceSettingsPage::updateThresholds() ui->labelMaxMemIcon->setPixmap(pix); } } + +void InstanceSettingsPage::updateRunningStatus(bool running) +{ + setEnabled(!running); +} diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.h b/launcher/ui/pages/instance/InstanceSettingsPage.h index cb6fbae0..89e663bf 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.h +++ b/launcher/ui/pages/instance/InstanceSettingsPage.h @@ -81,6 +81,7 @@ public: void updateThresholds(); private slots: + void updateRunningStatus(bool running); void on_javaDetectBtn_clicked(); void on_javaTestBtn_clicked(); void on_javaBrowseBtn_clicked(); -- cgit From f27716656c6f6006238203669a7a02f035733fc0 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 11 May 2023 16:32:00 -0700 Subject: fix: remove qt < 5.6 support process error signal Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/LoggedProcess.cpp | 4 ---- launcher/java/JavaChecker.cpp | 4 ---- 2 files changed, 8 deletions(-) (limited to 'launcher') diff --git a/launcher/LoggedProcess.cpp b/launcher/LoggedProcess.cpp index 763a9b5c..d70f6d00 100644 --- a/launcher/LoggedProcess.cpp +++ b/launcher/LoggedProcess.cpp @@ -45,11 +45,7 @@ LoggedProcess::LoggedProcess(QObject *parent) : QProcess(parent) connect(this, &QProcess::readyReadStandardOutput, this, &LoggedProcess::on_stdOut); connect(this, &QProcess::readyReadStandardError, this, &LoggedProcess::on_stdErr); connect(this, QOverload::of(&QProcess::finished), this, &LoggedProcess::on_exit); -#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) // &QProcess::errorOccurred added in 5.6 connect(this, &QProcess::errorOccurred, this, &LoggedProcess::on_error); -#else - connect(this, QOverload::of(&QProcess::error), this, &LoggedProcess::on_error); -#endif connect(this, &QProcess::stateChanged, this, &LoggedProcess::on_stateChange); } diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp index 922580ce..b4c55b3d 100644 --- a/launcher/java/JavaChecker.cpp +++ b/launcher/java/JavaChecker.cpp @@ -88,11 +88,7 @@ void JavaChecker::performCheck() qDebug() << "Running java checker: " + m_path + args.join(" ");; connect(process.get(), QOverload::of(&QProcess::finished), this, &JavaChecker::finished); -#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) // &QProcess::errorOccurred added in 5.6 connect(process.get(), &QProcess::errorOccurred, this, &JavaChecker::error); -#else - connect(process.get(), &QProcess::error, this, &JavaChecker::error); -#endif connect(process.get(), &QProcess::readyReadStandardOutput, this, &JavaChecker::stdoutReady); connect(process.get(), &QProcess::readyReadStandardError, this, &JavaChecker::stderrReady); connect(&killTimer, &QTimer::timeout, this, &JavaChecker::timeout); -- cgit From 5b8d0254408a6fd3e123eb06b7cbcdd20bd54518 Mon Sep 17 00:00:00 2001 From: Kode Date: Fri, 12 May 2023 14:43:55 +0100 Subject: ty! Co-authored-by: flow Signed-off-by: Kode --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index d2ef0653..9a45e46b 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -64,6 +64,7 @@ bool ModrinthPackExportTask::abort() if (buildZipFuture.isRunning()) { buildZipFuture.cancel(); + // NOTE: Here we don't do `emitAborted()` because it will be done when `buildZipFuture` actually cancels, which may not occur immediately. return true; } return false; -- cgit From 79ce7eb1fc9351e689e7106e3dc3a641d9614c9a Mon Sep 17 00:00:00 2001 From: Redson Date: Sat, 13 May 2023 09:00:10 -0300 Subject: fix: `shouldDisplay()` is now redundant. Signed-off-by: Redson --- launcher/ui/pages/instance/InstanceSettingsPage.cpp | 5 ----- launcher/ui/pages/instance/InstanceSettingsPage.h | 1 - 2 files changed, 6 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 97939461..46830720 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -76,11 +76,6 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) updateThresholds(); } -bool InstanceSettingsPage::shouldDisplay() const -{ - return true; -} - InstanceSettingsPage::~InstanceSettingsPage() { delete ui; diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.h b/launcher/ui/pages/instance/InstanceSettingsPage.h index 89e663bf..8bd854ad 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.h +++ b/launcher/ui/pages/instance/InstanceSettingsPage.h @@ -75,7 +75,6 @@ public: { return "Instance-settings"; } - virtual bool shouldDisplay() const override; void retranslate() override; void updateThresholds(); -- cgit From e1b6020b76401eb5a2f164775f3f738f357e4e2d Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 13 May 2023 18:24:01 +0100 Subject: Make some changes Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 13 +++++++++++-- launcher/ui/dialogs/ExportInstanceDialog.cpp | 3 --- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 9a45e46b..c550fdce 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -67,11 +67,15 @@ bool ModrinthPackExportTask::abort() // NOTE: Here we don't do `emitAborted()` because it will be done when `buildZipFuture` actually cancels, which may not occur immediately. return true; } + return false; } void ModrinthPackExportTask::collectFiles() { + setAbortable(false); + QCoreApplication::processEvents(); + files.clear(); if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) { emitFailed(tr("Could not search for files")); @@ -91,6 +95,8 @@ void ModrinthPackExportTask::collectFiles() void ModrinthPackExportTask::collectHashes() { for (const QFileInfo& file : files) { + QCoreApplication::processEvents(); + const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); // require sensible file types if (!std::any_of(PREFIXES.begin(), PREFIXES.end(), @@ -149,6 +155,8 @@ void ModrinthPackExportTask::collectHashes() void ModrinthPackExportTask::makeApiRequest() { + setAbortable(true); + if (pendingHashes.isEmpty()) buildZip(); else { @@ -186,7 +194,8 @@ void ModrinthPackExportTask::parseApiResponse(const QByteArray* response) } } } catch (const Json::JsonException& e) { - qWarning() << "Failed to parse versions response" << e.what(); + emitFailed(tr("Failed to parse versions response: %1").arg(e.what())); + return; } pendingHashes.clear(); buildZip(); @@ -194,7 +203,7 @@ void ModrinthPackExportTask::parseApiResponse(const QByteArray* response) void ModrinthPackExportTask::buildZip() { - setStatus("Adding files..."); + setStatus(tr("Adding files...")); buildZipFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { QuaZip zip(output); diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index ea01c5e2..57fe8119 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -45,7 +45,6 @@ #include #include #include -#include "StringUtils.h" #include "SeparatorPrefixTree.h" #include "Application.h" #include @@ -218,5 +217,3 @@ void ExportInstanceDialog::savePackIgnore() qWarning() << e.cause(); } } - -#include "ExportInstanceDialog.moc" -- cgit From 129e959a3b0a7d21965b15d6a65b0a9d22994838 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 13 May 2023 18:28:45 +0100 Subject: Move setAbortable(true) Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index c550fdce..8db89bbd 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -150,13 +150,12 @@ void ModrinthPackExportTask::collectHashes() pendingHashes[relative] = sha512.result().toHex(); } + setAbortable(true); makeApiRequest(); } void ModrinthPackExportTask::makeApiRequest() { - setAbortable(true); - if (pendingHashes.isEmpty()) buildZip(); else { -- cgit From 18cfe219fef2aabc1d3260764c02cd3476615176 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 13 May 2023 18:58:05 +0100 Subject: Hopefully This Worksâ„¢ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TheKodeToad --- launcher/FileIgnoreProxy.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp index 4fd1ef91..a3b7d505 100644 --- a/launcher/FileIgnoreProxy.cpp +++ b/launcher/FileIgnoreProxy.cpp @@ -129,12 +129,7 @@ bool FileIgnoreProxy::setData(const QModelIndex& index, const QVariant& value, i QString FileIgnoreProxy::relPath(const QString& path) const { - QString prefix = QDir().absoluteFilePath(root); - prefix += '/'; - if (!path.startsWith(prefix)) { - return QString(); - } - return path.mid(prefix.size()); + return QDir(root).relativeFilePath(path); } bool FileIgnoreProxy::setFilterState(QModelIndex index, Qt::CheckState state) -- cgit From 94cd831e8d15349e6e3428574cdada1b734f2e61 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 14 May 2023 22:13:53 +0300 Subject: Made sure the metadata is valid when checking mod deps Signed-off-by: Trial97 --- launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 96d343a1..948837d4 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -57,7 +57,8 @@ GetModDependenciesTask::GetModDependenciesTask(QObject* parent, , m_loaderType(mcLoaders(instance)) { for (auto mod : folder->allMods()) - m_mods.append(mod->metadata()); + if (auto meta = mod->metadata(); meta) + m_mods.append(meta); prepare(); }; -- cgit From 7537ea1ef532f5d8d50ad7aa7e49c4961ddf7b1c Mon Sep 17 00:00:00 2001 From: leo78913 Date: Sun, 14 May 2023 14:57:51 -0300 Subject: make instance settings account selector a comboBox Signed-off-by: leo78913 --- .../ui/pages/instance/InstanceSettingsPage.cpp | 54 ++++++---------------- launcher/ui/pages/instance/InstanceSettingsPage.h | 3 +- launcher/ui/pages/instance/InstanceSettingsPage.ui | 9 +--- 3 files changed, 15 insertions(+), 51 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 4b4c73dc..a583ab1d 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -60,15 +60,13 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) m_settings = inst->settings(); ui->setupUi(this); - accountMenu = new QMenu(this); - // Use undocumented property... https://stackoverflow.com/questions/7121718/create-a-scrollbar-in-a-submenu-qt - accountMenu->setStyleSheet("QMenu { menu-scrollable: 1; }"); - ui->instanceAccountSelector->setMenu(accountMenu); - connect(ui->openGlobalJavaSettingsButton, &QCommandLinkButton::clicked, this, &InstanceSettingsPage::globalSettingsButtonClicked); connect(APPLICATION, &Application::globalSettingsAboutToOpen, this, &InstanceSettingsPage::applySettings); connect(APPLICATION, &Application::globalSettingsClosed, this, &InstanceSettingsPage::loadSettings); + connect(ui->instanceAccountSelector, QOverload::of(&QComboBox::currentIndexChanged), this, &InstanceSettingsPage::changeInstanceAccount); loadSettings(); + + updateThresholds(); } @@ -454,36 +452,17 @@ void InstanceSettingsPage::on_javaTestBtn_clicked() void InstanceSettingsPage::updateAccountsMenu() { - accountMenu->clear(); - + ui->instanceAccountSelector->clear(); auto accounts = APPLICATION->accounts(); int accountIndex = accounts->findAccountByProfileId(m_settings->get("InstanceAccountId").toString()); - MinecraftAccountPtr defaultAccount = accounts->defaultAccount(); - - if (accountIndex != -1 && accounts->at(accountIndex)) { - defaultAccount = accounts->at(accountIndex); - } - - if (defaultAccount) { - ui->instanceAccountSelector->setText(defaultAccount->profileName()); - ui->instanceAccountSelector->setIcon(getFaceForAccount(defaultAccount)); - } else { - ui->instanceAccountSelector->setText(tr("No default account")); - ui->instanceAccountSelector->setIcon(APPLICATION->getThemedIcon("noaccount")); - } for (int i = 0; i < accounts->count(); i++) { MinecraftAccountPtr account = accounts->at(i); - QAction* action = new QAction(account->profileName(), this); - action->setData(i); - action->setCheckable(true); - if (accountIndex == i) { - action->setChecked(true); - } - action->setIcon(getFaceForAccount(account)); - accountMenu->addAction(action); - connect(action, SIGNAL(triggered(bool)), this, SLOT(changeInstanceAccount())); + ui->instanceAccountSelector->addItem(getFaceForAccount(account), account->profileName(), i); + if (i == accountIndex) + ui->instanceAccountSelector->setCurrentIndex(i); } + } QIcon InstanceSettingsPage::getFaceForAccount(MinecraftAccountPtr account) @@ -495,20 +474,13 @@ QIcon InstanceSettingsPage::getFaceForAccount(MinecraftAccountPtr account) return APPLICATION->getThemedIcon("noaccount"); } -void InstanceSettingsPage::changeInstanceAccount() +void InstanceSettingsPage::changeInstanceAccount(int index) { - QAction* sAction = (QAction*)sender(); - - Q_ASSERT(sAction->data().type() == QVariant::Type::Int); - - QVariant data = sAction->data(); - int index = data.toInt(); auto accounts = APPLICATION->accounts(); - auto account = accounts->at(index); - m_settings->set("InstanceAccountId", account->profileId()); - - ui->instanceAccountSelector->setText(account->profileName()); - ui->instanceAccountSelector->setIcon(getFaceForAccount(account)); + if (index != -1 && accounts->at(index) && ui->instanceAccountGroupBox->isChecked()) { + auto account = accounts->at(index); + m_settings->set("InstanceAccountId", account->profileId()); + } } void InstanceSettingsPage::on_maxMemSpinBox_valueChanged(int i) diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.h b/launcher/ui/pages/instance/InstanceSettingsPage.h index cb6fbae0..043c3e25 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.h +++ b/launcher/ui/pages/instance/InstanceSettingsPage.h @@ -95,12 +95,11 @@ private slots: void updateAccountsMenu(); QIcon getFaceForAccount(MinecraftAccountPtr account); - void changeInstanceAccount(); + void changeInstanceAccount(int index); private: Ui::InstanceSettingsPage *ui; BaseInstance *m_instance; SettingsObjectPtr m_settings; unique_qobject_ptr checker; - QMenu *accountMenu = nullptr; }; diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 1b986184..19d6dc02 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -636,14 +636,7 @@ - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextBesideIcon - - + -- cgit From 22aaf56855d9f1c4c8e2c2fdfba30a2d40a0ebdc Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 15 May 2023 18:48:30 +0100 Subject: De-hardcode .index Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index bc983efe..2b9f9174 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -17,6 +17,7 @@ */ #include "ExportMrPackDialog.h" +#include "minecraft/mod/ModFolderModel.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" #include "ui_ExportMrPackDialog.h" @@ -36,32 +37,35 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) ui->name->setText(instance->name()); ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); - auto model = new QFileSystemModel(this); + QFileSystemModel* model = new QFileSystemModel(this); // use the game root - everything outside cannot be exported - QString root = instance->gameRoot(); - proxy = new FileIgnoreProxy(root, this); + const QDir root(instance->gameRoot()); + proxy = new FileIgnoreProxy(instance->gameRoot(), this); proxy->setSourceModel(model); - QDir::Filters filter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); + const QDir::Filters filter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); - for (QString file : QDir(root).entryList(filter)) { + for (const QString& file : root.entryList(filter)) { if (!(file == "mods" || file == "coremods" || file == "datapacks" || file == "config" || file == "options.txt" || file == "servers.dat")) proxy->blockedPaths().insert(file); } - QDir modsIndex(instance->gameRoot() + "/mods/.index"); - if (modsIndex.exists()) - proxy->blockedPaths().insert("mods/.index"); + MinecraftInstance* mcInstance = dynamic_cast(instance.get()); + if (mcInstance) { + const QDir dir = mcInstance->loaderModList()->indexDir(); + if (dir.exists()) + proxy->blockedPaths().insert(root.relativeFilePath(dir.absolutePath())); + } ui->treeView->setModel(proxy); - ui->treeView->setRootIndex(proxy->mapFromSource(model->index(root))); + ui->treeView->setRootIndex(proxy->mapFromSource(model->index(instance->gameRoot()))); ui->treeView->sortByColumn(0, Qt::AscendingOrder); model->setFilter(filter); - model->setRootPath(root); + model->setRootPath(instance->gameRoot()); - auto headerView = ui->treeView->header(); + QHeaderView* headerView = ui->treeView->header(); headerView->setSectionResizeMode(QHeaderView::ResizeToContents); headerView->setSectionResizeMode(0, QHeaderView::Stretch); } @@ -100,4 +104,3 @@ void ExportMrPackDialog::done(int result) QDialog::done(result); } - -- cgit From 3be18b58bbb10bd7f93132d5c2bba6286dd85edc Mon Sep 17 00:00:00 2001 From: Kode Date: Mon, 15 May 2023 19:15:56 +0100 Subject: Better variable name :p Signed-off-by: Kode --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 2b9f9174..1551cc60 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -53,9 +53,9 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) MinecraftInstance* mcInstance = dynamic_cast(instance.get()); if (mcInstance) { - const QDir dir = mcInstance->loaderModList()->indexDir(); - if (dir.exists()) - proxy->blockedPaths().insert(root.relativeFilePath(dir.absolutePath())); + const QDir index = mcInstance->loaderModList()->indexDir(); + if (index.exists()) + proxy->blockedPaths().insert(root.relativeFilePath(index.absolutePath())); } ui->treeView->setModel(proxy); -- cgit From 4f0ec908ecc0c14c1ffe8e9631d031c754e3540a Mon Sep 17 00:00:00 2001 From: leo78913 Date: Tue, 9 May 2023 23:29:16 -0300 Subject: feat: add a close button to the main toolbar when running on gamescope Signed-off-by: leo78913 --- launcher/ui/MainWindow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 72b7db64..9b8db1ae 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -219,6 +219,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi // disabled until we have an instance selected ui->instanceToolBar->setEnabled(false); setInstanceActionsEnabled(false); + + // add a close button at the end of the main toolbar when running on gamescope / steam deck + if (qgetenv("XDG_CURRENT_DESKTOP") == "gamescope") { + ui->mainToolBar->addAction(ui->actionCloseWindow); + } + } // add the toolbar toggles to the view menu -- cgit From 1b3ff96ffd3a249d2b4b278a4afc2714038560d7 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 21 May 2023 01:46:28 -0700 Subject: fix: memory leak with NetJob and responce not getting cleaned up Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/InstanceCreationTask.h | 2 +- launcher/InstanceImportTask.cpp | 28 +++--- launcher/modplatform/flame/FileResolvingTask.cpp | 111 +++++++++++++++------ launcher/modplatform/flame/FileResolvingTask.h | 36 +++---- .../flame/FlameInstanceCreationTask.cpp | 1 + launcher/tasks/ConcurrentTask.cpp | 27 ++--- launcher/tasks/Task.cpp | 2 +- launcher/tasks/Task.h | 14 +++ 8 files changed, 141 insertions(+), 80 deletions(-) (limited to 'launcher') diff --git a/launcher/InstanceCreationTask.h b/launcher/InstanceCreationTask.h index 03ee1a7a..380fdf8a 100644 --- a/launcher/InstanceCreationTask.h +++ b/launcher/InstanceCreationTask.h @@ -34,7 +34,7 @@ class InstanceCreationTask : public InstanceTask { QString getError() const { return m_error_message; } protected: - void setError(QString message) { m_error_message = message; }; + void setError(const QString& message) { m_error_message = message; }; protected: bool m_abort = false; diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp index 8a48873e..352848f0 100644 --- a/launcher/InstanceImportTask.cpp +++ b/launcher/InstanceImportTask.cpp @@ -41,6 +41,7 @@ #include "MMCZip.h" #include "NullInstance.h" +#include "QObjectPtr.h" #include "icons/IconList.h" #include "icons/IconUtils.h" @@ -260,7 +261,7 @@ void InstanceImportTask::extractFinished() void InstanceImportTask::processFlame() { - FlameCreationTask* inst_creation_task = nullptr; + shared_qobject_ptr inst_creation_task = nullptr; if (!m_extra_info.isEmpty()) { auto pack_id_it = m_extra_info.constFind("pack_id"); Q_ASSERT(pack_id_it != m_extra_info.constEnd()); @@ -275,10 +276,10 @@ void InstanceImportTask::processFlame() if (original_instance_id_it != m_extra_info.constEnd()) original_instance_id = original_instance_id_it.value(); - inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); + inst_creation_task = makeShared(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id); } else { // FIXME: Find a way to get IDs in directly imported ZIPs - inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent, {}, {}); + inst_creation_task = makeShared(m_stagingPath, m_globalSettings, m_parent, QString(), QString()); } inst_creation_task->setName(*this); @@ -286,20 +287,19 @@ void InstanceImportTask::processFlame() inst_creation_task->setGroup(m_instGroup); inst_creation_task->setConfirmUpdate(shouldConfirmUpdate()); - connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] { + connect(inst_creation_task.get(), &Task::succeeded, this, [this, inst_creation_task] { setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID()); emitSucceeded(); }); - connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed); - connect(inst_creation_task, &Task::progress, this, &InstanceImportTask::setProgress); - connect(inst_creation_task, &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress); - connect(inst_creation_task, &Task::status, this, &InstanceImportTask::setStatus); - connect(inst_creation_task, &Task::details, this, &InstanceImportTask::setDetails); - connect(inst_creation_task, &Task::finished, inst_creation_task, &InstanceCreationTask::deleteLater); - - connect(this, &Task::aborted, inst_creation_task, &InstanceCreationTask::abort); - connect(inst_creation_task, &Task::aborted, this, &Task::abort); - connect(inst_creation_task, &Task::abortStatusChanged, this, &Task::setAbortable); + connect(inst_creation_task.get(), &Task::failed, this, &InstanceImportTask::emitFailed); + connect(inst_creation_task.get(), &Task::progress, this, &InstanceImportTask::setProgress); + connect(inst_creation_task.get(), &Task::stepProgress, this, &InstanceImportTask::propogateStepProgress); + connect(inst_creation_task.get(), &Task::status, this, &InstanceImportTask::setStatus); + connect(inst_creation_task.get(), &Task::details, this, &InstanceImportTask::setDetails); + + connect(this, &Task::aborted, inst_creation_task.get(), &InstanceCreationTask::abort); + connect(inst_creation_task.get(), &Task::aborted, this, &Task::abort); + connect(inst_creation_task.get(), &Task::abortStatusChanged, this, &Task::setAbortable); inst_creation_task->start(); } diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index d3a737bb..83db642e 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -35,7 +35,29 @@ void Flame::FileResolvingTask::executeTask() QByteArray data = Json::toText(object); auto dl = Net::Upload::makeByteArray(QUrl("https://api.curseforge.com/v1/mods/files"), result.get(), data); m_dljob->addNetAction(dl); - connect(m_dljob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::netJobFinished); + + auto step_progress = std::make_shared(); + connect(m_dljob.get(), &NetJob::finished, this, [this, step_progress]() { + step_progress->state = TaskStepState::Succeeded; + stepProgress(*step_progress); + netJobFinished(); + }); + connect(m_dljob.get(), &NetJob::failed, this, [this, step_progress](QString reason) { + step_progress->state = TaskStepState::Failed; + stepProgress(*step_progress); + emitFailed(reason); + }); + connect(m_dljob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress); + connect(m_dljob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) { + qDebug() << "Resolve slug progress" << current << total; + step_progress->update(current, total); + stepProgress(*step_progress); + }); + connect(m_dljob.get(), &NetJob::status, this, [this, step_progress](QString status) { + step_progress->status = status; + stepProgress(*step_progress); + }); + m_dljob->start(); } @@ -44,7 +66,7 @@ void Flame::FileResolvingTask::netJobFinished() setProgress(1, 3); // job to check modrinth for blocked projects m_checkJob.reset(new NetJob("Modrinth check", m_network)); - blockedProjects = QMap(); + blockedProjects = QMap>(); QJsonDocument doc; QJsonArray array; @@ -71,8 +93,8 @@ void Flame::FileResolvingTask::netJobFinished() auto hash = out.hash; if(!hash.isEmpty()) { auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash); - auto output = new QByteArray(); - auto dl = Net::Download::makeByteArray(QUrl(url), output); + auto output = std::make_shared(); + auto dl = Net::Download::makeByteArray(QUrl(url), output.get()); QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() { out.resolved = true; }); @@ -82,7 +104,27 @@ void Flame::FileResolvingTask::netJobFinished() } } } - connect(m_checkJob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::modrinthCheckFinished); + auto step_progress = std::make_shared(); + connect(m_checkJob.get(), &NetJob::finished, this, [this, step_progress]() { + step_progress->state = TaskStepState::Succeeded; + stepProgress(*step_progress); + modrinthCheckFinished(); + }); + connect(m_checkJob.get(), &NetJob::failed, this, [this, step_progress](QString reason) { + step_progress->state = TaskStepState::Failed; + stepProgress(*step_progress); + emitFailed(reason); + }); + connect(m_checkJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress); + connect(m_checkJob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) { + qDebug() << "Resolve slug progress" << current << total; + step_progress->update(current, total); + stepProgress(*step_progress); + }); + connect(m_checkJob.get(), &NetJob::status, this, [this, step_progress](QString status) { + step_progress->status = status; + stepProgress(*step_progress); + }); m_checkJob->start(); } @@ -95,7 +137,6 @@ void Flame::FileResolvingTask::modrinthCheckFinished() { auto &out = *it; auto bytes = blockedProjects[out]; if (!out->resolved) { - delete bytes; continue; } @@ -112,11 +153,9 @@ void Flame::FileResolvingTask::modrinthCheckFinished() { } else { out->resolved = false; } - - delete bytes; } //copy to an output list and filter out projects found on modrinth - auto block = new QList(); + auto block = std::make_shared>(); auto it = blockedProjects.keys(); std::copy_if(it.begin(), it.end(), std::back_inserter(*block), [](File *f) { return !f->resolved; @@ -124,32 +163,48 @@ void Flame::FileResolvingTask::modrinthCheckFinished() { //Display not found mods early if (!block->empty()) { //blocked mods found, we need the slug for displaying.... we need another job :D ! - auto slugJob = new NetJob("Slug Job", m_network); - auto slugs = QVector(block->size()); - auto index = 0; - for (auto fileInfo: *block) { - auto projectId = fileInfo->projectId; - slugs[index] = QByteArray(); + m_slugJob.reset(new NetJob("Slug Job", m_network)); + int index = 0; + for (auto mod : *block) { + auto projectId = mod->projectId; + auto output = std::make_shared(); auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(projectId); - auto dl = Net::Download::makeByteArray(url, &slugs[index]); - slugJob->addNetAction(dl); - index++; - } - connect(slugJob, &NetJob::succeeded, this, [slugs, this, slugJob, block]() { - slugJob->deleteLater(); - auto index = 0; - for (const auto &slugResult: slugs) { - auto json = QJsonDocument::fromJson(slugResult); + auto dl = Net::Download::makeByteArray(url, output.get()); + qDebug() << "Fetching url slug for file:" << mod->fileName; + QObject::connect(dl.get(), &Net::Download::succeeded, [block, index, output]() { + auto mod = block->at(index); // use the shared_ptr so it is captured and only freed when we are done + auto json = QJsonDocument::fromJson(*output); auto base = Json::requireString(Json::requireObject(Json::requireObject(Json::requireObject(json),"data"),"links"), "websiteUrl"); - auto mod = block->at(index); auto link = QString("%1/download/%2").arg(base, QString::number(mod->fileId)); mod->websiteUrl = link; - index++; - } + }); + m_slugJob->addNetAction(dl); + index++; + } + auto step_progress = std::make_shared(); + connect(m_slugJob.get(), &NetJob::succeeded, this, [this, step_progress]() { + step_progress->state = TaskStepState::Succeeded; + stepProgress(*step_progress); emitSucceeded(); }); - slugJob->start(); + connect(m_slugJob.get(), &NetJob::failed, this, [this, step_progress](QString reason) { + step_progress->state = TaskStepState::Failed; + stepProgress(*step_progress); + emitFailed(reason); + }); + connect(m_slugJob.get(), &NetJob::stepProgress, this, &FileResolvingTask::propogateStepProgress); + connect(m_slugJob.get(), &NetJob::progress, this, [this, step_progress](qint64 current, qint64 total) { + qDebug() << "Resolve slug progress" << current << total; + step_progress->update(current, total); + stepProgress(*step_progress); + }); + connect(m_slugJob.get(), &NetJob::status, this, [this, step_progress](QString status) { + step_progress->status = status; + stepProgress(*step_progress); + }); + + m_slugJob->start(); } else { emitSucceeded(); } diff --git a/launcher/modplatform/flame/FileResolvingTask.h b/launcher/modplatform/flame/FileResolvingTask.h index 8fc17ea9..c280827a 100644 --- a/launcher/modplatform/flame/FileResolvingTask.h +++ b/launcher/modplatform/flame/FileResolvingTask.h @@ -1,41 +1,37 @@ #pragma once -#include "tasks/Task.h" -#include "net/NetJob.h" #include "PackManifest.h" +#include "net/NetJob.h" +#include "tasks/Task.h" -namespace Flame -{ -class FileResolvingTask : public Task -{ +namespace Flame { +class FileResolvingTask : public Task { Q_OBJECT -public: - explicit FileResolvingTask(const shared_qobject_ptr& network, Flame::Manifest &toProcess); - virtual ~FileResolvingTask() {}; + public: + explicit FileResolvingTask(const shared_qobject_ptr& network, Flame::Manifest& toProcess); + virtual ~FileResolvingTask(){}; bool canAbort() const override { return true; } bool abort() override; - const Flame::Manifest &getResults() const - { - return m_toProcess; - } + const Flame::Manifest& getResults() const { return m_toProcess; } -protected: + protected: virtual void executeTask() override; -protected slots: + protected slots: void netJobFinished(); -private: /* data */ + private: /* data */ shared_qobject_ptr m_network; Flame::Manifest m_toProcess; - std::shared_ptr result; + std::shared_ptr result; NetJob::Ptr m_dljob; - NetJob::Ptr m_checkJob; + NetJob::Ptr m_checkJob; + NetJob::Ptr m_slugJob; void modrinthCheckFinished(); - QMap blockedProjects; + QMap> blockedProjects; }; -} +} // namespace Flame diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index 86fd2ab4..dae93d1c 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -384,6 +384,7 @@ bool FlameCreationTask::createInstance() connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::progress, this, &FlameCreationTask::setProgress); connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::status, this, &FlameCreationTask::setStatus); connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::stepProgress, this, &FlameCreationTask::propogateStepProgress); + connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::details, this, &FlameCreationTask::setDetails); m_mod_id_resolver->start(); loop.exec(); diff --git a/launcher/tasks/ConcurrentTask.cpp b/launcher/tasks/ConcurrentTask.cpp index fae2f3dc..5ee14505 100644 --- a/launcher/tasks/ConcurrentTask.cpp +++ b/launcher/tasks/ConcurrentTask.cpp @@ -138,7 +138,7 @@ void ConcurrentTask::startNext() connect(next.get(), &Task::progress, this, [this, next](qint64 current, qint64 total) { subTaskProgress(next, current, total); }); m_doing.insert(next.get(), next); - auto task_progress = std::make_shared(TaskStepProgress({ next->getUid() })); + auto task_progress = std::make_shared(next->getUid()); m_task_progress.insert(next->getUid(), task_progress); updateState(); @@ -166,9 +166,9 @@ void ConcurrentTask::subTaskSucceeded(Task::Ptr task) disconnect(task.get(), 0, this, 0); - emit stepProgress(*task_progress.get()); + emit stepProgress(*task_progress); updateState(); - updateStepProgress(*task_progress.get(), Operation::REMOVED); + updateStepProgress(*task_progress, Operation::REMOVED); startNext(); } @@ -184,9 +184,9 @@ void ConcurrentTask::subTaskFailed(Task::Ptr task, const QString& msg) disconnect(task.get(), 0, this, 0); - emit stepProgress(*task_progress.get()); + emit stepProgress(*task_progress); updateState(); - updateStepProgress(*task_progress.get(), Operation::REMOVED); + updateStepProgress(*task_progress, Operation::REMOVED); startNext(); } @@ -196,7 +196,7 @@ void ConcurrentTask::subTaskStatus(Task::Ptr task, const QString& msg) task_progress->status = msg; task_progress->state = TaskStepState::Running; - emit stepProgress(*task_progress.get()); + emit stepProgress(*task_progress); if (totalSize() == 1) { setStatus(msg); @@ -209,7 +209,7 @@ void ConcurrentTask::subTaskDetails(Task::Ptr task, const QString& msg) task_progress->details = msg; task_progress->state = TaskStepState::Running; - emit stepProgress(*task_progress.get()); + emit stepProgress(*task_progress); if (totalSize() == 1) { setDetails(msg); @@ -220,15 +220,10 @@ void ConcurrentTask::subTaskProgress(Task::Ptr task, qint64 current, qint64 tota { auto task_progress = m_task_progress.value(task->getUid()); - task_progress->old_current = task_progress->current; - task_progress->old_total = task_progress->old_total; - - task_progress->current = current; - task_progress->total = total; - task_progress->state = TaskStepState::Running; - - emit stepProgress(*task_progress.get()); - updateStepProgress(*task_progress.get(), Operation::CHANGED); + task_progress->update(current, total); + + emit stepProgress(*task_progress); + updateStepProgress(*task_progress, Operation::CHANGED); updateState(); if (totalSize() == 1) { diff --git a/launcher/tasks/Task.cpp b/launcher/tasks/Task.cpp index b0addd46..29c55cd4 100644 --- a/launcher/tasks/Task.cpp +++ b/launcher/tasks/Task.cpp @@ -109,7 +109,7 @@ void Task::start() return; } } - // NOTE: only fall thorugh to here in end states + // NOTE: only fall through to here in end states m_state = State::Running; emit started(); executeTask(); diff --git a/launcher/tasks/Task.h b/launcher/tasks/Task.h index 799ed945..6d8bbbb4 100644 --- a/launcher/tasks/Task.h +++ b/launcher/tasks/Task.h @@ -64,7 +64,21 @@ struct TaskStepProgress { QString status = ""; QString details = ""; TaskStepState state = TaskStepState::Waiting; + TaskStepProgress() { + this->uid = QUuid::createUuid(); + } + TaskStepProgress(QUuid uid) { + this->uid = uid; + } bool isDone() const { return (state == TaskStepState::Failed) || (state == TaskStepState::Succeeded); } + void update(qint64 current, qint64 total) { + this->old_current = this->current; + this->old_total = this->total; + + this->current = current; + this->total = total; + this->state = TaskStepState::Running; + } }; Q_DECLARE_METATYPE(TaskStepProgress) -- cgit From 21cb4598999808849eb18503f7aae54039c73cea Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 21 May 2023 01:47:54 -0700 Subject: fix: memory leak NetJob wans't getting cleaned up. ensure lambda capture of job doens;t increase refcount or it will be cyclic Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/modplatform/flame/FlameAPI.cpp | 41 ++++++++++++--------------------- 1 file changed, 15 insertions(+), 26 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 5ef9a409..92590a08 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -38,14 +38,14 @@ auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString QEventLoop lock; QString changelog; - auto* netJob = new NetJob(QString("Flame::FileChangelog"), APPLICATION->network()); - auto* response = new QByteArray(); + auto netJob = makeShared(QString("Flame::FileChangelog"), APPLICATION->network()); + auto response = std::make_shared(); netJob->addNetAction(Net::Download::makeByteArray( QString("https://api.curseforge.com/v1/mods/%1/files/%2/changelog") .arg(QString::fromStdString(std::to_string(modId)), QString::fromStdString(std::to_string(fileId))), - response)); + response.get())); - QObject::connect(netJob, &NetJob::succeeded, [netJob, response, &changelog] { + QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &changelog] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -60,10 +60,7 @@ auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString changelog = Json::ensureString(doc.object(), "data"); }); - QObject::connect(netJob, &NetJob::finished, [response, &lock] { - delete response; - lock.quit(); - }); + QObject::connect(netJob.get(), &NetJob::finished, [&lock] { lock.quit(); }); netJob->start(); lock.exec(); @@ -76,13 +73,12 @@ auto FlameAPI::getModDescription(int modId) -> QString QEventLoop lock; QString description; - auto* netJob = new NetJob(QString("Flame::ModDescription"), APPLICATION->network()); - auto* response = new QByteArray(); + auto netJob = makeShared(QString("Flame::ModDescription"), APPLICATION->network()); + auto response = std::make_shared(); netJob->addNetAction(Net::Download::makeByteArray( - QString("https://api.curseforge.com/v1/mods/%1/description") - .arg(QString::number(modId)), response)); + QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response.get())); - QObject::connect(netJob, &NetJob::succeeded, [netJob, response, &description] { + QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -97,10 +93,7 @@ auto FlameAPI::getModDescription(int modId) -> QString description = Json::ensureString(doc.object(), "data"); }); - QObject::connect(netJob, &NetJob::finished, [response, &lock] { - delete response; - lock.quit(); - }); + QObject::connect(netJob.get(), &NetJob::finished, [&lock] { lock.quit(); }); netJob->start(); lock.exec(); @@ -118,13 +111,13 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe QEventLoop loop; - auto netJob = new NetJob(QString("Flame::GetLatestVersion(%1)").arg(args.pack.name), APPLICATION->network()); - auto response = new QByteArray(); + auto netJob = makeShared(QString("Flame::GetLatestVersion(%1)").arg(args.pack.name), APPLICATION->network()); + auto response = std::make_shared(); ModPlatform::IndexedVersion ver; - netJob->addNetAction(Net::Download::makeByteArray(versions_url, response)); + netJob->addNetAction(Net::Download::makeByteArray(versions_url, response.get())); - QObject::connect(netJob, &NetJob::succeeded, [response, args, &ver] { + QObject::connect(netJob.get(), &NetJob::succeeded, [response, args, &ver] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -158,11 +151,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe } }); - QObject::connect(netJob, &NetJob::finished, [response, netJob, &loop] { - netJob->deleteLater(); - delete response; - loop.quit(); - }); + QObject::connect(netJob.get(), &NetJob::finished, [&loop] { loop.quit(); }); netJob->start(); -- cgit From 79839771561641d6fa34549861a5ed163e382312 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 21 May 2023 01:48:34 -0700 Subject: feat: Qt 5.15 adds transfer timeouts. at least use it for downloads Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/net/Download.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index cd3fcc85..7f8d3a06 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -134,11 +134,14 @@ void Download::executeTask() request.setRawHeader("Authorization", token.toUtf8()); } +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + request.setTransferTimeout(); +#endif + m_last_progress_time = m_clock.now(); m_last_progress_bytes = 0; QNetworkReply* rep = m_network->get(request); - m_reply.reset(rep); connect(rep, &QNetworkReply::downloadProgress, this, &Download::downloadProgress); connect(rep, &QNetworkReply::finished, this, &Download::downloadFinished); -- cgit From 6b8fe283f0bda66806175de10ba5874a4afdae45 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 21 May 2023 01:49:13 -0700 Subject: fix: memory leak, set parent so it's in tree to get cleaned up. Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/pages/instance/VersionPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index fffb96f2..74b7ec7c 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -165,7 +165,7 @@ VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent) auto proxy = new IconProxy(ui->packageView); proxy->setSourceModel(m_profile.get()); - m_filterModel = new QSortFilterProxyModel(); + m_filterModel = new QSortFilterProxyModel(this); m_filterModel->setDynamicSortFilter(true); m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive); m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive); -- cgit From 863027cbe826bbb38f7bebdef436a9682d094cb2 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 22 May 2023 11:56:37 +0100 Subject: Enable size grip Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ExportMrPackDialog.ui | 3 +++ 1 file changed, 3 insertions(+) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportMrPackDialog.ui index 8e6d61ff..f154d210 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.ui +++ b/launcher/ui/dialogs/ExportMrPackDialog.ui @@ -13,6 +13,9 @@ Export Modrinth Pack + + true + -- cgit From 3c937532f2c76257f47da04b1d71e48bfc839dc6 Mon Sep 17 00:00:00 2001 From: Tayou Date: Wed, 24 May 2023 15:18:08 +0200 Subject: fix System theme colors on windows Signed-off-by: Tayou --- launcher/ui/themes/SystemTheme.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/themes/SystemTheme.cpp b/launcher/ui/themes/SystemTheme.cpp index a95bc875..3a746d02 100644 --- a/launcher/ui/themes/SystemTheme.cpp +++ b/launcher/ui/themes/SystemTheme.cpp @@ -43,7 +43,7 @@ SystemTheme::SystemTheme() { themeDebugLog() << "Determining System Theme..."; const auto& style = QApplication::style(); - systemPalette = style->standardPalette(); + systemPalette = QApplication::palette(); QString lowerThemeName = style->objectName(); themeDebugLog() << "System theme seems to be:" << lowerThemeName; QStringList styles = QStyleFactory::keys(); -- cgit From 086a7e19f099c6c9b9529afb2360300e534876bf Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 24 May 2023 20:15:34 -0700 Subject: feat: Column on left, hideable - columns are hideable (saves to settings) - image column moved to left - datamodals can provide resize modes Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/ModFolderModel.cpp | 6 +- launcher/minecraft/mod/ModFolderModel.h | 4 +- launcher/minecraft/mod/ResourceFolderModel.cpp | 66 ++++++++++++++++++++++ launcher/minecraft/mod/ResourceFolderModel.h | 12 ++++ launcher/minecraft/mod/ResourcePackFolderModel.cpp | 6 +- launcher/minecraft/mod/ResourcePackFolderModel.h | 4 +- launcher/minecraft/mod/ShaderPackFolderModel.h | 2 + launcher/minecraft/mod/TexturePackFolderModel.cpp | 9 ++- launcher/minecraft/mod/TexturePackFolderModel.h | 4 +- .../ui/pages/instance/ExternalResourcesPage.cpp | 15 +++++ launcher/ui/pages/instance/ExternalResourcesPage.h | 1 + launcher/ui/widgets/ModListView.cpp | 9 +++ launcher/ui/widgets/ModListView.h | 2 + 13 files changed, 131 insertions(+), 9 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 8843f79f..59e078f1 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -37,6 +37,7 @@ #include "ModFolderModel.h" #include +#include #include #include #include @@ -56,7 +57,8 @@ ModFolderModel::ModFolderModel(const QString& dir, std::shared_ptr instance, bool is_indexed, bool create_dir) : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed) { - m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER, SortType::NAME }; + m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME , SortType::VERSION, SortType::DATE, SortType::PROVIDER}; + m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents}; } QVariant ModFolderModel::data(const QModelIndex &index, int role) const @@ -143,7 +145,7 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in switch (section) { case ActiveColumn: - return QString(); + return tr("Enable"); case NameColumn: return tr("Name"); case VersionColumn: diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index 20018e9c..c1f9a2b6 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -64,11 +64,11 @@ public: enum Columns { ActiveColumn = 0, + ImageColumn, NameColumn, VersionColumn, DateColumn, ProviderColumn, - ImageColumn, NUM_COLUMNS }; enum ModStatusAction { @@ -78,6 +78,8 @@ public: }; ModFolderModel(const QString &dir, std::shared_ptr instance, bool is_indexed = false, bool create_dir = true); + virtual QString id() const override { return "mods"; } + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index e1973468..ba64497b 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -8,12 +8,15 @@ #include #include #include +#include #include "Application.h" #include "FileSystem.h" +#include "QVariantUtils.h" #include "minecraft/mod/tasks/BasicFolderLoadTask.h" +#include "settings/Setting.h" #include "tasks/Task.h" ResourceFolderModel::ResourceFolderModel(QDir dir, std::shared_ptr instance, QObject* parent, bool create_dir) @@ -471,6 +474,8 @@ QVariant ResourceFolderModel::headerData(int section, Qt::Orientation orientatio switch (role) { case Qt::DisplayRole: switch (section) { + case ACTIVE_COLUMN: + return tr("Enable"); case NAME_COLUMN: return tr("Name"); case DATE_COLUMN: @@ -500,6 +505,67 @@ QVariant ResourceFolderModel::headerData(int section, Qt::Orientation orientatio return {}; } +void ResourceFolderModel::setupHeaderAction(QAction* act, int column) +{ + Q_ASSERT(act); + + act->setText(headerData(column, Qt::Orientation::Horizontal).toString()); +} + +void ResourceFolderModel::saveHiddenColumn(int column, bool hidden) +{ + auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id()); + auto setting = (APPLICATION->settings()->contains(setting_name)) ? + APPLICATION->settings()->getSetting(setting_name) : APPLICATION->settings()->registerSetting(setting_name); + + auto hiddenColumns = QVariantUtils::toList(setting->get()); + auto index = hiddenColumns.indexOf(column); + if (index >= 0 && !hidden) { + hiddenColumns.removeAt(index); + } else if ( index < 0 && hidden) { + hiddenColumns.append(column); + } + setting->set(QVariantUtils::fromList(hiddenColumns)); +} + +void ResourceFolderModel::loadHiddenColumns(QTreeView *tree) +{ + auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id()); + auto setting = (APPLICATION->settings()->contains(setting_name)) ? + APPLICATION->settings()->getSetting(setting_name) : APPLICATION->settings()->registerSetting(setting_name); + + auto hiddenColumns = QVariantUtils::toList(setting->get().toList()); + for (auto col : hiddenColumns) { + tree->setColumnHidden(col, true); + } + +} + +std::unique_ptr ResourceFolderModel::createHeaderContextMenu(QWidget* parent, QTreeView* tree) +{ + auto menu = std::make_unique(parent); + + menu->addSeparator()->setText(tr("Show / Hide Columns")); + + for (int col = 0; col < columnCount(); ++col) { + auto act = new QAction(); + setupHeaderAction(act, col); + + act->setCheckable(true); + act->setChecked(!tree->isColumnHidden(col)); + + connect(act, &QAction::toggled, tree, [this, col, tree](bool toggled){ + tree->setColumnHidden(col, !toggled); + saveHiddenColumn(col, !toggled); + }); + + menu->addAction(act); + + } + + return menu; +} + QSortFilterProxyModel* ResourceFolderModel::createFilterProxyModel(QObject* parent) { return new ProxyModel(parent); diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index fdf5f331..54627c80 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -1,5 +1,8 @@ #pragma once +#include +#include +#include #include #include #include @@ -29,6 +32,8 @@ class ResourceFolderModel : public QAbstractListModel { ResourceFolderModel(QDir, std::shared_ptr, QObject* parent = nullptr, bool create_dir = true); ~ResourceFolderModel() override; + virtual QString id() const { return "resource"; } + /** Starts watching the paths for changes. * * Returns whether starting to watch all the paths was successful. @@ -110,6 +115,11 @@ class ResourceFolderModel : public QAbstractListModel { [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + void setupHeaderAction(QAction* act, int column); + void saveHiddenColumn(int column, bool hidden); + void loadHiddenColumns(QTreeView* tree); + std::unique_ptr createHeaderContextMenu(QWidget* parent, QTreeView* tree); + /** This creates a proxy model to filter / sort the model for a UI. * * The actual comparisons and filtering are done directly by the Resource, so to modify behavior go there instead! @@ -117,6 +127,7 @@ class ResourceFolderModel : public QAbstractListModel { QSortFilterProxyModel* createFilterProxyModel(QObject* parent = nullptr); [[nodiscard]] SortType columnToSortKey(size_t column) const; + [[nodiscard]] QList columnResizeModes() const { return m_column_resize_modes; } class ProxyModel : public QSortFilterProxyModel { public: @@ -187,6 +198,7 @@ class ResourceFolderModel : public QAbstractListModel { // Represents the relationship between a column's index (represented by the list index), and it's sorting key. // As such, the order in with they appear is very important! QList m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE }; + QList m_column_resize_modes = { QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents }; bool m_can_interact = true; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index b11e2262..7ec5668c 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -50,7 +50,9 @@ ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, std::shared_ptr instance) : ResourceFolderModel(QDir(dir), instance) { - m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE, SortType::NAME }; + m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE}; + m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents}; + } QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const @@ -130,7 +132,7 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient case Qt::DisplayRole: switch (section) { case ActiveColumn: - return QString(); + return tr("Enable"); case NameColumn: return tr("Name"); case PackFormatColumn: diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.h b/launcher/minecraft/mod/ResourcePackFolderModel.h index 71532f30..bbec9619 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.h +++ b/launcher/minecraft/mod/ResourcePackFolderModel.h @@ -11,15 +11,17 @@ public: enum Columns { ActiveColumn = 0, + ImageColumn, NameColumn, PackFormatColumn, DateColumn, - ImageColumn, NUM_COLUMNS }; explicit ResourcePackFolderModel(const QString &dir, std::shared_ptr instance); + virtual QString id() const override { return "resourcepacks"; } + [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; diff --git a/launcher/minecraft/mod/ShaderPackFolderModel.h b/launcher/minecraft/mod/ShaderPackFolderModel.h index 6f3f2811..e010f6ed 100644 --- a/launcher/minecraft/mod/ShaderPackFolderModel.h +++ b/launcher/minecraft/mod/ShaderPackFolderModel.h @@ -9,4 +9,6 @@ class ShaderPackFolderModel : public ResourceFolderModel { explicit ShaderPackFolderModel(const QString& dir, std::shared_ptr instance) : ResourceFolderModel(QDir(dir), instance) {} + + virtual QString id() const override { return "shaderpacks"; } }; diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index e115cce6..c88f8f37 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -45,7 +45,9 @@ TexturePackFolderModel::TexturePackFolderModel(const QString& dir, std::shared_ptr instance) : ResourceFolderModel(QDir(dir), instance) { - m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE, SortType::NAME }; + m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::DATE }; + m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents}; + } Task* TexturePackFolderModel::createUpdateTask() @@ -115,6 +117,8 @@ QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orienta switch (role) { case Qt::DisplayRole: switch (section) { + case ActiveColumn: + return tr("Enable"); case NameColumn: return tr("Name"); case DateColumn: @@ -149,4 +153,5 @@ QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orienta int TexturePackFolderModel::columnCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : NUM_COLUMNS; -} \ No newline at end of file +} + diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h index 4467691a..ce9c06c4 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.h +++ b/launcher/minecraft/mod/TexturePackFolderModel.h @@ -49,14 +49,16 @@ public: enum Columns { ActiveColumn = 0, + ImageColumn, NameColumn, DateColumn, - ImageColumn, NUM_COLUMNS }; explicit TexturePackFolderModel(const QString &dir, std::shared_ptr instance); + virtual QString id() const override { return "texturepacks"; } + [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index 6c11b85b..bee11d9a 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -24,6 +24,8 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared m_filterModel->setSourceModel(m_model.get()); m_filterModel->setFilterKeyColumn(-1); ui->treeView->setModel(m_filterModel); + // must come after setModel + ui->treeView->setResizeModes(m_model->columnResizeModes()); ui->treeView->installEventFilter(this); ui->treeView->sortByColumn(1, Qt::AscendingOrder); @@ -44,6 +46,13 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared auto selection_model = ui->treeView->selectionModel(); connect(selection_model, &QItemSelectionModel::currentChanged, this, &ExternalResourcesPage::current); connect(ui->filterEdit, &QLineEdit::textChanged, this, &ExternalResourcesPage::filterTextChanged); + + auto viewHeader = ui->treeView->header(); + viewHeader->setContextMenuPolicy(Qt::CustomContextMenu); + + connect(viewHeader, &QHeaderView::customContextMenuRequested, this, &ExternalResourcesPage::ShowHeaderContextMenu); + + m_model->loadHiddenColumns(ui->treeView); } ExternalResourcesPage::~ExternalResourcesPage() @@ -65,6 +74,12 @@ void ExternalResourcesPage::ShowContextMenu(const QPoint& pos) delete menu; } +void ExternalResourcesPage::ShowHeaderContextMenu(const QPoint& pos) +{ + auto menu = m_model->createHeaderContextMenu(this, ui->treeView); + menu->exec(ui->treeView->mapToGlobal(pos)); +} + void ExternalResourcesPage::openedImpl() { m_model->startWatching(); diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.h b/launcher/ui/pages/instance/ExternalResourcesPage.h index d17fbb7f..906e6df7 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.h +++ b/launcher/ui/pages/instance/ExternalResourcesPage.h @@ -60,6 +60,7 @@ class ExternalResourcesPage : public QMainWindow, public BasePage { virtual void viewConfigs(); void ShowContextMenu(const QPoint& pos); + void ShowHeaderContextMenu(const QPoint& pos); protected: BaseInstance* m_instance = nullptr; diff --git a/launcher/ui/widgets/ModListView.cpp b/launcher/ui/widgets/ModListView.cpp index 09b03a76..893cd120 100644 --- a/launcher/ui/widgets/ModListView.cpp +++ b/launcher/ui/widgets/ModListView.cpp @@ -79,3 +79,12 @@ void ModListView::setModel ( QAbstractItemModel* model ) }); } } + +void ModListView::setResizeModes(const QList &modes) +{ + auto head = header(); + for(int i = 0; i < modes.count(); i++) { + head->setSectionResizeMode(i, modes[i]); + } +} + diff --git a/launcher/ui/widgets/ModListView.h b/launcher/ui/widgets/ModListView.h index 881e092f..3f0b3b0e 100644 --- a/launcher/ui/widgets/ModListView.h +++ b/launcher/ui/widgets/ModListView.h @@ -14,6 +14,7 @@ */ #pragma once +#include #include class ModListView: public QTreeView @@ -22,4 +23,5 @@ class ModListView: public QTreeView public: explicit ModListView ( QWidget* parent = 0 ); virtual void setModel ( QAbstractItemModel* model ); + virtual void setResizeModes (const QList& modes); }; -- cgit From e61d8e4dc870aaeb2949557a87cf2749df573667 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 25 May 2023 16:16:58 -0700 Subject: fix: katabasis and QStyle leaks Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/pages/instance/ManagedPackPage.cpp | 7 +++++-- libraries/katabasis/src/Reply.cpp | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index dc983d9a..593590f7 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -62,8 +62,11 @@ ManagedPackPage::ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_wi // NOTE: GTK2 themes crash with the proxy style. // This seems like an upstream bug, so there's not much else that can be done. - if (!QStyleFactory::keys().contains("gtk2")) - ui->versionsComboBox->setStyle(new NoBigComboBoxStyle(ui->versionsComboBox->style())); + if (!QStyleFactory::keys().contains("gtk2")){ + auto comboStyle = new NoBigComboBoxStyle(ui->versionsComboBox->style()); + comboStyle->setParent(APPLICATION); // make sure this gets cleaned up (setting to simply `this` causes it to be freed too soon) + ui->versionsComboBox->setStyle(comboStyle); + } ui->reloadButton->setVisible(false); connect(ui->reloadButton, &QPushButton::clicked, this, [this](bool){ diff --git a/libraries/katabasis/src/Reply.cpp b/libraries/katabasis/src/Reply.cpp index 3e27a7e6..c2607900 100644 --- a/libraries/katabasis/src/Reply.cpp +++ b/libraries/katabasis/src/Reply.cpp @@ -40,6 +40,8 @@ void ReplyList::remove(QNetworkReply *reply) { if (o2Reply) { o2Reply->stop(); (void)replies_.removeOne(o2Reply); + // we took ownership, we must free + delete o2Reply; } } -- cgit From aae892dfd1a28411fc14c267c073c71c20696f39 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 26 May 2023 19:21:07 -0700 Subject: fix(memory leak): IndexedPack too large to live inside a qlist without pointers () Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/modplatform/ModIndex.h | 3 +++ launcher/ui/pages/modplatform/ModModel.cpp | 4 +-- launcher/ui/pages/modplatform/ResourceModel.cpp | 29 +++++++++++----------- launcher/ui/pages/modplatform/ResourceModel.h | 2 +- .../ui/pages/modplatform/ResourcePackModel.cpp | 4 +-- launcher/ui/pages/modplatform/ShaderPackModel.cpp | 4 +-- tests/ResourceModel_test.cpp | 6 ++--- 7 files changed, 28 insertions(+), 24 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 40f1efc4..8d0223f9 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -23,6 +23,7 @@ #include #include #include +#include class QIODevice; @@ -83,6 +84,8 @@ struct ExtraPackData { }; struct IndexedPack { + using Ptr = std::shared_ptr; + QVariant addonId; ResourceProvider provider; QString name; diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index 3ffe6cb0..afd8b292 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -36,7 +36,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments() ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& entry) { - auto& pack = m_packs[entry.row()]; + auto& pack = *m_packs[entry.row()]; auto profile = static_cast(m_base_instance).getPackProfile(); Q_ASSERT(profile); @@ -51,7 +51,7 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry) { - auto& pack = m_packs[entry.row()]; + auto& pack = *m_packs[entry.row()]; return { pack }; } diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index db7d26f8..631ae68c 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "Application.h" #include "BuildConfig.h" @@ -45,16 +46,16 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant auto pack = m_packs.at(pos); switch (role) { case Qt::ToolTipRole: { - if (pack.description.length() > 100) { + if (pack->description.length() > 100) { // some magic to prevent to long tooltips and replace html linebreaks - QString edit = pack.description.left(97); + QString edit = pack->description.left(97); edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); return edit; } - return pack.description; + return pack->description; } case Qt::DecorationRole: { - if (auto icon_or_none = const_cast(this)->getIcon(const_cast(index), pack.logoUrl); + if (auto icon_or_none = const_cast(this)->getIcon(const_cast(index), pack->logoUrl); icon_or_none.has_value()) return icon_or_none.value(); @@ -64,16 +65,16 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant return QSize(0, 58); case Qt::UserRole: { QVariant v; - v.setValue(pack); + v.setValue(*pack); return v; } // Custom data case UserDataTypes::TITLE: - return pack.name; + return pack->name; case UserDataTypes::DESCRIPTION: - return pack.description; + return pack->description; case UserDataTypes::SELECTED: - return pack.isAnyVersionSelected(); + return pack->isAnyVersionSelected(); default: break; } @@ -102,7 +103,7 @@ bool ResourceModel::setData(const QModelIndex& index, const QVariant& value, int if (pos >= m_packs.size() || pos < 0 || !index.isValid()) return false; - m_packs[pos] = value.value(); + m_packs[pos] = std::make_shared(value.value()); emit dataChanged(index, index); return true; @@ -161,7 +162,7 @@ void ResourceModel::loadEntry(QModelIndex& entry) if (!hasActiveInfoJob()) m_current_info_job.clear(); - if (!pack.versionsLoaded) { + if (!pack->versionsLoaded) { auto args{ createVersionsArguments(entry) }; auto callbacks{ createVersionsCallbacks(entry) }; @@ -177,7 +178,7 @@ void ResourceModel::loadEntry(QModelIndex& entry) runInfoJob(job); } - if (!pack.extraDataLoaded) { + if (!pack->extraDataLoaded) { auto args{ createInfoArguments(entry) }; auto callbacks{ createInfoCallbacks(entry) }; @@ -326,15 +327,15 @@ void ResourceModel::loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArra void ResourceModel::searchRequestSucceeded(QJsonDocument& doc) { - QList newList; + QList newList; auto packs = documentToArray(doc); for (auto packRaw : packs) { auto packObj = packRaw.toObject(); - ModPlatform::IndexedPack pack; + ModPlatform::IndexedPack::Ptr pack = std::make_shared(); try { - loadIndexedPack(pack, packObj); + loadIndexedPack(*pack, packObj); newList.append(pack); } catch (const JSONValidationError& e) { qWarning() << "Error while loading resource from " << debugName() << ": " << e.cause(); diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 46a02d6e..1ec42cda 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -123,7 +123,7 @@ class ResourceModel : public QAbstractListModel { QSet m_currently_running_icon_actions; QSet m_failed_icon_actions; - QList m_packs; + QList m_packs; // HACK: We need this to prevent callbacks from calling the model after it has already been deleted. // This leaks a tiny bit of memory per time the user has opened a resource dialog. How to make this better? diff --git a/launcher/ui/pages/modplatform/ResourcePackModel.cpp b/launcher/ui/pages/modplatform/ResourcePackModel.cpp index 3df9a787..18c14bf8 100644 --- a/launcher/ui/pages/modplatform/ResourcePackModel.cpp +++ b/launcher/ui/pages/modplatform/ResourcePackModel.cpp @@ -22,13 +22,13 @@ ResourceAPI::SearchArgs ResourcePackResourceModel::createSearchArguments() ResourceAPI::VersionSearchArgs ResourcePackResourceModel::createVersionsArguments(QModelIndex& entry) { auto& pack = m_packs[entry.row()]; - return { pack }; + return { *pack }; } ResourceAPI::ProjectInfoArgs ResourcePackResourceModel::createInfoArguments(QModelIndex& entry) { auto& pack = m_packs[entry.row()]; - return { pack }; + return { *pack }; } void ResourcePackResourceModel::searchWithTerm(const QString& term, unsigned int sort) diff --git a/launcher/ui/pages/modplatform/ShaderPackModel.cpp b/launcher/ui/pages/modplatform/ShaderPackModel.cpp index 2101b394..aabd3be6 100644 --- a/launcher/ui/pages/modplatform/ShaderPackModel.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackModel.cpp @@ -22,13 +22,13 @@ ResourceAPI::SearchArgs ShaderPackResourceModel::createSearchArguments() ResourceAPI::VersionSearchArgs ShaderPackResourceModel::createVersionsArguments(QModelIndex& entry) { auto& pack = m_packs[entry.row()]; - return { pack }; + return { *pack }; } ResourceAPI::ProjectInfoArgs ShaderPackResourceModel::createInfoArguments(QModelIndex& entry) { auto& pack = m_packs[entry.row()]; - return { pack }; + return { *pack }; } void ShaderPackResourceModel::searchWithTerm(const QString& term, unsigned int sort) diff --git a/tests/ResourceModel_test.cpp b/tests/ResourceModel_test.cpp index 716bf853..c0d9cd95 100644 --- a/tests/ResourceModel_test.cpp +++ b/tests/ResourceModel_test.cpp @@ -75,9 +75,9 @@ class ResourceModelTest : public QObject { auto search_json = DummyResourceAPI::searchRequestResult(); auto processed_response = model->documentToArray(search_json).first().toObject(); - QVERIFY(processed_pack.addonId.toString() == Json::requireString(processed_response, "project_id")); - QVERIFY(processed_pack.description == Json::requireString(processed_response, "description")); - QVERIFY(processed_pack.authors.first().name == Json::requireString(processed_response, "author")); + QVERIFY(processed_pack->addonId.toString() == Json::requireString(processed_response, "project_id")); + QVERIFY(processed_pack->description == Json::requireString(processed_response, "description")); + QVERIFY(processed_pack->authors.first().name == Json::requireString(processed_response, "author")); } }; -- cgit From ff03dd22fe842fc3a24b517f8e9f7a8a54565337 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 26 May 2023 21:10:49 -0700 Subject: fix(memory leak): don't override default deconstructor + reset shared_ptr + ensure modal get's cleaned up Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/pages/modplatform/ModPage.h | 2 -- launcher/ui/pages/modplatform/ResourceModel.cpp | 2 +- launcher/ui/pages/modplatform/ResourcePackPage.h | 2 -- launcher/ui/pages/modplatform/ResourcePage.cpp | 2 ++ launcher/ui/pages/modplatform/ShaderPackPage.h | 2 -- 5 files changed, 3 insertions(+), 7 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h index c3b58cd6..4ea55efa 100644 --- a/launcher/ui/pages/modplatform/ModPage.h +++ b/launcher/ui/pages/modplatform/ModPage.h @@ -41,8 +41,6 @@ class ModPage : public ResourcePage { return page; } - ~ModPage() override = default; - //: The plural version of 'mod' [[nodiscard]] inline QString resourcesString() const override { return tr("mods"); } //: The singular version of 'mods' diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 631ae68c..472aa851 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -230,7 +230,7 @@ void ResourceModel::clearData() void ResourceModel::runSearchJob(Task::Ptr ptr) { - m_current_search_job = ptr; + m_current_search_job.reset(ptr); // clean up first m_current_search_job->start(); } void ResourceModel::runInfoJob(Task::Ptr ptr) diff --git a/launcher/ui/pages/modplatform/ResourcePackPage.h b/launcher/ui/pages/modplatform/ResourcePackPage.h index c01c89c4..8c5cf08b 100644 --- a/launcher/ui/pages/modplatform/ResourcePackPage.h +++ b/launcher/ui/pages/modplatform/ResourcePackPage.h @@ -31,8 +31,6 @@ class ResourcePackResourcePage : public ResourcePage { return page; } - ~ResourcePackResourcePage() override = default; - //: The plural version of 'resource pack' [[nodiscard]] inline QString resourcesString() const override { return tr("resource packs"); } //: The singular version of 'resource packs' diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index bbd465bc..f75bb886 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -83,6 +83,8 @@ ResourcePage::ResourcePage(ResourceDownloadDialog* parent, BaseInstance& base_in ResourcePage::~ResourcePage() { delete m_ui; + if (m_model) + delete m_model; } void ResourcePage::retranslate() diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.h b/launcher/ui/pages/modplatform/ShaderPackPage.h index 972419a8..9039c4d9 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.h +++ b/launcher/ui/pages/modplatform/ShaderPackPage.h @@ -31,8 +31,6 @@ class ShaderPackResourcePage : public ResourcePage { return page; } - ~ShaderPackResourcePage() override = default; - //: The plural version of 'shader pack' [[nodiscard]] inline QString resourcesString() const override { return tr("shader packs"); } //: The singular version of 'shader packs' -- cgit From c81cb59b4b76bc4558a857c7e13c50629c6b27db Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 26 May 2023 21:21:10 -0700 Subject: fix(memory leak): don't capture job and create cyclic refrence Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/modplatform/helpers/NetworkResourceAPI.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp index 010ac15e..a3c592fd 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp +++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp @@ -24,7 +24,7 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks& netJob->addNetAction(Net::Download::makeByteArray(QUrl(search_url), response)); - QObject::connect(netJob.get(), &NetJob::succeeded, [=]{ + QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks]{ QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -40,16 +40,20 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks& callbacks.on_succeed(doc); }); - QObject::connect(netJob.get(), &NetJob::failed, [=](QString reason){ + QObject::connect(netJob.get(), &NetJob::failed, [&netJob, callbacks](QString reason){ int network_error_code = -1; if (auto* failed_action = netJob->getFailedActions().at(0); failed_action && failed_action->m_reply) network_error_code = failed_action->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); callbacks.on_fail(reason, network_error_code); }); - QObject::connect(netJob.get(), &NetJob::aborted, [=]{ + QObject::connect(netJob.get(), &NetJob::aborted, [callbacks]{ callbacks.on_abort(); }); + QObject::connect(netJob.get(), &NetJob::finished, [response] { + delete response; + }); + return netJob; } @@ -88,7 +92,7 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi netJob->addNetAction(Net::Download::makeByteArray(versions_url, response)); - QObject::connect(netJob.get(), &NetJob::succeeded, [=] { + QObject::connect(netJob.get(), &NetJob::succeeded, [response, callbacks, args] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { -- cgit From 37420405c7b5dddb003533e1487ba45a2da5b808 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 27 May 2023 23:22:40 -0700 Subject: fix(memory leak): refactor NoBigComboStyle -> singleton Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/pages/instance/ManagedPackPage.cpp | 33 ++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index 593590f7..ac34a5f4 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -41,8 +41,38 @@ class NoBigComboBoxStyle : public QProxyStyle { return QProxyStyle::styleHint(hint, option, widget, returnData); } // clang-format on + + static NoBigComboBoxStyle* GetInstance(QStyle* style); + + private: + static QMap s_singleton_instances_; + static std::mutex s_singleton_instances_mutex_; }; +QMap NoBigComboBoxStyle::s_singleton_instances_ = {}; +std::mutex NoBigComboBoxStyle::s_singleton_instances_mutex_; + +/** + * QProxyStyle and QStyle objects object to being freed even if all the widgets using them are gone + * so make singlestons tied to the lifetime of the application to clean them up and ensure they arn't + * being remade over and over agian leaking memory. + * */ +NoBigComboBoxStyle* NoBigComboBoxStyle::GetInstance(QStyle* style) +{ + std::lock_guard lock(s_singleton_instances_mutex_); + auto inst_iter = s_singleton_instances_.constFind(style); + NoBigComboBoxStyle* inst = nullptr; + if(inst_iter == s_singleton_instances_.constEnd() || *inst_iter == nullptr) { + inst = new NoBigComboBoxStyle(style); + inst->setParent(APPLICATION); + s_singleton_instances_.insert(style, inst); + qDebug() << "QProxyStyle NoBigComboBox created for" << style->objectName() << style; + } else { + inst = *inst_iter; + } + return inst; +} + ManagedPackPage* ManagedPackPage::createPage(BaseInstance* inst, QString type, QWidget* parent) { if (type == "modrinth") @@ -63,8 +93,7 @@ ManagedPackPage::ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_wi // NOTE: GTK2 themes crash with the proxy style. // This seems like an upstream bug, so there's not much else that can be done. if (!QStyleFactory::keys().contains("gtk2")){ - auto comboStyle = new NoBigComboBoxStyle(ui->versionsComboBox->style()); - comboStyle->setParent(APPLICATION); // make sure this gets cleaned up (setting to simply `this` causes it to be freed too soon) + auto comboStyle = NoBigComboBoxStyle::GetInstance(ui->versionsComboBox->style()); ui->versionsComboBox->setStyle(comboStyle); } -- cgit From a04a6f1e0d0d551506a86964c51e5ce6af5587b4 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 28 May 2023 02:15:39 -0700 Subject: fix(memory leak): don't give shared pointers out to foldermodels (causes cyclic refrence) Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/MinecraftInstance.cpp | 30 +++++++++++----------- launcher/minecraft/MinecraftInstance.h | 16 ++++++------ launcher/minecraft/WorldList.cpp | 2 +- launcher/minecraft/WorldList.h | 4 +-- launcher/minecraft/mod/ModFolderModel.cpp | 2 +- launcher/minecraft/mod/ModFolderModel.h | 2 +- launcher/minecraft/mod/ResourceFolderModel.cpp | 2 +- launcher/minecraft/mod/ResourceFolderModel.h | 4 +-- launcher/minecraft/mod/ResourcePackFolderModel.cpp | 2 +- launcher/minecraft/mod/ResourcePackFolderModel.h | 2 +- launcher/minecraft/mod/ShaderPackFolderModel.h | 2 +- launcher/minecraft/mod/TexturePackFolderModel.cpp | 2 +- launcher/minecraft/mod/TexturePackFolderModel.h | 2 +- launcher/ui/dialogs/NewInstanceDialog.cpp | 2 +- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 2 +- launcher/ui/widgets/PageContainer.cpp | 4 ++- tests/ResourceFolderModel_test.cpp | 17 ++++-------- 17 files changed, 46 insertions(+), 51 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 35bef05e..2c624a36 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -1109,79 +1109,79 @@ JavaVersion MinecraftInstance::getJavaVersion() return JavaVersion(settings()->get("JavaVersion").toString()); } -std::shared_ptr MinecraftInstance::loaderModList() const +std::shared_ptr MinecraftInstance::loaderModList() { if (!m_loader_mod_list) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); - m_loader_mod_list.reset(new ModFolderModel(modsRoot(), shared_from_this(), is_indexed)); + m_loader_mod_list.reset(new ModFolderModel(modsRoot(), this, is_indexed)); m_loader_mod_list->disableInteraction(isRunning()); connect(this, &BaseInstance::runningStatusChanged, m_loader_mod_list.get(), &ModFolderModel::disableInteraction); } return m_loader_mod_list; } -std::shared_ptr MinecraftInstance::coreModList() const +std::shared_ptr MinecraftInstance::coreModList() { if (!m_core_mod_list) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); - m_core_mod_list.reset(new ModFolderModel(coreModsDir(), shared_from_this(), is_indexed)); + m_core_mod_list.reset(new ModFolderModel(coreModsDir(), this, is_indexed)); m_core_mod_list->disableInteraction(isRunning()); connect(this, &BaseInstance::runningStatusChanged, m_core_mod_list.get(), &ModFolderModel::disableInteraction); } return m_core_mod_list; } -std::shared_ptr MinecraftInstance::nilModList() const +std::shared_ptr MinecraftInstance::nilModList() { if (!m_nil_mod_list) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); - m_nil_mod_list.reset(new ModFolderModel(nilModsDir(), shared_from_this(), is_indexed, false)); + m_nil_mod_list.reset(new ModFolderModel(nilModsDir(), this, is_indexed, false)); m_nil_mod_list->disableInteraction(isRunning()); connect(this, &BaseInstance::runningStatusChanged, m_nil_mod_list.get(), &ModFolderModel::disableInteraction); } return m_nil_mod_list; } -std::shared_ptr MinecraftInstance::resourcePackList() const +std::shared_ptr MinecraftInstance::resourcePackList() { if (!m_resource_pack_list) { - m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir(), shared_from_this())); + m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir(), this)); } return m_resource_pack_list; } -std::shared_ptr MinecraftInstance::texturePackList() const +std::shared_ptr MinecraftInstance::texturePackList() { if (!m_texture_pack_list) { - m_texture_pack_list.reset(new TexturePackFolderModel(texturePacksDir(), shared_from_this())); + m_texture_pack_list.reset(new TexturePackFolderModel(texturePacksDir(), this)); } return m_texture_pack_list; } -std::shared_ptr MinecraftInstance::shaderPackList() const +std::shared_ptr MinecraftInstance::shaderPackList() { if (!m_shader_pack_list) { - m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir(), shared_from_this())); + m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir(), this)); } return m_shader_pack_list; } -std::shared_ptr MinecraftInstance::worldList() const +std::shared_ptr MinecraftInstance::worldList() { if (!m_world_list) { - m_world_list.reset(new WorldList(worldDir(), shared_from_this())); + m_world_list.reset(new WorldList(worldDir(), this)); } return m_world_list; } -std::shared_ptr MinecraftInstance::gameOptionsModel() const +std::shared_ptr MinecraftInstance::gameOptionsModel() { if (!m_game_options) { diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index a75fa481..068b3008 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -115,14 +115,14 @@ public: std::shared_ptr getPackProfile() const; ////// Mod Lists ////// - std::shared_ptr loaderModList() const; - std::shared_ptr coreModList() const; - std::shared_ptr nilModList() const; - std::shared_ptr resourcePackList() const; - std::shared_ptr texturePackList() const; - std::shared_ptr shaderPackList() const; - std::shared_ptr worldList() const; - std::shared_ptr gameOptionsModel() const; + std::shared_ptr loaderModList(); + std::shared_ptr coreModList(); + std::shared_ptr nilModList(); + std::shared_ptr resourcePackList(); + std::shared_ptr texturePackList(); + std::shared_ptr shaderPackList(); + std::shared_ptr worldList(); + std::shared_ptr gameOptionsModel(); ////// Launch stuff ////// Task::Ptr createUpdateTask(Net::Mode mode) override; diff --git a/launcher/minecraft/WorldList.cpp b/launcher/minecraft/WorldList.cpp index df6b4ecc..0feee299 100644 --- a/launcher/minecraft/WorldList.cpp +++ b/launcher/minecraft/WorldList.cpp @@ -45,7 +45,7 @@ #include #include -WorldList::WorldList(const QString &dir, std::shared_ptr instance) +WorldList::WorldList(const QString &dir, BaseInstance* instance) : QAbstractListModel(), m_instance(instance), m_dir(dir) { FS::ensureFolderPathExists(m_dir.absolutePath()); diff --git a/launcher/minecraft/WorldList.h b/launcher/minecraft/WorldList.h index 10fb4e3c..96b64193 100644 --- a/launcher/minecraft/WorldList.h +++ b/launcher/minecraft/WorldList.h @@ -50,7 +50,7 @@ public: IconFileRole }; - WorldList(const QString &dir, std::shared_ptr instance); + WorldList(const QString &dir, BaseInstance* instance); virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; @@ -128,7 +128,7 @@ signals: void changed(); protected: - std::shared_ptr m_instance; + BaseInstance* m_instance; QFileSystemWatcher *m_watcher; bool is_watching; QDir m_dir; diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 6ae25d33..5e3b31e0 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -54,7 +54,7 @@ #include "minecraft/mod/tasks/ModFolderLoadTask.h" #include "modplatform/ModIndex.h" -ModFolderModel::ModFolderModel(const QString& dir, std::shared_ptr instance, bool is_indexed, bool create_dir) +ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool is_indexed, bool create_dir) : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed) { m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER }; diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index 46f5087f..d337fe29 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -75,7 +75,7 @@ public: Enable, Toggle }; - ModFolderModel(const QString &dir, std::shared_ptr instance, bool is_indexed = false, bool create_dir = true); + ModFolderModel(const QString &dir, BaseInstance* instance, bool is_indexed = false, bool create_dir = true); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index e1973468..d2d875e4 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -16,7 +16,7 @@ #include "tasks/Task.h" -ResourceFolderModel::ResourceFolderModel(QDir dir, std::shared_ptr instance, QObject* parent, bool create_dir) +ResourceFolderModel::ResourceFolderModel(QDir dir, BaseInstance* instance, QObject* parent, bool create_dir) : QAbstractListModel(parent), m_dir(dir), m_instance(instance), m_watcher(this) { if (create_dir) { diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index fdf5f331..0a35e1bc 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -26,7 +26,7 @@ class QSortFilterProxyModel; class ResourceFolderModel : public QAbstractListModel { Q_OBJECT public: - ResourceFolderModel(QDir, std::shared_ptr, QObject* parent = nullptr, bool create_dir = true); + ResourceFolderModel(QDir, BaseInstance* instance, QObject* parent = nullptr, bool create_dir = true); ~ResourceFolderModel() override; /** Starts watching the paths for changes. @@ -191,7 +191,7 @@ class ResourceFolderModel : public QAbstractListModel { bool m_can_interact = true; QDir m_dir; - std::shared_ptr m_instance; + BaseInstance* m_instance; QFileSystemWatcher m_watcher; bool m_is_watching = false; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 6eba4e2e..c12d1f23 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -45,7 +45,7 @@ #include "minecraft/mod/tasks/BasicFolderLoadTask.h" #include "minecraft/mod/tasks/LocalResourcePackParseTask.h" -ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, std::shared_ptr instance) +ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) { m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE }; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.h b/launcher/minecraft/mod/ResourcePackFolderModel.h index 66d5a074..db4b14fb 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.h +++ b/launcher/minecraft/mod/ResourcePackFolderModel.h @@ -17,7 +17,7 @@ public: NUM_COLUMNS }; - explicit ResourcePackFolderModel(const QString &dir, std::shared_ptr instance); + explicit ResourcePackFolderModel(const QString &dir, BaseInstance* instance); [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; diff --git a/launcher/minecraft/mod/ShaderPackFolderModel.h b/launcher/minecraft/mod/ShaderPackFolderModel.h index 6f3f2811..dc5acf80 100644 --- a/launcher/minecraft/mod/ShaderPackFolderModel.h +++ b/launcher/minecraft/mod/ShaderPackFolderModel.h @@ -6,7 +6,7 @@ class ShaderPackFolderModel : public ResourceFolderModel { Q_OBJECT public: - explicit ShaderPackFolderModel(const QString& dir, std::shared_ptr instance) + explicit ShaderPackFolderModel(const QString& dir, BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) {} }; diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index 1e218537..c6609ed1 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -39,7 +39,7 @@ #include "minecraft/mod/tasks/BasicFolderLoadTask.h" #include "minecraft/mod/tasks/LocalTexturePackParseTask.h" -TexturePackFolderModel::TexturePackFolderModel(const QString& dir, std::shared_ptr instance) +TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) {} diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h index 246997bd..425a71e4 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.h +++ b/launcher/minecraft/mod/TexturePackFolderModel.h @@ -43,7 +43,7 @@ class TexturePackFolderModel : public ResourceFolderModel Q_OBJECT public: - explicit TexturePackFolderModel(const QString &dir, std::shared_ptr instance); + explicit TexturePackFolderModel(const QString &dir, BaseInstance* instance); [[nodiscard]] Task* createUpdateTask() override; [[nodiscard]] Task* createParseTask(Resource&) override; }; diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index 64ed7673..aafaf220 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -99,7 +99,7 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString // NOTE: m_buttons must be initialized before PageContainer, because it indirectly accesses m_buttons through setSuggestedPack! Do not move this below. m_buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - m_container = new PageContainer(this); + m_container = new PageContainer(this, {}, this); m_container->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding); m_container->layout()->setContentsMargins(0, 0, 0, 0); ui->verticalLayout->insertWidget(2, m_container); diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index edb7d063..d2a8d33e 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -89,7 +89,7 @@ void ResourceDownloadDialog::reject() // won't work with subclasses if we put it in this ctor. void ResourceDownloadDialog::initializeContainer() { - m_container = new PageContainer(this); + m_container = new PageContainer(this, {}, this); m_container->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding); m_container->layout()->setContentsMargins(0, 0, 0, 0); m_vertical_layout.addWidget(m_container); diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index 0a06a351..b9b17b42 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -87,7 +87,9 @@ PageContainer::PageContainer(BasePageProvider *pageProvider, QString defaultId, auto pages = pageProvider->getPages(); for (auto page : pages) { - page->stackIndex = m_pageStack->addWidget(dynamic_cast(page)); + auto widget = dynamic_cast(page); + widget->setParent(this); + page->stackIndex = m_pageStack->addWidget(widget); page->listIndex = counter; page->setParentContainer(this); counter++; diff --git a/tests/ResourceFolderModel_test.cpp b/tests/ResourceFolderModel_test.cpp index 054d81c4..962d89f1 100644 --- a/tests/ResourceFolderModel_test.cpp +++ b/tests/ResourceFolderModel_test.cpp @@ -90,9 +90,7 @@ slots: QEventLoop loop; - InstancePtr instance; - - ModFolderModel m(tempDir.path(), instance, true); + ModFolderModel m(tempDir.path(), nullptr, true); connect(&m, &ModFolderModel::updateFinished, &loop, &QEventLoop::quit); @@ -116,8 +114,7 @@ slots: QString folder = source + '/'; QTemporaryDir tempDir; QEventLoop loop; - InstancePtr instance; - ModFolderModel m(tempDir.path(), instance, true); + ModFolderModel m(tempDir.path(), nullptr, true); connect(&m, &ModFolderModel::updateFinished, &loop, &QEventLoop::quit); @@ -140,8 +137,7 @@ slots: void test_addFromWatch() { QString source = QFINDTESTDATA("testdata/ResourceFolderModel"); - InstancePtr instance; - ModFolderModel model(source, instance); + ModFolderModel model(source, nullptr); QCOMPARE(model.size(), 0); @@ -161,9 +157,7 @@ slots: QString file_mod = QFINDTESTDATA("testdata/ResourceFolderModel/supercoolmod.jar"); QTemporaryDir tmp; - InstancePtr instance; - - ResourceFolderModel model(QDir(tmp.path()), instance); + ResourceFolderModel model(QDir(tmp.path()), nullptr); QCOMPARE(model.size(), 0); @@ -214,8 +208,7 @@ slots: QString file_mod = QFINDTESTDATA("testdata/ResourceFolderModel/supercoolmod.jar"); QTemporaryDir tmp; - InstancePtr instance; - ResourceFolderModel model(tmp.path(), instance); + ResourceFolderModel model(tmp.path(), nullptr); QCOMPARE(model.size(), 0); -- cgit From 86974b046ee0b232b07e3a28cbc1e954d88dd40f Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 28 May 2023 11:48:09 +0100 Subject: Clarify comment Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 8db89bbd..98fbc218 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -129,7 +129,7 @@ void ModrinthPackExportTask::collectHashes() const Mod* mod = *modIter; if (mod->metadata() != nullptr) { QUrl& url = mod->metadata()->url; - // most likely some of these may be from curseforge + // ensure the url is permitted on modrinth.com if (!url.isEmpty() && BuildConfig.MODRINTH_MRPACK_HOSTS.contains(url.host())) { qDebug() << "Resolving" << relative << "from index"; -- cgit From 0357921284f68c7948104fe95d23209757afde09 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 28 May 2023 04:37:09 -0700 Subject: cleanup: move qstyle getInstance decl inline Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/pages/instance/ManagedPackPage.cpp | 54 +++++++++++++------------- 1 file changed, 28 insertions(+), 26 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index ac34a5f4..a708377c 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -30,8 +30,6 @@ class NoBigComboBoxStyle : public QProxyStyle { Q_OBJECT public: - NoBigComboBoxStyle(QStyle* style) : QProxyStyle(style) {} - // clang-format off int styleHint(QStyle::StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override { @@ -42,36 +40,40 @@ class NoBigComboBoxStyle : public QProxyStyle { } // clang-format on - static NoBigComboBoxStyle* GetInstance(QStyle* style); + /** + * Something about QProxyStyle and QStyle objects means they can't be free'd just + * because all the widgets using them are gone. + * They seems to be tied to the QApplicaiton lifecycle. + * So make singletons tied to the lifetime of the application to clean them up and ensure they aren't + * being remade over and over again, thus leaking memory. + */ + public: + static NoBigComboBoxStyle* getInstance(QStyle* style) + { + std::lock_guard lock(s_singleton_instances_mutex_); + auto inst_iter = s_singleton_instances_.constFind(style); + NoBigComboBoxStyle* inst = nullptr; + if (inst_iter == s_singleton_instances_.constEnd() || *inst_iter == nullptr) { + inst = new NoBigComboBoxStyle(style); + inst->setParent(APPLICATION); + s_singleton_instances_.insert(style, inst); + qDebug() << "QProxyStyle NoBigComboBox created for" << style->objectName() << style; + } else { + inst = *inst_iter; + } + return inst; + } private: - static QMap s_singleton_instances_; + NoBigComboBoxStyle(QStyle* style) : QProxyStyle(style) {} + + static QHash s_singleton_instances_; static std::mutex s_singleton_instances_mutex_; }; -QMap NoBigComboBoxStyle::s_singleton_instances_ = {}; +QHash NoBigComboBoxStyle::s_singleton_instances_ = {}; std::mutex NoBigComboBoxStyle::s_singleton_instances_mutex_; -/** - * QProxyStyle and QStyle objects object to being freed even if all the widgets using them are gone - * so make singlestons tied to the lifetime of the application to clean them up and ensure they arn't - * being remade over and over agian leaking memory. - * */ -NoBigComboBoxStyle* NoBigComboBoxStyle::GetInstance(QStyle* style) -{ - std::lock_guard lock(s_singleton_instances_mutex_); - auto inst_iter = s_singleton_instances_.constFind(style); - NoBigComboBoxStyle* inst = nullptr; - if(inst_iter == s_singleton_instances_.constEnd() || *inst_iter == nullptr) { - inst = new NoBigComboBoxStyle(style); - inst->setParent(APPLICATION); - s_singleton_instances_.insert(style, inst); - qDebug() << "QProxyStyle NoBigComboBox created for" << style->objectName() << style; - } else { - inst = *inst_iter; - } - return inst; -} ManagedPackPage* ManagedPackPage::createPage(BaseInstance* inst, QString type, QWidget* parent) { @@ -93,7 +95,7 @@ ManagedPackPage::ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_wi // NOTE: GTK2 themes crash with the proxy style. // This seems like an upstream bug, so there's not much else that can be done. if (!QStyleFactory::keys().contains("gtk2")){ - auto comboStyle = NoBigComboBoxStyle::GetInstance(ui->versionsComboBox->style()); + auto comboStyle = NoBigComboBoxStyle::getInstance(ui->versionsComboBox->style()); ui->versionsComboBox->setStyle(comboStyle); } -- cgit From 7af116fb006e2eb62429740bd0abbe14f50ff244 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 28 May 2023 05:06:28 -0700 Subject: refactor: function scope statics Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/pages/instance/ManagedPackPage.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index a708377c..d0701a7a 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -50,6 +50,9 @@ class NoBigComboBoxStyle : public QProxyStyle { public: static NoBigComboBoxStyle* getInstance(QStyle* style) { + static QHash s_singleton_instances_ = {}; + static std::mutex s_singleton_instances_mutex_; + std::lock_guard lock(s_singleton_instances_mutex_); auto inst_iter = s_singleton_instances_.constFind(style); NoBigComboBoxStyle* inst = nullptr; @@ -67,14 +70,8 @@ class NoBigComboBoxStyle : public QProxyStyle { private: NoBigComboBoxStyle(QStyle* style) : QProxyStyle(style) {} - static QHash s_singleton_instances_; - static std::mutex s_singleton_instances_mutex_; }; -QHash NoBigComboBoxStyle::s_singleton_instances_ = {}; -std::mutex NoBigComboBoxStyle::s_singleton_instances_mutex_; - - ManagedPackPage* ManagedPackPage::createPage(BaseInstance* inst, QString type, QWidget* parent) { if (type == "modrinth") -- cgit From bf0a577fb9d063d90d0003227fce08f32fa09dd1 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 28 May 2023 16:57:35 +0300 Subject: Fixed repaint issue Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/ResourcePage.cpp | 10 ++++++---- launcher/ui/pages/modplatform/ResourcePage.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 4ebdea56..1edd4f81 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -312,9 +312,11 @@ void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatfo m_parent_dialog->addResource(pack, version); } -void ResourcePage::removeResourceFromDialog(const QString& pack_name) +void ResourcePage::removeResourceFromDialog(ModPlatform::IndexedPack& pack) { - m_parent_dialog->removeResource(pack_name); + m_parent_dialog->removeResource(pack.name); + for (auto& ver : pack.versions) + ver.is_currently_selected = false; } void ResourcePage::addResourceToPage(ModPlatform::IndexedPack& pack, @@ -340,7 +342,7 @@ void ResourcePage::onResourceSelected() auto& version = current_pack.versions[m_selected_version_index]; if (version.is_currently_selected) - removeResourceFromDialog(current_pack.name); + removeResourceFromDialog(current_pack); else addResourceToDialog(current_pack, version); @@ -351,7 +353,7 @@ void ResourcePage::onResourceSelected() updateSelectionButton(); /* Force redraw on the resource list when the selection changes */ - m_ui->packView->adjustSize(); + m_ui->packView->repaint(); } void ResourcePage::openUrl(const QUrl& url) diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index df68e6fd..41b0d0e4 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -76,7 +76,7 @@ class ResourcePage : public QWidget, public BasePage { virtual void updateVersionList(); void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); - void removeResourceFromDialog(const QString& pack_name); + void removeResourceFromDialog(ModPlatform::IndexedPack& pack); virtual void removeResourceFromPage(const QString& name); virtual void addResourceToPage(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, const std::shared_ptr); -- cgit From bdff8591aa945bd193f0fdae613f14dea6fb4809 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 28 May 2023 17:54:46 +0300 Subject: Removed extra loop Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/ResourcePage.cpp | 8 +++----- launcher/ui/pages/modplatform/ResourcePage.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index c8b3bb61..736034ad 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -314,11 +314,9 @@ void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack::Ptr pack, ModPl m_parent_dialog->addResource(pack, version); } -void ResourcePage::removeResourceFromDialog(ModPlatform::IndexedPack::Ptr pack) +void ResourcePage::removeResourceFromDialog(const QString& pack_name) { - m_parent_dialog->removeResource(pack->name); - for (auto& ver : pack->versions) - ver.is_currently_selected = false; + m_parent_dialog->removeResource(pack_name); } void ResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, @@ -344,7 +342,7 @@ void ResourcePage::onResourceSelected() auto& version = current_pack->versions[m_selected_version_index]; if (version.is_currently_selected) - removeResourceFromDialog(current_pack); + removeResourceFromDialog(current_pack->name); else addResourceToDialog(current_pack, version); diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index cc7aa707..b4a87f57 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -76,7 +76,7 @@ class ResourcePage : public QWidget, public BasePage { virtual void updateVersionList(); void addResourceToDialog(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&); - void removeResourceFromDialog(ModPlatform::IndexedPack::Ptr pack); + void removeResourceFromDialog(const QString& pack_name); virtual void removeResourceFromPage(const QString& name); virtual void addResourceToPage(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&, const std::shared_ptr); -- cgit From b4dff181f7dd222086c9405ab49347633dcb7ff8 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 28 May 2023 18:22:55 +0300 Subject: Fixed Ptr logic Signed-off-by: Trial97 --- .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 18 ++++++++++-------- launcher/minecraft/mod/tasks/GetModDependenciesTask.h | 4 ++-- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 948837d4..bd80a661 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -65,8 +65,8 @@ GetModDependenciesTask::GetModDependenciesTask(QObject* parent, void GetModDependenciesTask::prepare() { for (auto sel : m_selected) { - for (auto dep : getDependenciesForVersion(sel->version, sel->pack.provider)) { - addTask(prepareDependencyTask(dep, sel->pack.provider, 20)); + for (auto dep : getDependenciesForVersion(sel->version, sel->pack->provider)) { + addTask(prepareDependencyTask(dep, sel->pack->provider, 20)); } } } @@ -82,7 +82,7 @@ QList GetModDependenciesTask::getDependenciesForVersion dep == c_dependencies.end()) { // check the current dependency list if (auto dep = std::find_if(m_selected.begin(), m_selected.end(), [&ver_dep, providerName](std::shared_ptr i) { - return i->pack.addonId == ver_dep.addonId && i->pack.provider == providerName; + return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName; }); dep == m_selected.end()) { // check the selected versions if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), @@ -92,7 +92,7 @@ QList GetModDependenciesTask::getDependenciesForVersion dep == m_mods.end()) { // check the existing mods if (auto dep = std::find_if(m_pack_dependencies.begin(), m_pack_dependencies.end(), [&ver_dep, providerName](std::shared_ptr i) { - return i->pack.addonId == ver_dep.addonId && i->pack.provider == providerName; + return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName; }); dep == m_pack_dependencies.end()) { // check loaded dependencies c_dependencies.append(ver_dep); @@ -111,7 +111,9 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen { auto pDep = std::make_shared(); pDep->dependency = dep; - pDep->pack = { dep.addonId, providerName }; + pDep->pack = std::make_shared(); + pDep->pack->addonId = dep.addonId; + pDep->pack->provider = providerName; m_pack_dependencies.append(pDep); auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider; @@ -131,7 +133,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen try { auto obj = provider.name == ModPlatform::ResourceProvider::FLAME ? Json::requireObject(Json::requireObject(doc), "data") : Json::requireObject(doc); - provider.mod->loadIndexedPack(pDep->pack, obj); + provider.mod->loadIndexedPack(*pDep->pack, obj); } catch (const JSONValidationError& e) { qDebug() << doc; qWarning() << "Error while reading mod info: " << e.cause(); @@ -157,8 +159,8 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen return; } pDep->version.is_currently_selected = true; - pDep->pack.versions = { pDep->version }; - pDep->pack.versionsLoaded = true; + pDep->pack->versions = { pDep->version }; + pDep->pack->versionsLoaded = true; } catch (const JSONValidationError& e) { qDebug() << doc; diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index aca3c004..3824e781 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -40,10 +40,10 @@ class GetModDependenciesTask : public SequentialTask { struct PackDependency { ModPlatform::Dependency dependency; - ModPlatform::IndexedPack pack; + ModPlatform::IndexedPack::Ptr pack; ModPlatform::IndexedVersion version; PackDependency(){}; - PackDependency(const ModPlatform::IndexedPack& p, const ModPlatform::IndexedVersion& v) + PackDependency(const ModPlatform::IndexedPack::Ptr p, const ModPlatform::IndexedVersion& v) { pack = p; version = v; diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 6bb9b78a..495ee8ed 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -179,7 +179,7 @@ void ResourceDownloadDialog::confirm() }); for (auto& task : selected) { confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath(), - ProviderCaps.name(task->getProvider()), getReqiredBy(selected, task->getPack().addonId) }); + ProviderCaps.name(task->getProvider()), getReqiredBy(selected, task->getPack()->addonId) }); } if (confirm_dialog->exec()) { -- cgit From b9503ff15f355f0ddc2f2bdb841877766d5fe99d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 28 May 2023 18:27:02 +0300 Subject: Added Q_DECLARE_METATYPE(ModPlatform::IndexedPack::Ptr) Signed-off-by: Trial97 --- launcher/modplatform/ModIndex.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index dcc3484d..82da2ab2 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* 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 . -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * 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 . + */ #pragma once @@ -115,12 +115,12 @@ struct IndexedPack { if (!versionsLoaded) return false; - return std::any_of(versions.constBegin(), versions.constEnd(), - [](auto const& v) { return v.is_currently_selected; }); + return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); } }; } // namespace ModPlatform Q_DECLARE_METATYPE(ModPlatform::IndexedPack) +Q_DECLARE_METATYPE(ModPlatform::IndexedPack::Ptr) Q_DECLARE_METATYPE(ModPlatform::ResourceProvider) -- cgit From 10436ed70cc967da8d1d9ee5bca497ec8f70a66f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 28 May 2023 19:15:41 +0300 Subject: Fixed code quality Signed-off-by: Trial97 --- launcher/modplatform/flame/FlameCheckUpdate.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index ca7262c2..e09aeb3d 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -130,8 +130,7 @@ void FlameCheckUpdate::executeTask() setStatus(tr("Getting API response from CurseForge for '%1'...").arg(mod->name())); setProgress(i++, m_mods.size()); - ModPlatform::IndexedPack pack{ mod->metadata()->project_id.toString() }; - auto latest_ver = api.getLatestVersion({ pack, m_game_versions, m_loaders }); + auto latest_ver = api.getLatestVersion({ { mod->metadata()->project_id.toString() }, m_game_versions, m_loaders }); // Check if we were aborted while getting the latest version if (m_was_aborted) { -- cgit From 4eb9083ddc3c57f45d252ceae18d3e9dbf4ee4a3 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 28 May 2023 13:00:08 -0700 Subject: refactor: column names as class property, use string names in setting Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/ModFolderModel.cpp | 9 +++------ launcher/minecraft/mod/ResourceFolderModel.cpp | 13 ++++++------- launcher/minecraft/mod/ResourceFolderModel.h | 3 +++ launcher/minecraft/mod/ResourcePackFolderModel.cpp | 8 +++----- launcher/minecraft/mod/TexturePackFolderModel.cpp | 7 +++---- 5 files changed, 18 insertions(+), 22 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 02e77b30..b49aac18 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -57,6 +57,8 @@ ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool is_indexed, bool create_dir) : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed) { + m_column_names = QStringList({ "Enable", "Image", "Name", "Version", "Last Modified", "Provider" }); + m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Version"), tr("Last Modified"), tr("Provider") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME , SortType::VERSION, SortType::DATE, SortType::PROVIDER}; m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents}; } @@ -145,17 +147,12 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in switch (section) { case ActiveColumn: - return tr("Enable"); case NameColumn: - return tr("Name"); case VersionColumn: - return tr("Version"); case DateColumn: - return tr("Last changed"); case ProviderColumn: - return tr("Provider"); case ImageColumn: - return tr("Image"); + return columnNames().at(section); default: return QVariant(); } diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 838fca53..2997a43d 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -475,11 +475,9 @@ QVariant ResourceFolderModel::headerData(int section, Qt::Orientation orientatio case Qt::DisplayRole: switch (section) { case ACTIVE_COLUMN: - return tr("Enable"); case NAME_COLUMN: - return tr("Name"); case DATE_COLUMN: - return tr("Last modified"); + return columnNames().at(section); default: return {}; } @@ -509,7 +507,7 @@ void ResourceFolderModel::setupHeaderAction(QAction* act, int column) { Q_ASSERT(act); - act->setText(headerData(column, Qt::Orientation::Horizontal).toString()); + act->setText(columnNames().at(column)); } void ResourceFolderModel::saveHiddenColumn(int column, bool hidden) @@ -518,12 +516,13 @@ void ResourceFolderModel::saveHiddenColumn(int column, bool hidden) auto setting = (APPLICATION->settings()->contains(setting_name)) ? APPLICATION->settings()->getSetting(setting_name) : APPLICATION->settings()->registerSetting(setting_name); - auto hiddenColumns = QVariantUtils::toList(setting->get()); - auto index = hiddenColumns.indexOf(column); + auto hiddenColumns = QVariantUtils::toList(setting->get()); + auto name = columnNames(false).at(column); + auto index = hiddenColumns.indexOf(name); if (index >= 0 && !hidden) { hiddenColumns.removeAt(index); } else if ( index < 0 && hidden) { - hiddenColumns.append(column); + hiddenColumns.append(name); } setting->set(QVariantUtils::fromList(hiddenColumns)); } diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index e1dc685b..138815cf 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -97,6 +97,7 @@ class ResourceFolderModel : public QAbstractListModel { /* Basic columns */ enum Columns { ACTIVE_COLUMN = 0, NAME_COLUMN, DATE_COLUMN, NUM_COLUMNS }; + QStringList columnNames(bool translated = true) const { return translated ? m_column_names_translated : m_column_names; }; [[nodiscard]] int rowCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : static_cast(size()); } [[nodiscard]] int columnCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : NUM_COLUMNS; }; @@ -198,6 +199,8 @@ class ResourceFolderModel : public QAbstractListModel { // Represents the relationship between a column's index (represented by the list index), and it's sorting key. // As such, the order in with they appear is very important! QList m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE }; + QStringList m_column_names = {"Enable", "Name", "Last Modified"}; + QStringList m_column_names_translated = {tr("Enable"), tr("Name"), tr("Last Modified")}; QList m_column_resize_modes = { QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents }; bool m_can_interact = true; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 8a7b1049..989554de 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -50,6 +50,8 @@ ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) { + m_column_names = QStringList({ "Enable", "Image", "Name", "Pack Format", "Last Modified" }); + m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE}; m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents}; @@ -132,15 +134,11 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient case Qt::DisplayRole: switch (section) { case ActiveColumn: - return tr("Enable"); case NameColumn: - return tr("Name"); case PackFormatColumn: - return tr("Pack Format"); case DateColumn: - return tr("Last changed"); case ImageColumn: - return tr("Image"); + return columnNames().at(section); default: return {}; } diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index 76145b3b..898d128f 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -45,6 +45,8 @@ TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) { + m_column_names = QStringList({ "Enable", "Image", "Name", "Last Modified" }); + m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Last Modified") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::DATE }; m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents}; @@ -118,13 +120,10 @@ QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orienta case Qt::DisplayRole: switch (section) { case ActiveColumn: - return tr("Enable"); case NameColumn: - return tr("Name"); case DateColumn: - return tr("Last modified"); case ImageColumn: - return tr("Image"); + return columnNames().at(section); default: return {}; } -- cgit From 5fe9e30f394a8025cdb6aa11b4cc11b9a2bb6a64 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 28 May 2023 14:53:15 -0700 Subject: fix: use instance settings, make image column user resizeable, fix memory leak Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/ModFolderModel.cpp | 2 +- launcher/minecraft/mod/ResourceFolderModel.cpp | 29 ++++++++++++---------- launcher/minecraft/mod/ResourceFolderModel.h | 2 +- launcher/minecraft/mod/ResourcePackFolderModel.cpp | 2 +- launcher/minecraft/mod/TexturePackFolderModel.cpp | 2 +- .../ui/pages/instance/ExternalResourcesPage.cpp | 3 ++- 6 files changed, 22 insertions(+), 18 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index b49aac18..e745f954 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -60,7 +60,7 @@ ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool m_column_names = QStringList({ "Enable", "Image", "Name", "Version", "Last Modified", "Provider" }); m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Version"), tr("Last Modified"), tr("Provider") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME , SortType::VERSION, SortType::DATE, SortType::PROVIDER}; - m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents}; + m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents}; } QVariant ModFolderModel::data(const QModelIndex &index, int role) const diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 2997a43d..b60f8182 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -513,10 +513,10 @@ void ResourceFolderModel::setupHeaderAction(QAction* act, int column) void ResourceFolderModel::saveHiddenColumn(int column, bool hidden) { auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id()); - auto setting = (APPLICATION->settings()->contains(setting_name)) ? - APPLICATION->settings()->getSetting(setting_name) : APPLICATION->settings()->registerSetting(setting_name); + auto setting = (m_instance->settings()->contains(setting_name)) ? + m_instance->settings()->getSetting(setting_name) : m_instance->settings()->registerSetting(setting_name); - auto hiddenColumns = QVariantUtils::toList(setting->get()); + auto hiddenColumns = setting->get().toStringList(); auto name = columnNames(false).at(column); auto index = hiddenColumns.indexOf(name); if (index >= 0 && !hidden) { @@ -524,30 +524,33 @@ void ResourceFolderModel::saveHiddenColumn(int column, bool hidden) } else if ( index < 0 && hidden) { hiddenColumns.append(name); } - setting->set(QVariantUtils::fromList(hiddenColumns)); + setting->set(hiddenColumns); } void ResourceFolderModel::loadHiddenColumns(QTreeView *tree) { auto const setting_name = QString("UI/%1_Page/HiddenColumns").arg(id()); - auto setting = (APPLICATION->settings()->contains(setting_name)) ? - APPLICATION->settings()->getSetting(setting_name) : APPLICATION->settings()->registerSetting(setting_name); - - auto hiddenColumns = QVariantUtils::toList(setting->get().toList()); - for (auto col : hiddenColumns) { - tree->setColumnHidden(col, true); + auto setting = (m_instance->settings()->contains(setting_name)) ? + m_instance->settings()->getSetting(setting_name) : m_instance->settings()->registerSetting(setting_name); + + auto hiddenColumns = setting->get().toStringList(); + auto col_names = columnNames(false); + for (auto col_name : hiddenColumns) { + auto index = col_names.indexOf(col_name); + if (index >= 0) + tree->setColumnHidden(index, true); } } -std::unique_ptr ResourceFolderModel::createHeaderContextMenu(QWidget* parent, QTreeView* tree) +QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree) { - auto menu = std::make_unique(parent); + auto menu = new QMenu(tree); menu->addSeparator()->setText(tr("Show / Hide Columns")); for (int col = 0; col < columnCount(); ++col) { - auto act = new QAction(); + auto act = new QAction(menu); setupHeaderAction(act, col); act->setCheckable(true); diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 138815cf..3c9c4d89 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -119,7 +119,7 @@ class ResourceFolderModel : public QAbstractListModel { void setupHeaderAction(QAction* act, int column); void saveHiddenColumn(int column, bool hidden); void loadHiddenColumns(QTreeView* tree); - std::unique_ptr createHeaderContextMenu(QWidget* parent, QTreeView* tree); + QMenu* createHeaderContextMenu(QTreeView* tree); /** This creates a proxy model to filter / sort the model for a UI. * diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 989554de..14a28b47 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -53,7 +53,7 @@ ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstanc m_column_names = QStringList({ "Enable", "Image", "Name", "Pack Format", "Last Modified" }); m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE}; - m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents}; + m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents}; } diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index 898d128f..531a7023 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -48,7 +48,7 @@ TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance* m_column_names = QStringList({ "Enable", "Image", "Name", "Last Modified" }); m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Last Modified") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::DATE }; - m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents}; + m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents}; } diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index bee11d9a..2f824ffb 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -76,8 +76,9 @@ void ExternalResourcesPage::ShowContextMenu(const QPoint& pos) void ExternalResourcesPage::ShowHeaderContextMenu(const QPoint& pos) { - auto menu = m_model->createHeaderContextMenu(this, ui->treeView); + auto menu = m_model->createHeaderContextMenu(ui->treeView); menu->exec(ui->treeView->mapToGlobal(pos)); + menu->deleteLater(); } void ExternalResourcesPage::openedImpl() -- cgit From 6c082403c4e910248a41fd84a1a48522484be2cf Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 31 May 2023 20:23:23 +0300 Subject: Fixed comments Signed-off-by: Trial97 --- launcher/Application.cpp | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) (limited to 'launcher') diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 430a96af..026d1636 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -376,13 +376,10 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // init the logger { - static const QString logBase = "logs/"+BuildConfig.LAUNCHER_NAME + "-%0.log"; - QDir logDir = QDir(dataPath); - if(!logDir.exists("logs")) { - logDir.mkpath("logs"); //this can fail, but there is no need to throw an error *yet*, since it also triggers the error message below! - } - auto moveFile = [](const QString &oldName, const QString &newName) - { + static const QString logBase = FS::PathCombine("logs", BuildConfig.LAUNCHER_NAME + "-%0.log"); + FS::ensureFolderPathExists( + "logs"); // this can fail, but there is no need to throw an error *yet*, since it also triggers the error message below! + auto moveFile = [](const QString& oldName, const QString& newName) { QFile::remove(newName); QFile::copy(oldName, newName); QFile::remove(oldName); @@ -394,19 +391,15 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) moveFile(logBase.arg(0), logBase.arg(1)); logFile = std::unique_ptr(new QFile(logBase.arg(0))); - if(!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) - { - showFatalErrorMessage( - "The launcher data folder is not writable!", - QString( - "The launcher couldn't create a log file - the data folder is not writable.\n" - "\n" - "Make sure you have write permissions to the logs folder.\n" - "(%1)\n" - "\n" - "The launcher cannot continue until you fix this problem." - ).arg(dataPath+"/logs") - ); + if (!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { + showFatalErrorMessage("The launcher data folder is not writable!", + QString("The launcher couldn't create a log file - the data folder is not writable.\n" + "\n" + "Make sure you have write permissions to the data folder.\n" + "(%1)\n" + "\n" + "The launcher cannot continue until you fix this problem.") + .arg(dataPath)); return; } qInstallMessageHandler(appDebugOutput); -- cgit From 3a6657596ba19a0310df38ed0c94f292c2de68c9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 1 Jun 2023 23:48:48 +0300 Subject: Added migration for old logs Signed-off-by: Trial97 --- launcher/Application.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 026d1636..e9a3cb89 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -376,9 +376,18 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // init the logger { - static const QString logBase = FS::PathCombine("logs", BuildConfig.LAUNCHER_NAME + "-%0.log"); - FS::ensureFolderPathExists( - "logs"); // this can fail, but there is no need to throw an error *yet*, since it also triggers the error message below! + static const QString baseLogFile = BuildConfig.LAUNCHER_NAME + "-%0.log"; + static const QString logBase = FS::PathCombine("logs", baseLogFile); + if (FS::ensureFolderPathExists("logs")) { // if this did not fail + for (auto i = 0; i <= 4; i++) { + auto oldName = baseLogFile.arg(i); + auto newName = logBase.arg(i); + if (QFile::exists(newName)) // in case there are already files in folder just to be safe add a suffix + newName += ".old"; + QFile::rename(oldName, newName); + } + } + auto moveFile = [](const QString& oldName, const QString& newName) { QFile::remove(newName); QFile::copy(oldName, newName); -- cgit From 17691ab5154ecadf661f1035cfc87b4e4c5e236f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 2 Jun 2023 01:22:25 +0300 Subject: Made use of moveFile function Signed-off-by: Trial97 --- launcher/Application.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'launcher') diff --git a/launcher/Application.cpp b/launcher/Application.cpp index e9a3cb89..724e6e44 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -378,26 +378,20 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) { static const QString baseLogFile = BuildConfig.LAUNCHER_NAME + "-%0.log"; static const QString logBase = FS::PathCombine("logs", baseLogFile); - if (FS::ensureFolderPathExists("logs")) { // if this did not fail - for (auto i = 0; i <= 4; i++) { - auto oldName = baseLogFile.arg(i); - auto newName = logBase.arg(i); - if (QFile::exists(newName)) // in case there are already files in folder just to be safe add a suffix - newName += ".old"; - QFile::rename(oldName, newName); - } - } - auto moveFile = [](const QString& oldName, const QString& newName) { QFile::remove(newName); QFile::copy(oldName, newName); QFile::remove(oldName); }; + if (FS::ensureFolderPathExists("logs")) { // if this did not fail + for (auto i = 0; i <= 4; i++) + if (auto oldName = baseLogFile.arg(i); + QFile::exists(oldName)) // do not pointlessly delete new files if the old ones are not there + moveFile(oldName, logBase.arg(i)); + } - moveFile(logBase.arg(3), logBase.arg(4)); - moveFile(logBase.arg(2), logBase.arg(3)); - moveFile(logBase.arg(1), logBase.arg(2)); - moveFile(logBase.arg(0), logBase.arg(1)); + for (auto i = 4; i > 0; i--) + moveFile(logBase.arg(i - 1), logBase.arg(i)); logFile = std::unique_ptr(new QFile(logBase.arg(0))); if (!logFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { -- cgit From 1840505a0f887ebfc2c719113873ea3345b133fb Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sat, 3 Jun 2023 00:04:06 +0300 Subject: Fix crash when selecting same mod from different providers (#1029) --- launcher/ResourceDownloadTask.cpp | 49 +++++++------ launcher/ResourceDownloadTask.h | 58 ++++++++------- launcher/modplatform/ModIndex.h | 35 +++++---- launcher/modplatform/flame/FlameCheckUpdate.cpp | 22 +++--- .../modplatform/modrinth/ModrinthCheckUpdate.cpp | 28 +++---- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 82 ++++++++++----------- launcher/ui/dialogs/ResourceDownloadDialog.h | 17 ++--- launcher/ui/pages/modplatform/ModPage.cpp | 27 ++++--- launcher/ui/pages/modplatform/ModPage.h | 15 ++-- launcher/ui/pages/modplatform/ResourceModel.cpp | 65 ++++++++++++++--- launcher/ui/pages/modplatform/ResourceModel.h | 12 +++ launcher/ui/pages/modplatform/ResourcePage.cpp | 85 +++++++++++++--------- launcher/ui/pages/modplatform/ResourcePage.h | 18 +++-- launcher/ui/pages/modplatform/ShaderPackPage.cpp | 16 ++-- launcher/ui/pages/modplatform/ShaderPackPage.h | 4 +- launcher/ui/widgets/PageContainer.cpp | 5 ++ launcher/ui/widgets/PageContainer.h | 1 + 17 files changed, 314 insertions(+), 225 deletions(-) (limited to 'launcher') diff --git a/launcher/ResourceDownloadTask.cpp b/launcher/ResourceDownloadTask.cpp index 61b918aa..06c03c77 100644 --- a/launcher/ResourceDownloadTask.cpp +++ b/launcher/ResourceDownloadTask.cpp @@ -1,21 +1,21 @@ // SPDX-License-Identifier: GPL-3.0-only -/* -* Prism Launcher - Minecraft Launcher -* Copyright (c) 2022-2023 flowln -* Copyright (C) 2022 Sefa Eyeoglu -* -* 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 . -*/ +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022-2023 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * 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 . + */ #include "ResourceDownloadTask.h" @@ -24,14 +24,15 @@ #include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ResourceFolderModel.h" -ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack pack, +ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion version, const std::shared_ptr packs, - bool is_indexed) - : m_pack(std::move(pack)), m_pack_version(std::move(version)), m_pack_model(packs) + bool is_indexed, + QString custom_target_folder) + : m_pack(std::move(pack)), m_pack_version(std::move(version)), m_pack_model(packs), m_custom_target_folder(custom_target_folder) { if (auto model = dynamic_cast(m_pack_model.get()); model && is_indexed) { - m_update_task.reset(new LocalModUpdateTask(model->indexDir(), m_pack, m_pack_version)); + m_update_task.reset(new LocalModUpdateTask(model->indexDir(), *m_pack, m_pack_version)); connect(m_update_task.get(), &LocalModUpdateTask::hasOldMod, this, &ResourceDownloadTask::hasOldResource); addTask(m_update_task); @@ -40,13 +41,13 @@ ResourceDownloadTask::ResourceDownloadTask(ModPlatform::IndexedPack pack, m_filesNetJob.reset(new NetJob(tr("Resource download"), APPLICATION->network())); m_filesNetJob->setStatus(tr("Downloading resource:\n%1").arg(m_pack_version.downloadUrl)); - QDir dir { m_pack_model->dir() }; + QDir dir{ m_pack_model->dir() }; { // FIXME: Make this more generic. May require adding additional info to IndexedVersion, // or adquiring a reference to the base instance. - if (!m_pack_version.custom_target_folder.isEmpty()) { + if (!m_custom_target_folder.isEmpty()) { dir.cdUp(); - dir.cd(m_pack_version.custom_target_folder); + dir.cd(m_custom_target_folder); } } diff --git a/launcher/ResourceDownloadTask.h b/launcher/ResourceDownloadTask.h index 73ad2d07..09147c8c 100644 --- a/launcher/ResourceDownloadTask.h +++ b/launcher/ResourceDownloadTask.h @@ -1,44 +1,51 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* Prism Launcher - Minecraft Launcher -* Copyright (c) 2022-2023 flowln -* Copyright (C) 2022 Sefa Eyeoglu -* -* 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 . -*/ + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022-2023 flowln + * Copyright (C) 2022 Sefa Eyeoglu + * + * 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 . + */ #pragma once #include "net/NetJob.h" #include "tasks/SequentialTask.h" -#include "modplatform/ModIndex.h" #include "minecraft/mod/tasks/LocalModUpdateTask.h" +#include "modplatform/ModIndex.h" class ResourceFolderModel; class ResourceDownloadTask : public SequentialTask { Q_OBJECT -public: - explicit ResourceDownloadTask(ModPlatform::IndexedPack pack, ModPlatform::IndexedVersion version, const std::shared_ptr packs, bool is_indexed = true); + public: + explicit ResourceDownloadTask(ModPlatform::IndexedPack::Ptr pack, + ModPlatform::IndexedVersion version, + const std::shared_ptr packs, + bool is_indexed = true, + QString custom_target_folder = {}); const QString& getFilename() const { return m_pack_version.fileName; } - const QString& getCustomPath() const { return m_pack_version.custom_target_folder; } + const QString& getCustomPath() const { return m_custom_target_folder; } const QVariant& getVersionID() const { return m_pack_version.fileId; } + const QString& getName() const { return m_pack->name; } + ModPlatform::IndexedPack::Ptr getPack() { return m_pack; } -private: - ModPlatform::IndexedPack m_pack; + private: + ModPlatform::IndexedPack::Ptr m_pack; ModPlatform::IndexedVersion m_pack_version; const std::shared_ptr m_pack_model; + QString m_custom_target_folder; NetJob::Ptr m_filesNetJob; LocalModUpdateTask::Ptr m_update_task; @@ -47,11 +54,8 @@ private: void downloadFailed(QString reason); void downloadSucceeded(); - std::tuple to_delete {"", ""}; + std::tuple to_delete{ "", "" }; -private slots: + private slots: void hasOldResource(QString name, QString filename); }; - - - diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 8d0223f9..82da2ab2 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -1,20 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* 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 . -*/ + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 flowln + * + * 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 . + */ #pragma once @@ -69,7 +69,6 @@ struct IndexedVersion { // For internal use, not provided by APIs bool is_currently_selected = false; - QString custom_target_folder; }; struct ExtraPackData { @@ -116,12 +115,12 @@ struct IndexedPack { if (!versionsLoaded) return false; - return std::any_of(versions.constBegin(), versions.constEnd(), - [](auto const& v) { return v.is_currently_selected; }); + return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); } }; } // namespace ModPlatform Q_DECLARE_METATYPE(ModPlatform::IndexedPack) +Q_DECLARE_METATYPE(ModPlatform::IndexedPack::Ptr) Q_DECLARE_METATYPE(ModPlatform::ResourceProvider) diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index 06a89502..e09aeb3d 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -3,6 +3,7 @@ #include "FlameModIndex.h" #include +#include #include "FileSystem.h" #include "Json.h" @@ -129,8 +130,7 @@ void FlameCheckUpdate::executeTask() setStatus(tr("Getting API response from CurseForge for '%1'...").arg(mod->name())); setProgress(i++, m_mods.size()); - ModPlatform::IndexedPack pack{ mod->metadata()->project_id.toString() }; - auto latest_ver = api.getLatestVersion({ pack, m_game_versions, m_loaders }); + auto latest_ver = api.getLatestVersion({ { mod->metadata()->project_id.toString() }, m_game_versions, m_loaders }); // Check if we were aborted while getting the latest version if (m_was_aborted) { @@ -156,15 +156,15 @@ void FlameCheckUpdate::executeTask() if (!latest_ver.hash.isEmpty() && (mod->metadata()->hash != latest_ver.hash || mod->status() == ModStatus::NotInstalled)) { // Fake pack with the necessary info to pass to the download task :) - ModPlatform::IndexedPack pack; - pack.name = mod->name(); - pack.slug = mod->metadata()->slug; - pack.addonId = mod->metadata()->project_id; - pack.websiteUrl = mod->homeurl(); + auto pack = std::make_shared(); + pack->name = mod->name(); + pack->slug = mod->metadata()->slug; + pack->addonId = mod->metadata()->project_id; + pack->websiteUrl = mod->homeurl(); for (auto& author : mod->authors()) - pack.authors.append({ author }); - pack.description = mod->description(); - pack.provider = ModPlatform::ResourceProvider::FLAME; + pack->authors.append({ author }); + pack->description = mod->description(); + pack->provider = ModPlatform::ResourceProvider::FLAME; auto old_version = mod->version(); if (old_version.isEmpty() && mod->status() != ModStatus::NotInstalled) { @@ -173,7 +173,7 @@ void FlameCheckUpdate::executeTask() } auto download_task = makeShared(pack, latest_ver, m_mods_folder); - m_updatable.emplace_back(pack.name, mod->metadata()->hash, old_version, latest_ver.version, + m_updatable.emplace_back(pack->name, mod->metadata()->hash, old_version, latest_ver.version, api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()), ModPlatform::ResourceProvider::FLAME, download_task); } diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index d1be7209..4fe91ce7 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -54,7 +54,7 @@ void ModrinthCheckUpdate::executeTask() if (mod->metadata()->hash_format != best_hash_type) { auto hash_task = Hashing::createModrinthHasher(mod->fileinfo().absoluteFilePath()); connect(hash_task.get(), &Task::succeeded, [&] { - QString hash (hash_task->getResult()); + QString hash(hash_task->getResult()); hashes.append(hash); mappings.insert(hash, mod); }); @@ -67,7 +67,7 @@ void ModrinthCheckUpdate::executeTask() } QEventLoop loop; - connect(&hashing_task, &Task::finished, [&loop]{ loop.quit(); }); + connect(&hashing_task, &Task::finished, [&loop] { loop.quit(); }); hashing_task.start(); loop.exec(); @@ -112,7 +112,8 @@ void ModrinthCheckUpdate::executeTask() // so we may want to filter it QString loader_filter; if (m_loaders.has_value()) { - static auto flags = { ResourceAPI::ModLoaderType::Forge, ResourceAPI::ModLoaderType::Fabric, ResourceAPI::ModLoaderType::Quilt }; + static auto flags = { ResourceAPI::ModLoaderType::Forge, ResourceAPI::ModLoaderType::Fabric, + ResourceAPI::ModLoaderType::Quilt }; for (auto flag : flags) { if (m_loaders.value().testFlag(flag)) { loader_filter = api.getModLoaderString(flag); @@ -122,7 +123,8 @@ void ModrinthCheckUpdate::executeTask() } // Currently, we rely on a couple heuristics to determine whether an update is actually available or not: - // - The file needs to be preferred: It is either the primary file, or the one found via (explicit) usage of the loader_filter + // - The file needs to be preferred: It is either the primary file, or the one found via (explicit) usage of the + // loader_filter // - The version reported by the JAR is different from the version reported by the indexed version (it's usually the case) // Such is the pain of having arbitrary files for a given version .-. @@ -149,19 +151,19 @@ void ModrinthCheckUpdate::executeTask() continue; // Fake pack with the necessary info to pass to the download task :) - ModPlatform::IndexedPack pack; - pack.name = mod->name(); - pack.slug = mod->metadata()->slug; - pack.addonId = mod->metadata()->project_id; - pack.websiteUrl = mod->homeurl(); + auto pack = std::make_shared(); + pack->name = mod->name(); + pack->slug = mod->metadata()->slug; + pack->addonId = mod->metadata()->project_id; + pack->websiteUrl = mod->homeurl(); for (auto& author : mod->authors()) - pack.authors.append({ author }); - pack.description = mod->description(); - pack.provider = ModPlatform::ResourceProvider::MODRINTH; + pack->authors.append({ author }); + pack->description = mod->description(); + pack->provider = ModPlatform::ResourceProvider::MODRINTH; auto download_task = makeShared(pack, project_ver, m_mods_folder); - m_updatable.emplace_back(pack.name, hash, mod->version(), project_ver.version_number, project_ver.changelog, + m_updatable.emplace_back(pack->name, hash, mod->version(), project_ver.version_number, project_ver.changelog, ModPlatform::ResourceProvider::MODRINTH, download_task); } } diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index d2a8d33e..61c48e75 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -20,14 +20,15 @@ #include "ResourceDownloadDialog.h" #include +#include #include "Application.h" #include "ResourceDownloadTask.h" #include "minecraft/mod/ModFolderModel.h" #include "minecraft/mod/ResourcePackFolderModel.h" -#include "minecraft/mod/TexturePackFolderModel.h" #include "minecraft/mod/ShaderPackFolderModel.h" +#include "minecraft/mod/TexturePackFolderModel.h" #include "ui/dialogs/ReviewMessageBox.h" @@ -41,7 +42,10 @@ namespace ResourceDownload { ResourceDownloadDialog::ResourceDownloadDialog(QWidget* parent, const std::shared_ptr base_model) - : QDialog(parent), m_base_model(base_model), m_buttons(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel), m_vertical_layout(this) + : QDialog(parent) + , m_base_model(base_model) + , m_buttons(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel) + , m_vertical_layout(this) { setObjectName(QStringLiteral("ResourceDownloadDialog")); @@ -102,7 +106,8 @@ void ResourceDownloadDialog::initializeContainer() void ResourceDownloadDialog::connectButtons() { auto OkButton = m_buttons.button(QDialogButtonBox::Ok); - OkButton->setToolTip(tr("Opens a new popup to review your selected %1 and confirm your selection. Shortcut: Ctrl+Return").arg(resourcesString())); + OkButton->setToolTip( + tr("Opens a new popup to review your selected %1 and confirm your selection. Shortcut: Ctrl+Return").arg(resourcesString())); connect(OkButton, &QPushButton::clicked, this, &ResourceDownloadDialog::confirm); auto CancelButton = m_buttons.button(QDialogButtonBox::Cancel); @@ -114,21 +119,24 @@ void ResourceDownloadDialog::connectButtons() void ResourceDownloadDialog::confirm() { - auto keys = m_selected.keys(); - keys.sort(Qt::CaseInsensitive); + auto selected = getTasks(); + std::sort(selected.begin(), selected.end(), [](const DownloadTaskPtr& a, const DownloadTaskPtr& b) { + return QString::compare(a->getName(), b->getName(), Qt::CaseInsensitive) < 0; + }); auto confirm_dialog = ReviewMessageBox::create(this, tr("Confirm %1 to download").arg(resourcesString())); confirm_dialog->retranslateUi(resourcesString()); - for (auto& task : keys) { - auto selected = m_selected.constFind(task).value(); - confirm_dialog->appendResource({ task, selected->getFilename(), selected->getCustomPath() }); + for (auto& task : selected) { + confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath() }); } if (confirm_dialog->exec()) { auto deselected = confirm_dialog->deselectedResources(); - for (auto name : deselected) { - m_selected.remove(name); + for (auto page : m_container->getPages()) { + auto res = static_cast(page); + for (auto name : deselected) + res->removeResourceFromPage(name); } this->accept(); @@ -145,46 +153,39 @@ ResourcePage* ResourceDownloadDialog::getSelectedPage() return m_selectedPage; } -void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, bool is_indexed) +void ResourceDownloadDialog::addResource(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& ver) { - removeResource(pack, ver); - - ver.is_currently_selected = true; - m_selected.insert(pack.name, makeShared(pack, ver, getBaseModel(), is_indexed)); - - m_buttons.button(QDialogButtonBox::Ok)->setEnabled(!m_selected.isEmpty()); + removeResource(pack->name); + m_selectedPage->addResourceToPage(pack, ver, getBaseModel()); + setButtonStatus(); } -static ModPlatform::IndexedVersion& getVersionWithID(ModPlatform::IndexedPack& pack, QVariant id) +void ResourceDownloadDialog::removeResource(const QString& pack_name) { - Q_ASSERT(pack.versionsLoaded); - auto it = std::find_if(pack.versions.begin(), pack.versions.end(), [id](auto const& v) { return v.fileId == id; }); - Q_ASSERT(it != pack.versions.end()); - return *it; + for (auto page : m_container->getPages()) { + static_cast(page)->removeResourceFromPage(pack_name); + } + setButtonStatus(); } -void ResourceDownloadDialog::removeResource(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver) +void ResourceDownloadDialog::setButtonStatus() { - if (auto selected_task_it = m_selected.find(pack.name); selected_task_it != m_selected.end()) { - auto selected_task = *selected_task_it; - auto old_version_id = selected_task->getVersionID(); - - // If the new and old version IDs don't match, search for the old one and deselect it. - if (ver.fileId != old_version_id) - getVersionWithID(pack, old_version_id).is_currently_selected = false; + auto selected = false; + for (auto page : m_container->getPages()) { + auto res = static_cast(page); + selected = selected || res->hasSelectedPacks(); } - - // Deselect the new version too, since all versions of that pack got removed. - ver.is_currently_selected = false; - - m_selected.remove(pack.name); - - m_buttons.button(QDialogButtonBox::Ok)->setEnabled(!m_selected.isEmpty()); + m_buttons.button(QDialogButtonBox::Ok)->setEnabled(selected); } const QList ResourceDownloadDialog::getTasks() { - return m_selected.values(); + QList selected; + for (auto page : m_container->getPages()) { + auto res = static_cast(page); + selected.append(res->selectedPacks()); + } + return selected; } void ResourceDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* selected) @@ -205,8 +206,6 @@ void ResourceDownloadDialog::selectedPageChanged(BasePage* previous, BasePage* s m_selectedPage->setSearchTerm(prev_page->getSearchTerm()); } - - ModDownloadDialog::ModDownloadDialog(QWidget* parent, const std::shared_ptr& mods, BaseInstance* instance) : ResourceDownloadDialog(parent, mods), m_instance(instance) { @@ -232,7 +231,6 @@ QList ModDownloadDialog::getPages() return pages; } - ResourcePackDownloadDialog::ResourcePackDownloadDialog(QWidget* parent, const std::shared_ptr& resource_packs, BaseInstance* instance) @@ -258,7 +256,6 @@ QList ResourcePackDownloadDialog::getPages() return pages; } - TexturePackDownloadDialog::TexturePackDownloadDialog(QWidget* parent, const std::shared_ptr& resource_packs, BaseInstance* instance) @@ -284,7 +281,6 @@ QList TexturePackDownloadDialog::getPages() return pages; } - ShaderPackDownloadDialog::ShaderPackDownloadDialog(QWidget* parent, const std::shared_ptr& shaders, BaseInstance* instance) diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.h b/launcher/ui/dialogs/ResourceDownloadDialog.h index 5678dc8b..5b5b48c6 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.h +++ b/launcher/ui/dialogs/ResourceDownloadDialog.h @@ -62,8 +62,8 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { bool selectPage(QString pageId); ResourcePage* getSelectedPage(); - void addResource(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&, bool is_indexed = false); - void removeResource(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); + void addResource(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&); + void removeResource(const QString&); const QList getTasks(); [[nodiscard]] const std::shared_ptr getBaseModel() const { return m_base_model; } @@ -79,6 +79,7 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { protected: [[nodiscard]] virtual QString geometrySaveKey() const { return ""; } + void setButtonStatus(); protected: const std::shared_ptr m_base_model; @@ -88,12 +89,8 @@ class ResourceDownloadDialog : public QDialog, public BasePageProvider { QDialogButtonBox m_buttons; QVBoxLayout m_vertical_layout; - - QHash m_selected; }; - - class ModDownloadDialog final : public ResourceDownloadDialog { Q_OBJECT @@ -135,8 +132,8 @@ class TexturePackDownloadDialog final : public ResourceDownloadDialog { public: explicit TexturePackDownloadDialog(QWidget* parent, - const std::shared_ptr& resource_packs, - BaseInstance* instance); + const std::shared_ptr& resource_packs, + BaseInstance* instance); ~TexturePackDownloadDialog() override = default; //: String that gets appended to the texture pack download dialog title ("Download " + resourcesString()) @@ -153,9 +150,7 @@ class ShaderPackDownloadDialog final : public ResourceDownloadDialog { Q_OBJECT public: - explicit ShaderPackDownloadDialog(QWidget* parent, - const std::shared_ptr& shader_packs, - BaseInstance* instance); + explicit ShaderPackDownloadDialog(QWidget* parent, const std::shared_ptr& shader_packs, BaseInstance* instance); ~ShaderPackDownloadDialog() override = default; //: String that gets appended to the shader pack download dialog title ("Download " + resourcesString()) diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 04be43ad..95064d16 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -55,8 +55,7 @@ namespace ResourceDownload { -ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance& instance) - : ResourcePage(dialog, instance) +ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance) { connect(m_ui->searchButton, &QPushButton::clicked, this, &ModPage::triggerSearch); connect(m_ui->resourceFilterButton, &QPushButton::clicked, this, &ModPage::filterMods); @@ -75,12 +74,10 @@ void ModPage::setFilterWidget(unique_qobject_ptr& widget) m_filter_widget->setInstance(&static_cast(m_base_instance)); m_filter = m_filter_widget->getFilter(); - connect(m_filter_widget.get(), &ModFilterWidget::filterChanged, this, [&]{ - m_ui->searchButton->setStyleSheet("text-decoration: underline"); - }); - connect(m_filter_widget.get(), &ModFilterWidget::filterUnchanged, this, [&]{ - m_ui->searchButton->setStyleSheet("text-decoration: none"); - }); + connect(m_filter_widget.get(), &ModFilterWidget::filterChanged, this, + [&] { m_ui->searchButton->setStyleSheet("text-decoration: underline"); }); + connect(m_filter_widget.get(), &ModFilterWidget::filterUnchanged, this, + [&] { m_ui->searchButton->setStyleSheet("text-decoration: none"); }); } /******** Callbacks to events in the UI (set up in the derived classes) ********/ @@ -125,11 +122,11 @@ void ModPage::updateVersionList() QString mcVersion = packProfile->getComponentVersion("net.minecraft"); auto current_pack = getCurrentPack(); - for (int i = 0; i < current_pack.versions.size(); i++) { - auto version = current_pack.versions[i]; + for (int i = 0; i < current_pack->versions.size(); i++) { + auto version = current_pack->versions[i]; bool valid = false; - for(auto& mcVer : m_filter->versions){ - //NOTE: Flame doesn't care about loader, so passing it changes nothing. + for (auto& mcVer : m_filter->versions) { + // NOTE: Flame doesn't care about loader, so passing it changes nothing. if (validateVersion(version, mcVer.toString(), packProfile->getModLoaders())) { valid = true; break; @@ -148,10 +145,12 @@ void ModPage::updateVersionList() updateSelectionButton(); } -void ModPage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) +void ModPage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, + ModPlatform::IndexedVersion& version, + const std::shared_ptr base_model) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); - m_parent_dialog->addResource(pack, version, is_indexed); + m_model->addPack(pack, version, base_model, is_indexed); } } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h index 4ea55efa..5510c191 100644 --- a/launcher/ui/pages/modplatform/ModPage.h +++ b/launcher/ui/pages/modplatform/ModPage.h @@ -8,8 +8,8 @@ #include "modplatform/ModIndex.h" -#include "ui/pages/modplatform/ResourcePage.h" #include "ui/pages/modplatform/ModModel.h" +#include "ui/pages/modplatform/ResourcePage.h" #include "ui/widgets/ModFilterWidget.h" namespace Ui { @@ -25,13 +25,14 @@ class ModPage : public ResourcePage { Q_OBJECT public: - template + template static T* create(ModDownloadDialog* dialog, BaseInstance& instance) { auto page = new T(dialog, instance); auto model = static_cast(page->getModel()); - auto filter_widget = ModFilterWidget::create(static_cast(instance).getPackProfile()->getComponentVersion("net.minecraft"), page); + auto filter_widget = + ModFilterWidget::create(static_cast(instance).getPackProfile()->getComponentVersion("net.minecraft"), page); page->setFilterWidget(filter_widget); model->setFilter(page->getFilter()); @@ -48,9 +49,13 @@ class ModPage : public ResourcePage { [[nodiscard]] QMap urlHandlers() const override; - void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&) override; + void addResourceToPage(ModPlatform::IndexedPack::Ptr, + ModPlatform::IndexedVersion&, + const std::shared_ptr) override; - virtual auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional loaders = {}) const -> bool = 0; + virtual auto validateVersion(ModPlatform::IndexedVersion& ver, + QString mineVer, + std::optional loaders = {}) const -> bool = 0; [[nodiscard]] bool supportsFiltering() const override { return true; }; auto getFilter() const -> const std::shared_ptr { return m_filter; } diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index 472aa851..a5ea1ca9 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -6,9 +6,11 @@ #include #include +#include #include #include #include +#include #include #include "Application.h" @@ -65,7 +67,7 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant return QSize(0, 58); case Qt::UserRole: { QVariant v; - v.setValue(*pack); + v.setValue(pack); return v; } // Custom data @@ -103,7 +105,7 @@ bool ResourceModel::setData(const QModelIndex& index, const QVariant& value, int if (pos >= m_packs.size() || pos < 0 || !index.isValid()) return false; - m_packs[pos] = std::make_shared(value.value()); + m_packs[pos] = value.value(); emit dataChanged(index, index); return true; @@ -230,7 +232,7 @@ void ResourceModel::clearData() void ResourceModel::runSearchJob(Task::Ptr ptr) { - m_current_search_job.reset(ptr); // clean up first + m_current_search_job.reset(ptr); // clean up first m_current_search_job->start(); } void ResourceModel::runInfoJob(Task::Ptr ptr) @@ -336,7 +338,15 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc) ModPlatform::IndexedPack::Ptr pack = std::make_shared(); try { loadIndexedPack(*pack, packObj); - newList.append(pack); + if (auto sel = std::find_if(m_selected.begin(), m_selected.end(), + [&pack](const DownloadTaskPtr i) { + const auto ipack = i->getPack(); + return ipack->provider == pack->provider && ipack->addonId == pack->addonId; + }); + sel != m_selected.end()) { + newList.append(sel->get()->getPack()); + } else + newList.append(pack); } catch (const JSONValidationError& e) { qWarning() << "Error while loading resource from " << debugName() << ": " << e.cause(); continue; @@ -390,15 +400,15 @@ void ResourceModel::searchRequestAborted() void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index) { - auto current_pack = data(index, Qt::UserRole).value(); + auto current_pack = data(index, Qt::UserRole).value(); // Check if the index is still valid for this resource or not - if (pack.addonId != current_pack.addonId) + if (pack.addonId != current_pack->addonId) return; try { auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array(); - loadIndexedPackVersions(current_pack, arr); + loadIndexedPackVersions(*current_pack, arr); } catch (const JSONValidationError& e) { qDebug() << doc; qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause(); @@ -417,15 +427,15 @@ void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::Ind void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index) { - auto current_pack = data(index, Qt::UserRole).value(); + auto current_pack = data(index, Qt::UserRole).value(); // Check if the index is still valid for this resource or not - if (pack.addonId != current_pack.addonId) + if (pack.addonId != current_pack->addonId) return; try { auto obj = Json::requireObject(doc); - loadExtraPackInfo(current_pack, obj); + loadExtraPackInfo(*current_pack, obj); } catch (const JSONValidationError& e) { qDebug() << doc; qWarning() << "Error while reading " << debugName() << " resource info: " << e.cause(); @@ -442,4 +452,39 @@ void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::Indexe emit projectInfoUpdated(); } +void ResourceModel::addPack(ModPlatform::IndexedPack::Ptr pack, + ModPlatform::IndexedVersion& version, + const std::shared_ptr packs, + bool is_indexed, + QString custom_target_folder) +{ + version.is_currently_selected = true; + m_selected.append(makeShared(pack, version, packs, is_indexed, custom_target_folder)); +} + +void ResourceModel::removePack(const QString& rem) +{ + auto pred = [&rem](const DownloadTaskPtr i) { return rem == i->getName(); }; +#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) + m_selected.removeIf(pred); +#else + { + for (auto it = m_selected.begin(); it != m_selected.end();) + if (pred(*it)) + it = m_selected.erase(it); + else + ++it; + } +#endif + auto pack = std::find_if(m_packs.begin(), m_packs.end(), [&rem](const ModPlatform::IndexedPack::Ptr i) { return rem == i->name; }); + if (pack == m_packs.end()) { // ignore it if is not in the current search + return; + } + if (!pack->get()->versionsLoaded) { + return; + } + for (auto& ver : pack->get()->versions) + ver.is_currently_selected = false; +} + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 1ec42cda..69e23473 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -10,6 +10,7 @@ #include "QObjectPtr.h" +#include "ResourceDownloadTask.h" #include "modplatform/ResourceAPI.h" #include "tasks/ConcurrentTask.h" @@ -29,6 +30,8 @@ class ResourceModel : public QAbstractListModel { Q_PROPERTY(QString search_term MEMBER m_search_term WRITE setSearchTerm) public: + using DownloadTaskPtr = shared_qobject_ptr; + ResourceModel(ResourceAPI* api); ~ResourceModel() override; @@ -80,6 +83,14 @@ class ResourceModel : public QAbstractListModel { /** Gets the icon at the URL for the given index. If it's not fetched yet, fetch it and update when fisinhed. */ std::optional getIcon(QModelIndex&, const QUrl&); + void addPack(ModPlatform::IndexedPack::Ptr pack, + ModPlatform::IndexedVersion& version, + const std::shared_ptr packs, + bool is_indexed = false, + QString custom_target_folder = {}); + void removePack(const QString& rem); + QList selectedPacks() { return m_selected; } + protected: /** Resets the model's data. */ void clearData(); @@ -124,6 +135,7 @@ class ResourceModel : public QAbstractListModel { QSet m_failed_icon_actions; QList m_packs; + QList m_selected; // HACK: We need this to prevent callbacks from calling the model after it has already been deleted. // This leaks a tiny bit of memory per time the user has opened a resource dialog. How to make this better? diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index f75bb886..736034ad 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -37,6 +37,7 @@ */ #include "ResourcePage.h" +#include "modplatform/ModIndex.h" #include "ui_ResourcePage.h" #include @@ -158,16 +159,16 @@ void ResourcePage::addSortings() m_ui->sortByBox->addItem(sorting.readable_name, QVariant(sorting.index)); } -bool ResourcePage::setCurrentPack(ModPlatform::IndexedPack pack) +bool ResourcePage::setCurrentPack(ModPlatform::IndexedPack::Ptr pack) { QVariant v; v.setValue(pack); return m_model->setData(m_ui->packView->currentIndex(), v, Qt::UserRole); } -ModPlatform::IndexedPack ResourcePage::getCurrentPack() const +ModPlatform::IndexedPack::Ptr ResourcePage::getCurrentPack() const { - return m_model->data(m_ui->packView->currentIndex(), Qt::UserRole).value(); + return m_model->data(m_ui->packView->currentIndex(), Qt::UserRole).value(); } void ResourcePage::updateUi() @@ -175,14 +176,14 @@ void ResourcePage::updateUi() auto current_pack = getCurrentPack(); QString text = ""; - QString name = current_pack.name; + QString name = current_pack->name; - if (current_pack.websiteUrl.isEmpty()) + if (current_pack->websiteUrl.isEmpty()) text = name; else - text = "" + name + ""; + text = "websiteUrl + "\">" + name + ""; - if (!current_pack.authors.empty()) { + if (!current_pack->authors.empty()) { auto authorToStr = [](ModPlatform::ModpackAuthor& author) -> QString { if (author.url.isEmpty()) { return author.name; @@ -190,44 +191,44 @@ void ResourcePage::updateUi() return QString("%2").arg(author.url, author.name); }; QStringList authorStrs; - for (auto& author : current_pack.authors) { + for (auto& author : current_pack->authors) { authorStrs.push_back(authorToStr(author)); } text += "
" + tr(" by ") + authorStrs.join(", "); } - if (current_pack.extraDataLoaded) { - if (!current_pack.extraData.donate.isEmpty()) { + if (current_pack->extraDataLoaded) { + if (!current_pack->extraData.donate.isEmpty()) { text += "

" + tr("Donate information: "); auto donateToStr = [](ModPlatform::DonationData& donate) -> QString { return QString("%2").arg(donate.url, donate.platform); }; QStringList donates; - for (auto& donate : current_pack.extraData.donate) { + for (auto& donate : current_pack->extraData.donate) { donates.append(donateToStr(donate)); } text += donates.join(", "); } - if (!current_pack.extraData.issuesUrl.isEmpty() || !current_pack.extraData.sourceUrl.isEmpty() || - !current_pack.extraData.wikiUrl.isEmpty() || !current_pack.extraData.discordUrl.isEmpty()) { + if (!current_pack->extraData.issuesUrl.isEmpty() || !current_pack->extraData.sourceUrl.isEmpty() || + !current_pack->extraData.wikiUrl.isEmpty() || !current_pack->extraData.discordUrl.isEmpty()) { text += "

" + tr("External links:") + "
"; } - if (!current_pack.extraData.issuesUrl.isEmpty()) - text += "- " + tr("Issues: %1").arg(current_pack.extraData.issuesUrl) + "
"; - if (!current_pack.extraData.wikiUrl.isEmpty()) - text += "- " + tr("Wiki: %1").arg(current_pack.extraData.wikiUrl) + "
"; - if (!current_pack.extraData.sourceUrl.isEmpty()) - text += "- " + tr("Source code: %1").arg(current_pack.extraData.sourceUrl) + "
"; - if (!current_pack.extraData.discordUrl.isEmpty()) - text += "- " + tr("Discord: %1").arg(current_pack.extraData.discordUrl) + "
"; + if (!current_pack->extraData.issuesUrl.isEmpty()) + text += "- " + tr("Issues: %1").arg(current_pack->extraData.issuesUrl) + "
"; + if (!current_pack->extraData.wikiUrl.isEmpty()) + text += "- " + tr("Wiki: %1").arg(current_pack->extraData.wikiUrl) + "
"; + if (!current_pack->extraData.sourceUrl.isEmpty()) + text += "- " + tr("Source code: %1").arg(current_pack->extraData.sourceUrl) + "
"; + if (!current_pack->extraData.discordUrl.isEmpty()) + text += "- " + tr("Discord: %1").arg(current_pack->extraData.discordUrl) + "
"; } text += "
"; m_ui->packDescription->setHtml( - text + (current_pack.extraData.body.isEmpty() ? current_pack.description : markdownToHTML(current_pack.extraData.body))); + text + (current_pack->extraData.body.isEmpty() ? current_pack->description : markdownToHTML(current_pack->extraData.body))); m_ui->packDescription->flush(); } @@ -239,7 +240,7 @@ void ResourcePage::updateSelectionButton() } m_ui->resourceSelectionButton->setEnabled(true); - if (!getCurrentPack().isVersionSelected(m_selected_version_index)) { + if (!getCurrentPack()->isVersionSelected(m_selected_version_index)) { m_ui->resourceSelectionButton->setText(tr("Select %1 for download").arg(resourceString())); } else { m_ui->resourceSelectionButton->setText(tr("Deselect %1 for download").arg(resourceString())); @@ -254,12 +255,12 @@ void ResourcePage::updateVersionList() m_ui->versionSelectionBox->clear(); m_ui->versionSelectionBox->blockSignals(false); - for (int i = 0; i < current_pack.versions.size(); i++) { - auto& version = current_pack.versions[i]; + for (int i = 0; i < current_pack->versions.size(); i++) { + auto& version = current_pack->versions[i]; if (optedOut(version)) continue; - m_ui->versionSelectionBox->addItem(current_pack.versions[i].version, QVariant(i)); + m_ui->versionSelectionBox->addItem(current_pack->versions[i].version, QVariant(i)); } if (m_ui->versionSelectionBox->count() == 0) { @@ -279,7 +280,7 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) auto current_pack = getCurrentPack(); bool request_load = false; - if (!current_pack.versionsLoaded) { + if (!current_pack->versionsLoaded) { m_ui->resourceSelectionButton->setText(tr("Loading versions...")); m_ui->resourceSelectionButton->setEnabled(false); @@ -288,7 +289,7 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) updateVersionList(); } - if (!current_pack.extraDataLoaded) + if (!current_pack->extraDataLoaded) request_load = true; if (request_load) @@ -308,14 +309,26 @@ void ResourcePage::onVersionSelectionChanged(QString data) updateSelectionButton(); } -void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) +void ResourcePage::addResourceToDialog(ModPlatform::IndexedPack::Ptr pack, ModPlatform::IndexedVersion& version) { m_parent_dialog->addResource(pack, version); } -void ResourcePage::removeResourceFromDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) +void ResourcePage::removeResourceFromDialog(const QString& pack_name) { - m_parent_dialog->removeResource(pack, version); + m_parent_dialog->removeResource(pack_name); +} + +void ResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, + ModPlatform::IndexedVersion& ver, + const std::shared_ptr base_model) +{ + m_model->addPack(pack, ver, base_model); +} + +void ResourcePage::removeResourceFromPage(const QString& name) +{ + m_model->removePack(name); } void ResourcePage::onResourceSelected() @@ -324,12 +337,12 @@ void ResourcePage::onResourceSelected() return; auto current_pack = getCurrentPack(); - if (!current_pack.versionsLoaded) + if (!current_pack->versionsLoaded) return; - auto& version = current_pack.versions[m_selected_version_index]; + auto& version = current_pack->versions[m_selected_version_index]; if (version.is_currently_selected) - removeResourceFromDialog(current_pack, version); + removeResourceFromDialog(current_pack->name); else addResourceToDialog(current_pack, version); @@ -340,7 +353,7 @@ void ResourcePage::onResourceSelected() updateSelectionButton(); /* Force redraw on the resource list when the selection changes */ - m_ui->packView->adjustSize(); + m_ui->packView->repaint(); } void ResourcePage::openUrl(const QUrl& url) @@ -370,7 +383,7 @@ void ResourcePage::openUrl(const QUrl& url) const QString slug = match.captured(1); // ensure the user isn't opening the same mod - if (slug != getCurrentPack().slug) { + if (slug != getCurrentPack()->slug) { m_parent_dialog->selectPage(page); auto newPage = m_parent_dialog->getSelectedPage(); diff --git a/launcher/ui/pages/modplatform/ResourcePage.h b/launcher/ui/pages/modplatform/ResourcePage.h index 1896d53e..b4a87f57 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.h +++ b/launcher/ui/pages/modplatform/ResourcePage.h @@ -7,10 +7,12 @@ #include #include +#include "ResourceDownloadTask.h" #include "modplatform/ModIndex.h" #include "modplatform/ResourceAPI.h" #include "ui/pages/BasePage.h" +#include "ui/pages/modplatform/ResourceModel.h" #include "ui/widgets/ProgressWidget.h" namespace Ui { @@ -27,6 +29,7 @@ class ResourceModel; class ResourcePage : public QWidget, public BasePage { Q_OBJECT public: + using DownloadTaskPtr = shared_qobject_ptr; ~ResourcePage() override; /* Affects what the user sees */ @@ -57,8 +60,8 @@ class ResourcePage : public QWidget, public BasePage { /** Programatically set the term in the search bar. */ void setSearchTerm(QString); - [[nodiscard]] bool setCurrentPack(ModPlatform::IndexedPack); - [[nodiscard]] auto getCurrentPack() const -> ModPlatform::IndexedPack; + [[nodiscard]] bool setCurrentPack(ModPlatform::IndexedPack::Ptr); + [[nodiscard]] auto getCurrentPack() const -> ModPlatform::IndexedPack::Ptr; [[nodiscard]] auto getDialog() const -> const ResourceDownloadDialog* { return m_parent_dialog; } [[nodiscard]] auto getModel() const -> ResourceModel* { return m_model; } @@ -72,12 +75,17 @@ class ResourcePage : public QWidget, public BasePage { virtual void updateSelectionButton(); virtual void updateVersionList(); - virtual void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); - virtual void removeResourceFromDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&); + void addResourceToDialog(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&); + void removeResourceFromDialog(const QString& pack_name); + virtual void removeResourceFromPage(const QString& name); + virtual void addResourceToPage(ModPlatform::IndexedPack::Ptr, ModPlatform::IndexedVersion&, const std::shared_ptr); + + QList selectedPacks() { return m_model->selectedPacks(); } + bool hasSelectedPacks() { return !(m_model->selectedPacks().isEmpty()); } protected slots: virtual void triggerSearch() {} - + void onSelectionChanged(QModelIndex first, QModelIndex second); void onVersionSelectionChanged(QString data); void onResourceSelected(); diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.cpp b/launcher/ui/pages/modplatform/ShaderPackPage.cpp index 251c07e7..fbf94e84 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.cpp +++ b/launcher/ui/pages/modplatform/ShaderPackPage.cpp @@ -13,8 +13,7 @@ namespace ResourceDownload { -ShaderPackResourcePage::ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) - : ResourcePage(dialog, instance) +ShaderPackResourcePage::ShaderPackResourcePage(ShaderPackDownloadDialog* dialog, BaseInstance& instance) : ResourcePage(dialog, instance) { connect(m_ui->searchButton, &QPushButton::clicked, this, &ShaderPackResourcePage::triggerSearch); connect(m_ui->packView, &QListView::doubleClicked, this, &ShaderPackResourcePage::onResourceSelected); @@ -38,17 +37,20 @@ QMap ShaderPackResourcePage::urlHandlers() const { QMap map; map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?modrinth\\.com\\/shaders\\/([^\\/]+)\\/?"), "modrinth"); - map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/customization\\/([^\\/]+)\\/?"), "curseforge"); + map.insert(QRegularExpression::anchoredPattern("(?:www\\.)?curseforge\\.com\\/minecraft\\/customization\\/([^\\/]+)\\/?"), + "curseforge"); map.insert(QRegularExpression::anchoredPattern("minecraft\\.curseforge\\.com\\/projects\\/([^\\/]+)\\/?"), "curseforge"); return map; } -void ShaderPackResourcePage::addResourceToDialog(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& version) +void ShaderPackResourcePage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, + ModPlatform::IndexedVersion& version, + const std::shared_ptr base_model) { + QString custom_target_folder; if (version.loaders.contains(QStringLiteral("canvas"))) - version.custom_target_folder = QStringLiteral("resourcepacks"); - - m_parent_dialog->addResource(pack, version); + custom_target_folder = QStringLiteral("resourcepacks"); + m_model->addPack(pack, version, base_model, false, custom_target_folder); } } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ShaderPackPage.h b/launcher/ui/pages/modplatform/ShaderPackPage.h index 9039c4d9..fcf6d4a7 100644 --- a/launcher/ui/pages/modplatform/ShaderPackPage.h +++ b/launcher/ui/pages/modplatform/ShaderPackPage.h @@ -38,7 +38,9 @@ class ShaderPackResourcePage : public ResourcePage { [[nodiscard]] bool supportsFiltering() const override { return false; }; - void addResourceToDialog(ModPlatform::IndexedPack&, ModPlatform::IndexedVersion&) override; + void addResourceToPage(ModPlatform::IndexedPack::Ptr, + ModPlatform::IndexedVersion&, + const std::shared_ptr) override; [[nodiscard]] QMap urlHandlers() const override; diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index b9b17b42..38a22897 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -137,6 +137,11 @@ BasePage* PageContainer::getPage(QString pageId) return m_model->findPageEntryById(pageId); } +const QList PageContainer::getPages() const +{ + return m_model->pages(); +} + void PageContainer::refreshContainer() { m_proxyModel->invalidate(); diff --git a/launcher/ui/widgets/PageContainer.h b/launcher/ui/widgets/PageContainer.h index 97e294dc..ad74d43a 100644 --- a/launcher/ui/widgets/PageContainer.h +++ b/launcher/ui/widgets/PageContainer.h @@ -80,6 +80,7 @@ public: virtual bool selectPage(QString pageId) override; BasePage* getPage(QString pageId) override; + const QList getPages() const; void refreshContainer() override; virtual void setParentContainer(BasePageContainer * container) -- cgit From f6f32914de6dbad07cffe786d0f15df03525a1c2 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 2 Jun 2023 15:48:02 -0700 Subject: fix: add origonal instance path to allowed_symlinks.txt when copying via symlinks Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/InstanceCopyTask.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/InstanceCopyTask.cpp b/launcher/InstanceCopyTask.cpp index 4ac3b51a..abe97b17 100644 --- a/launcher/InstanceCopyTask.cpp +++ b/launcher/InstanceCopyTask.cpp @@ -39,7 +39,16 @@ void InstanceCopyTask::executeTask() setStatus(tr("Copying instance %1").arg(m_origInstance->name())); auto copySaves = [&]() { - FS::copy savesCopy(FS::PathCombine(m_origInstance->instanceRoot(), "saves"), FS::PathCombine(m_stagingPath, "saves")); + QFileInfo mcDir(FS::PathCombine(m_stagingPath, "minecraft")); + QFileInfo dotMCDir(FS::PathCombine(m_stagingPath, ".minecraft")); + + QString staging_mc_dir; + if (mcDir.exists() && !dotMCDir.exists()) + staging_mc_dir = mcDir.filePath(); + else + staging_mc_dir = dotMCDir.filePath(); + + FS::copy savesCopy(FS::PathCombine(m_origInstance->gameRoot(), "saves"), FS::PathCombine(staging_mc_dir, "saves")); savesCopy.followSymlinks(true); return savesCopy(); @@ -123,6 +132,7 @@ void InstanceCopyTask::copyFinished() emitFailed(tr("Instance folder copy failed.")); return; } + // FIXME: shouldn't this be able to report errors? auto instanceSettings = std::make_shared(FS::PathCombine(m_stagingPath, "instance.cfg")); @@ -134,6 +144,24 @@ void InstanceCopyTask::copyFinished() } if (m_useLinks) inst->addLinkedInstanceId(m_origInstance->id()); + if (m_useLinks) { + auto allowed_symlinks_file = QFileInfo(FS::PathCombine(inst->gameRoot(), "allowed_symlinks.txt")); + + QByteArray allowed_symlinks; + if (allowed_symlinks_file.exists()) { + allowed_symlinks.append(FS::read(allowed_symlinks_file.path())); + if (allowed_symlinks.right(1) != "\n") + allowed_symlinks.append("\n"); // we want to be on a new line + } + allowed_symlinks.append(m_origInstance->gameRoot().toUtf8()); + allowed_symlinks.append("\n"); + if (allowed_symlinks_file.isSymbolicLink()) + FS::deletePath(allowed_symlinks_file + .path()); // we dont want to modify the origonal. also make sure the resulting file is not itself a link. + + FS::write(allowed_symlinks_file.path(), allowed_symlinks); + } + emitSucceeded(); } -- cgit From 8eb10e991f79ef38e1c689d28e34b5f4fda8dc83 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 2 Jun 2023 16:14:38 -0700 Subject: fix: use isSymLink (i've made this mistake before but I've made it again) Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/InstanceCopyTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/InstanceCopyTask.cpp b/launcher/InstanceCopyTask.cpp index abe97b17..a0b5635c 100644 --- a/launcher/InstanceCopyTask.cpp +++ b/launcher/InstanceCopyTask.cpp @@ -155,7 +155,7 @@ void InstanceCopyTask::copyFinished() } allowed_symlinks.append(m_origInstance->gameRoot().toUtf8()); allowed_symlinks.append("\n"); - if (allowed_symlinks_file.isSymbolicLink()) + if (allowed_symlinks_file.isSymLink()) FS::deletePath(allowed_symlinks_file .path()); // we dont want to modify the origonal. also make sure the resulting file is not itself a link. -- cgit From e26827b84922d7d84c3ee83dfed58759b1c0ca15 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 3 Jun 2023 13:39:42 +0100 Subject: Optimised icons Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 2 ++ launcher/FastFileIconProvider.cpp | 47 ++++++++++++++++++++++++++++ launcher/FastFileIconProvider.h | 26 +++++++++++++++ launcher/ui/dialogs/ExportInstanceDialog.cpp | 5 +-- launcher/ui/dialogs/ExportInstanceDialog.h | 42 +++++++++++++++++++------ launcher/ui/dialogs/ExportMrPackDialog.cpp | 3 ++ launcher/ui/dialogs/ExportMrPackDialog.h | 2 ++ 7 files changed, 115 insertions(+), 12 deletions(-) create mode 100644 launcher/FastFileIconProvider.cpp create mode 100644 launcher/FastFileIconProvider.h (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 82ed0930..ce2771a4 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -724,6 +724,8 @@ SET(LAUNCHER_SOURCES SkinUtils.h FileIgnoreProxy.cpp FileIgnoreProxy.h + FastFileIconProvider.cpp + FastFileIconProvider.h # GUI - setup wizard ui/setupwizard/SetupWizard.h diff --git a/launcher/FastFileIconProvider.cpp b/launcher/FastFileIconProvider.cpp new file mode 100644 index 00000000..f2b6f442 --- /dev/null +++ b/launcher/FastFileIconProvider.cpp @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "FastFileIconProvider.h" + +#include +#include + +QIcon FastFileIconProvider::icon(const QFileInfo& info) const +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) + bool link = info.isSymbolicLink() || info.isAlias() || info.isShortcut(); +#else + // in versions prior to 6.4 we don't have access to isAlias + bool link = info.isSymLink(); +#endif + QStyle::StandardPixmap icon; + + if (info.isDir()) { + if (link) + icon = QStyle::SP_DirLinkIcon; + else + icon = QStyle::SP_DirIcon; + } else { + if (link) + icon = QStyle::SP_FileLinkIcon; + else + icon = QStyle::SP_FileIcon; + } + + return QApplication::style()->standardIcon(icon); +} \ No newline at end of file diff --git a/launcher/FastFileIconProvider.h b/launcher/FastFileIconProvider.h new file mode 100644 index 00000000..20853404 --- /dev/null +++ b/launcher/FastFileIconProvider.h @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +class FastFileIconProvider : public QFileIconProvider { + public: + QIcon icon(const QFileInfo& info) const override; +}; \ No newline at end of file diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index 603a723c..8ecd91a9 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -46,7 +47,6 @@ #include #include #include -#include "StringUtils.h" #include "SeparatorPrefixTree.h" #include "Application.h" #include @@ -57,6 +57,7 @@ ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget *parent { ui->setupUi(this); auto model = new QFileSystemModel(this); + model->setIconProvider(&icons); auto root = instance->instanceRoot(); proxyModel = new FileIgnoreProxy(root, this); loadPackIgnore(); diff --git a/launcher/ui/dialogs/ExportInstanceDialog.h b/launcher/ui/dialogs/ExportInstanceDialog.h index d96f4537..5e801875 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.h +++ b/launcher/ui/dialogs/ExportInstanceDialog.h @@ -1,16 +1,36 @@ -/* Copyright 2013-2021 MultiMC Contributors +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad * - * 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 + * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. * - * 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. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #pragma once @@ -19,6 +39,7 @@ #include #include #include "FileIgnoreProxy.h" +#include "FastFileIconProvider.h" class BaseInstance; typedef std::shared_ptr InstancePtr; @@ -48,6 +69,7 @@ private: Ui::ExportInstanceDialog *ui; InstancePtr m_instance; FileIgnoreProxy * proxyModel; + FastFileIconProvider icons; private slots: void rowsInserted(QModelIndex parent, int top, int bottom); diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 1551cc60..06e4693e 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -26,6 +26,7 @@ #include #include #include +#include "FastFileIconProvider.h" #include "FileSystem.h" #include "MMCZip.h" #include "modplatform/modrinth/ModrinthPackExportTask.h" @@ -38,6 +39,8 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); QFileSystemModel* model = new QFileSystemModel(this); + model->setIconProvider(&icons); + // use the game root - everything outside cannot be exported const QDir root(instance->gameRoot()); proxy = new FileIgnoreProxy(instance->gameRoot(), this); diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportMrPackDialog.h index 63e3f016..98f1d5fc 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.h +++ b/launcher/ui/dialogs/ExportMrPackDialog.h @@ -20,6 +20,7 @@ #include #include "BaseInstance.h" +#include "FastFileIconProvider.h" #include "FileIgnoreProxy.h" namespace Ui { @@ -39,4 +40,5 @@ class ExportMrPackDialog : public QDialog { const InstancePtr instance; Ui::ExportMrPackDialog* ui; FileIgnoreProxy* proxy; + FastFileIconProvider icons; }; -- cgit From 3c87e5d31eb8fb33d6e63a38377c9729a130af45 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 3 Jun 2023 13:44:09 +0100 Subject: Make mcInstance mutable Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 2 +- launcher/modplatform/modrinth/ModrinthPackExportTask.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 98fbc218..29df90dd 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -40,7 +40,7 @@ ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, , version(version) , summary(summary) , instance(instance) - , mcInstance(dynamic_cast(instance.get())) + , mcInstance(dynamic_cast(instance.get())) , gameRoot(instance->gameRoot()) , output(output) , filter(filter) diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index 5426d6da..af00ffaa 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -51,7 +51,7 @@ class ModrinthPackExportTask : public Task { // inputs const QString name, version, summary; const InstancePtr instance; - const MinecraftInstance* mcInstance; + MinecraftInstance* mcInstance; const QDir gameRoot; const QString output; const MMCZip::FilterFunction filter; -- cgit From f613b03efd58e04451e70d4e673adff5837492a9 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 3 Jun 2023 08:28:49 -0700 Subject: Typo fix Co-authored-by: Sefa Eyeoglu Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/InstanceCopyTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/InstanceCopyTask.cpp b/launcher/InstanceCopyTask.cpp index a0b5635c..60dcd5a1 100644 --- a/launcher/InstanceCopyTask.cpp +++ b/launcher/InstanceCopyTask.cpp @@ -157,7 +157,7 @@ void InstanceCopyTask::copyFinished() allowed_symlinks.append("\n"); if (allowed_symlinks_file.isSymLink()) FS::deletePath(allowed_symlinks_file - .path()); // we dont want to modify the origonal. also make sure the resulting file is not itself a link. + .path()); // we dont want to modify the original. also make sure the resulting file is not itself a link. FS::write(allowed_symlinks_file.path(), allowed_symlinks); } -- cgit From 5824047ffa4e31f018ddc068c2677ce9b8e5b43d Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Mon, 5 Jun 2023 01:12:16 -0700 Subject: fix(memory leak): cyclic refrence in translations model dl task Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/translations/TranslationsModel.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 46db4804..23e55c51 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -190,7 +190,7 @@ struct TranslationsModel::Private std::unique_ptr m_qt_translator; std::unique_ptr m_app_translator; - Net::Download::Ptr m_index_task; + Net::Download* m_index_task; QString m_downloadingTranslation; NetJob::Ptr m_dl_job; NetJob::Ptr m_index_job; @@ -673,8 +673,9 @@ void TranslationsModel::downloadIndex() d->m_index_job.reset(new NetJob("Translations Index", APPLICATION->network())); MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("translations", "index_v2.json"); entry->setStale(true); - d->m_index_task = Net::Download::makeCached(QUrl(BuildConfig.TRANSLATIONS_BASE_URL + "index_v2.json"), entry); - d->m_index_job->addNetAction(d->m_index_task); + auto task = Net::Download::makeCached(QUrl(BuildConfig.TRANSLATIONS_BASE_URL + "index_v2.json"), entry); + d->m_index_task = task.get(); + d->m_index_job->addNetAction(task); connect(d->m_index_job.get(), &NetJob::failed, this, &TranslationsModel::indexFailed); connect(d->m_index_job.get(), &NetJob::succeeded, this, &TranslationsModel::indexReceived); d->m_index_job->start(); -- cgit From 37b4f606c8e0853c831f792e7238587c66222176 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 5 Jun 2023 17:52:48 +0100 Subject: Validate input lengths on mrpack export Signed-off-by: TheKodeToad --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 14 ++++++++++++++ launcher/ui/dialogs/ExportMrPackDialog.h | 1 + launcher/ui/dialogs/ExportMrPackDialog.ui | 6 +++++- 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 06e4693e..239873f6 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "FastFileIconProvider.h" #include "FileSystem.h" #include "MMCZip.h" @@ -38,6 +39,13 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) ui->name->setText(instance->name()); ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); + // ensure a valid pack is generated + // the name and version fields mustn't be empty + connect(ui->name, &QLineEdit::textEdited, this, &ExportMrPackDialog::validate); + connect(ui->version, &QLineEdit::textEdited, this, &ExportMrPackDialog::validate); + // the instance name can technically be empty + validate(); + QFileSystemModel* model = new QFileSystemModel(this); model->setIconProvider(&icons); @@ -107,3 +115,9 @@ void ExportMrPackDialog::done(int result) QDialog::done(result); } + +void ExportMrPackDialog::validate() +{ + const bool invalid = ui->name->text().isEmpty() || ui->version->text().isEmpty(); + ui->buttonBox->button(QDialogButtonBox::Ok)->setDisabled(invalid); +} diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportMrPackDialog.h index 98f1d5fc..1c70c4ae 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.h +++ b/launcher/ui/dialogs/ExportMrPackDialog.h @@ -35,6 +35,7 @@ class ExportMrPackDialog : public QDialog { ~ExportMrPackDialog(); void done(int result) override; + void validate(); private: const InstancePtr instance; diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportMrPackDialog.ui index f154d210..9a789737 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.ui +++ b/launcher/ui/dialogs/ExportMrPackDialog.ui @@ -51,7 +51,11 @@
- + + + 1.0.0 + +
-- cgit From 961285d6abad3e70a0ab748007349ef67632f138 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 5 Jun 2023 20:49:47 +0100 Subject: Add a search bar to version lists Signed-off-by: TheKodeToad --- launcher/VersionProxyModel.cpp | 21 +++++++++++-- launcher/VersionProxyModel.h | 3 ++ launcher/ui/dialogs/VersionSelectDialog.cpp | 47 ++++++++++++++++++---------- launcher/ui/widgets/JavaSettingsWidget.cpp | 2 +- launcher/ui/widgets/VersionSelectWidget.cpp | 34 ++++++++++++++++++-- launcher/ui/widgets/VersionSelectWidget.h | 48 +++++++++++++++++++++-------- 6 files changed, 122 insertions(+), 33 deletions(-) (limited to 'launcher') diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 6aba268d..d5d14c24 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,9 +55,14 @@ public: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { const auto &filters = m_parent->filters(); + const QString &search = m_parent->search(); + const QModelIndex idx = sourceModel()->index(source_row, 0, source_parent); + + if (!search.isEmpty() && !sourceModel()->data(idx, BaseVersionList::VersionRole).toString().contains(search)) + return false; + for (auto it = filters.begin(); it != filters.end(); ++it) { - auto idx = sourceModel()->index(source_row, 0, source_parent); auto data = sourceModel()->data(idx, it.key()); auto match = data.toString(); if(!it.value()->accepts(match)) @@ -431,6 +437,7 @@ QModelIndex VersionProxyModel::getVersion(const QString& version) const void VersionProxyModel::clearFilters() { m_filters.clear(); + m_search.clear(); filterModel->filterChanged(); } @@ -440,11 +447,21 @@ void VersionProxyModel::setFilter(const BaseVersionList::ModelRoles column, Filt filterModel->filterChanged(); } +void VersionProxyModel::setSearch(const QString &search) { + m_search = search; + filterModel->filterChanged(); +} + const VersionProxyModel::FilterMap &VersionProxyModel::filters() const { return m_filters; } +const QString &VersionProxyModel::search() const +{ + return m_search; +} + void VersionProxyModel::sourceAboutToBeReset() { beginResetModel(); diff --git a/launcher/VersionProxyModel.h b/launcher/VersionProxyModel.h index 8991c31b..6434376c 100644 --- a/launcher/VersionProxyModel.h +++ b/launcher/VersionProxyModel.h @@ -38,7 +38,9 @@ public: virtual void setSourceModel(QAbstractItemModel *sourceModel) override; const FilterMap &filters() const; + const QString &search() const; void setFilter(const BaseVersionList::ModelRoles column, Filter * filter); + void setSearch(const QString &search); void clearFilters(); QModelIndex getRecommended() const; QModelIndex getVersion(const QString & version) const; @@ -59,6 +61,7 @@ private slots: private: QList m_columns; FilterMap m_filters; + QString m_search; BaseVersionList::RoleList roles; VersionFilterModel * filterModel; bool hasRecommended = false; diff --git a/launcher/ui/dialogs/VersionSelectDialog.cpp b/launcher/ui/dialogs/VersionSelectDialog.cpp index d7880334..5feb70d2 100644 --- a/launcher/ui/dialogs/VersionSelectDialog.cpp +++ b/launcher/ui/dialogs/VersionSelectDialog.cpp @@ -1,16 +1,36 @@ -/* Copyright 2013-2021 MultiMC Contributors +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad * - * 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 + * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. * - * 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. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include "VersionSelectDialog.h" @@ -22,15 +42,10 @@ #include #include -#include "ui/dialogs/ProgressDialog.h" #include "ui/widgets/VersionSelectWidget.h" -#include "ui/dialogs/CustomMessageBox.h" #include "BaseVersion.h" #include "BaseVersionList.h" -#include "tasks/Task.h" -#include "Application.h" -#include "VersionProxyModel.h" VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent, bool cancelable) : QDialog(parent) @@ -40,7 +55,7 @@ VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, m_verticalLayout = new QVBoxLayout(this); m_verticalLayout->setObjectName(QStringLiteral("verticalLayout")); - m_versionWidget = new VersionSelectWidget(parent); + m_versionWidget = new VersionSelectWidget(true, parent); m_verticalLayout->addWidget(m_versionWidget); m_horizontalLayout = new QHBoxLayout(); diff --git a/launcher/ui/widgets/JavaSettingsWidget.cpp b/launcher/ui/widgets/JavaSettingsWidget.cpp index 15994319..c94fdd8d 100644 --- a/launcher/ui/widgets/JavaSettingsWidget.cpp +++ b/launcher/ui/widgets/JavaSettingsWidget.cpp @@ -46,7 +46,7 @@ void JavaSettingsWidget::setupUi() m_verticalLayout = new QVBoxLayout(this); m_verticalLayout->setObjectName(QStringLiteral("verticalLayout")); - m_versionWidget = new VersionSelectWidget(this); + m_versionWidget = new VersionSelectWidget(true, this); m_verticalLayout->addWidget(m_versionWidget); m_horizontalLayout = new QHBoxLayout(); diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index 404860d9..252e2719 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -8,8 +8,10 @@ #include "ui/dialogs/CustomMessageBox.h" -VersionSelectWidget::VersionSelectWidget(QWidget* parent) - : QWidget(parent) +VersionSelectWidget::VersionSelectWidget(QWidget* parent) : VersionSelectWidget(false, parent) {} + +VersionSelectWidget::VersionSelectWidget(bool focusSearch, QWidget* parent) + : QWidget(parent), focusSearch(focusSearch) { setObjectName(QStringLiteral("VersionSelectWidget")); verticalLayout = new QVBoxLayout(this); @@ -30,6 +32,12 @@ VersionSelectWidget::VersionSelectWidget(QWidget* parent) listView->setModel(m_proxyModel); verticalLayout->addWidget(listView); + search = new QLineEdit(this); + search->setPlaceholderText(tr("Search")); + search->setClearButtonEnabled(true); + verticalLayout->addWidget(search); + connect(search, &QLineEdit::textEdited, this, &VersionSelectWidget::updateSearch); + sneakyProgressBar = new QProgressBar(this); sneakyProgressBar->setObjectName(QStringLiteral("sneakyProgressBar")); sneakyProgressBar->setFormat(QStringLiteral("%p%")); @@ -89,6 +97,8 @@ void VersionSelectWidget::initialize(BaseVersionList *vlist) { listView->setEmptyMode(VersionListView::String); } + search->setFocus(); + focusSearch = false; preselect(); } } @@ -114,6 +124,7 @@ void VersionSelectWidget::loadList() loadTask->start(); } sneakyProgressBar->setHidden(false); + search->setHidden(true); } void VersionSelectWidget::onTaskSucceeded() @@ -123,6 +134,14 @@ void VersionSelectWidget::onTaskSucceeded() listView->setEmptyMode(VersionListView::String); } sneakyProgressBar->setHidden(true); + search->setHidden(false); + + if (focusSearch) + { + search->setFocus(); + focusSearch = false; + } + preselect(); loadTask = nullptr; } @@ -155,6 +174,17 @@ void VersionSelectWidget::preselect() selectRecommended(); } +void VersionSelectWidget::updateSearch(const QString &value) { + m_proxyModel->setSearch(value); + // if nothing is selected, pick the first result + if (!value.isEmpty()) { + listView->selectionModel()->setCurrentIndex( + listView->model()->index(0, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + listView->scrollToTop(); + } else + listView->scrollTo(listView->selectionModel()->currentIndex(), QAbstractItemView::PositionAtCenter); +} + void VersionSelectWidget::selectCurrent() { if(m_currentVersion.isEmpty()) diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index e75efc6f..df9c8a62 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -1,22 +1,43 @@ -/* Copyright 2013-2021 MultiMC Contributors +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad * - * 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 + * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. * - * 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. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #pragma once #include #include +#include #include "BaseVersionList.h" #include "VersionListView.h" @@ -30,7 +51,8 @@ class VersionSelectWidget: public QWidget { Q_OBJECT public: - explicit VersionSelectWidget(QWidget *parent = 0); + explicit VersionSelectWidget(QWidget *parent); + explicit VersionSelectWidget(bool focusSearch = false, QWidget *parent = 0); ~VersionSelectWidget(); //! loads the list if needed. @@ -67,6 +89,7 @@ private slots: private: void preselect(); + void updateSearch(const QString &value); private: QString m_currentVersion; @@ -75,9 +98,10 @@ private: int resizeOnColumn = 0; Task * loadTask; bool preselectedAlready = false; + bool focusSearch; -private: QVBoxLayout *verticalLayout = nullptr; VersionListView *listView = nullptr; + QLineEdit *search; QProgressBar *sneakyProgressBar = nullptr; }; -- cgit From 7c5047b2acd25708063056cff547dc1b8fcfbb41 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 5 Jun 2023 23:10:41 +0100 Subject: cAsE iNsEnSiTiVe Signed-off-by: TheKodeToad --- launcher/VersionProxyModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index d5d14c24..47cfa5ba 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -58,7 +58,7 @@ public: const QString &search = m_parent->search(); const QModelIndex idx = sourceModel()->index(source_row, 0, source_parent); - if (!search.isEmpty() && !sourceModel()->data(idx, BaseVersionList::VersionRole).toString().contains(search)) + if (!search.isEmpty() && !sourceModel()->data(idx, BaseVersionList::VersionRole).toString().contains(search, Qt::CaseInsensitive)) return false; for (auto it = filters.begin(); it != filters.end(); ++it) -- cgit From 6505a6280111e29b33d829703d1c1a87f90dba7a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 6 Jun 2023 10:34:05 +0300 Subject: Renamed requires fields Signed-off-by: Trial97 --- launcher/meta/JsonFormat.cpp | 7 +++---- launcher/meta/Version.cpp | 4 ++-- launcher/meta/Version.h | 4 ++-- launcher/meta/VersionList.cpp | 4 ++-- launcher/minecraft/Component.cpp | 4 ++-- launcher/minecraft/OneSixVersionFormat.cpp | 10 +++++----- launcher/minecraft/VersionFile.h | 2 +- launcher/modplatform/atlauncher/ATLPackInstallTask.cpp | 2 +- .../modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp | 2 +- 9 files changed, 19 insertions(+), 20 deletions(-) (limited to 'launcher') diff --git a/launcher/meta/JsonFormat.cpp b/launcher/meta/JsonFormat.cpp index 473f37d6..cb2d06ea 100644 --- a/launcher/meta/JsonFormat.cpp +++ b/launcher/meta/JsonFormat.cpp @@ -56,10 +56,10 @@ static Version::Ptr parseCommonVersion(const QString &uid, const QJsonObject &ob version->setType(ensureString(obj, "type", QString())); version->setRecommended(ensureBoolean(obj, QString("recommended"), false)); version->setVolatile(ensureBoolean(obj, QString("volatile"), false)); - RequireSet requires, conflicts; - parseRequires(obj, &requires, "requires"); + RequireSet reqs, conflicts; + parseRequires(obj, &reqs, "requires"); parseRequires(obj, &conflicts, "conflicts"); - version->setRequires(requires, conflicts); + version->setRequires(reqs, conflicts); return version; } @@ -176,7 +176,6 @@ void parseRequires(const QJsonObject& obj, RequireSet* ptr, const char * keyName { if(obj.contains(keyName)) { - QSet requires; auto reqArray = requireArray(obj, keyName); auto iter = reqArray.begin(); while(iter != reqArray.end()) diff --git a/launcher/meta/Version.cpp b/launcher/meta/Version.cpp index e617abf8..0718a420 100644 --- a/launcher/meta/Version.cpp +++ b/launcher/meta/Version.cpp @@ -116,9 +116,9 @@ void Meta::Version::setTime(const qint64 time) emit timeChanged(); } -void Meta::Version::setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts) +void Meta::Version::setRequires(const Meta::RequireSet &reqs, const Meta::RequireSet &conflicts) { - m_requires = requires; + m_requires = reqs; m_conflicts = conflicts; emit requiresChanged(); } diff --git a/launcher/meta/Version.h b/launcher/meta/Version.h index 78156193..59a96a68 100644 --- a/launcher/meta/Version.h +++ b/launcher/meta/Version.h @@ -63,7 +63,7 @@ public: { return m_time; } - const Meta::RequireSet &requires() const + const Meta::RequireSet &requiredSet() const { return m_requires; } @@ -91,7 +91,7 @@ public: public: // for usage by format parsers only void setType(const QString &type); void setTime(const qint64 time); - void setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts); + void setRequires(const Meta::RequireSet &reqs, const Meta::RequireSet &conflicts); void setVolatile(bool volatile_); void setRecommended(bool recommended); void setProvidesRecommendations(); diff --git a/launcher/meta/VersionList.cpp b/launcher/meta/VersionList.cpp index 7f001dfc..9f448278 100644 --- a/launcher/meta/VersionList.cpp +++ b/launcher/meta/VersionList.cpp @@ -77,7 +77,7 @@ QVariant VersionList::data(const QModelIndex &index, int role) const case ParentVersionRole: { // FIXME: HACK: this should be generic and be replaced by something else. Anything that is a hard 'equals' dep is a 'parent uid'. - auto & reqs = version->requires(); + auto & reqs = version->requiredSet(); auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Require & req) { return req.uid == "net.minecraft"; @@ -92,7 +92,7 @@ QVariant VersionList::data(const QModelIndex &index, int role) const case UidRole: return version->uid(); case TimeRole: return version->time(); - case RequiresRole: return QVariant::fromValue(version->requires()); + case RequiresRole: return QVariant::fromValue(version->requiredSet()); case SortRole: return version->rawTime(); case VersionPtrRole: return QVariant::fromValue(version); case RecommendedRole: return version->isRecommended(); diff --git a/launcher/minecraft/Component.cpp b/launcher/minecraft/Component.cpp index 7e5b6058..ff81fcbb 100644 --- a/launcher/minecraft/Component.cpp +++ b/launcher/minecraft/Component.cpp @@ -451,9 +451,9 @@ void Component::updateCachedData() m_cachedVolatile = file->m_volatile; changed = true; } - if(!deepCompare(m_cachedRequires, file->requires)) + if(!deepCompare(m_cachedRequires, file->m_requires)) { - m_cachedRequires = file->requires; + m_cachedRequires = file->m_requires; changed = true; } if(!deepCompare(m_cachedConflicts, file->conflicts)) diff --git a/launcher/minecraft/OneSixVersionFormat.cpp b/launcher/minecraft/OneSixVersionFormat.cpp index 888b6860..b586198b 100644 --- a/launcher/minecraft/OneSixVersionFormat.cpp +++ b/launcher/minecraft/OneSixVersionFormat.cpp @@ -276,7 +276,7 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc if (root.contains("requires")) { - Meta::parseRequires(root, &out->requires); + Meta::parseRequires(root, &out->m_requires); } QString dependsOnMinecraftVersion = root.value("mcVersion").toString(); if(!dependsOnMinecraftVersion.isEmpty()) @@ -284,9 +284,9 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc Meta::Require mcReq; mcReq.uid = "net.minecraft"; mcReq.equalsVersion = dependsOnMinecraftVersion; - if (out->requires.count(mcReq) == 0) + if (out->m_requires.count(mcReq) == 0) { - out->requires.insert(mcReq); + out->m_requires.insert(mcReq); } } if (root.contains("conflicts")) @@ -392,9 +392,9 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch } root.insert("mods", array); } - if(!patch->requires.empty()) + if(!patch->m_requires.empty()) { - Meta::serializeRequires(root, &patch->requires, "requires"); + Meta::serializeRequires(root, &patch->m_requires, "requires"); } if(!patch->conflicts.empty()) { diff --git a/launcher/minecraft/VersionFile.h b/launcher/minecraft/VersionFile.h index 11c5a3af..8e9dd167 100644 --- a/launcher/minecraft/VersionFile.h +++ b/launcher/minecraft/VersionFile.h @@ -138,7 +138,7 @@ public: /* data */ * Prism Launcher: set of packages this depends on * NOTE: this is shared with the meta format!!! */ - Meta::RequireSet requires; + Meta::RequireSet m_requires; /** * Prism Launcher: set of packages this conflicts with diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 96cea7b7..07e0bf23 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -352,7 +352,7 @@ QString PackInstallTask::getVersionForLoader(QString uid) if(m_version.loader.recommended || m_version.loader.latest) { for (int i = 0; i < vlist->versions().size(); i++) { auto version = vlist->versions().at(i); - auto reqs = version->requires(); + auto reqs = version->requiredSet(); // filter by minecraft version, if the loader depends on a certain version. // not all mod loaders depend on a given Minecraft version, so we won't do this diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp index f5f50cae..3d2d568a 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.cpp @@ -68,7 +68,7 @@ QString AtlUserInteractionSupportImpl::chooseVersion(Meta::VersionList::Ptr vlis // select recommended build for (int i = 0; i < vlist->versions().size(); i++) { auto version = vlist->versions().at(i); - auto reqs = version->requires(); + auto reqs = version->requiredSet(); // filter by minecraft version, if the loader depends on a certain version. if (minecraftVersion != nullptr) { -- cgit From c343036d3bfd60cb24477fcd2ae1286276236a68 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 6 Jun 2023 12:24:53 +0100 Subject: Simplify Signed-off-by: TheKodeToad --- launcher/ui/widgets/VersionSelectWidget.cpp | 29 +++++++++-------------------- launcher/ui/widgets/VersionSelectWidget.h | 1 - 2 files changed, 9 insertions(+), 21 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index 252e2719..6aaffaac 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -36,7 +36,15 @@ VersionSelectWidget::VersionSelectWidget(bool focusSearch, QWidget* parent) search->setPlaceholderText(tr("Search")); search->setClearButtonEnabled(true); verticalLayout->addWidget(search); - connect(search, &QLineEdit::textEdited, this, &VersionSelectWidget::updateSearch); + connect(search, &QLineEdit::textEdited, [this](const QString& value) { + m_proxyModel->setSearch(value); + if (!value.isEmpty() || !listView->selectionModel()->hasSelection()) { + const QModelIndex first = listView->model()->index(0, 0); + listView->selectionModel()->setCurrentIndex(first, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + listView->scrollToTop(); + } else + listView->scrollTo(listView->selectionModel()->currentIndex(), QAbstractItemView::PositionAtCenter); + }); sneakyProgressBar = new QProgressBar(this); sneakyProgressBar->setObjectName(QStringLiteral("sneakyProgressBar")); @@ -124,7 +132,6 @@ void VersionSelectWidget::loadList() loadTask->start(); } sneakyProgressBar->setHidden(false); - search->setHidden(true); } void VersionSelectWidget::onTaskSucceeded() @@ -134,13 +141,6 @@ void VersionSelectWidget::onTaskSucceeded() listView->setEmptyMode(VersionListView::String); } sneakyProgressBar->setHidden(true); - search->setHidden(false); - - if (focusSearch) - { - search->setFocus(); - focusSearch = false; - } preselect(); loadTask = nullptr; @@ -174,17 +174,6 @@ void VersionSelectWidget::preselect() selectRecommended(); } -void VersionSelectWidget::updateSearch(const QString &value) { - m_proxyModel->setSearch(value); - // if nothing is selected, pick the first result - if (!value.isEmpty()) { - listView->selectionModel()->setCurrentIndex( - listView->model()->index(0, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); - listView->scrollToTop(); - } else - listView->scrollTo(listView->selectionModel()->currentIndex(), QAbstractItemView::PositionAtCenter); -} - void VersionSelectWidget::selectCurrent() { if(m_currentVersion.isEmpty()) diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index df9c8a62..8d2c900c 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -89,7 +89,6 @@ private slots: private: void preselect(); - void updateSearch(const QString &value); private: QString m_currentVersion; -- cgit From e8843417952ae0dc881a1ef8f352e4959f2c572b Mon Sep 17 00:00:00 2001 From: Tayou Date: Tue, 6 Jun 2023 18:15:26 +0200 Subject: save meta custom url as string, not QUrl Signed-off-by: Tayou --- launcher/ui/pages/global/APIPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/pages/global/APIPage.cpp b/launcher/ui/pages/global/APIPage.cpp index f662ee1c..dca1b3a6 100644 --- a/launcher/ui/pages/global/APIPage.cpp +++ b/launcher/ui/pages/global/APIPage.cpp @@ -177,7 +177,7 @@ void APIPage::applySettings() metaURL.setScheme("https"); } - s->set("MetaURLOverride", metaURL); + s->set("MetaURLOverride", metaURL.toString()); QString flameKey = ui->flameKey->text(); s->set("FlameKeyOverride", flameKey); QString modrinthToken = ui->modrinthToken->text(); -- cgit From d59a06344a73e028a6f026d9f32027c2b9f73b39 Mon Sep 17 00:00:00 2001 From: leo78913 Date: Sun, 14 May 2023 15:03:32 -0300 Subject: fix main toolbar accounts toolbutton name previously it was not using the selected account name when opening the launcher and i also added an action group to the menu items so it uses radio buttons instead of checkboxes :p Signed-off-by: leo78913 --- launcher/ui/MainWindow.cpp | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 72b7db64..fab1185d 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -199,7 +199,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi helpMenuButton->setPopupMode(QToolButton::InstantPopup); auto accountMenuButton = dynamic_cast(ui->mainToolBar->widgetForAction(ui->actionAccountsButton)); - ui->actionAccountsButton->setMenu(ui->accountsMenu); accountMenuButton->setPopupMode(QToolButton::InstantPopup); } @@ -414,15 +413,6 @@ void MainWindow::keyReleaseEvent(QKeyEvent *event) void MainWindow::retranslateUi() { - auto accounts = APPLICATION->accounts(); - MinecraftAccountPtr defaultAccount = accounts->defaultAccount(); - if(defaultAccount) { - auto profileLabel = profileInUseFilter(defaultAccount->profileName(), defaultAccount->isInUse()); - ui->actionAccountsButton->setText(profileLabel); - } - else { - ui->actionAccountsButton->setText(tr("Accounts")); - } if (m_selectedInstance) { m_statusLeft->setText(m_selectedInstance->getStatusbarDescription()); @@ -432,6 +422,12 @@ void MainWindow::retranslateUi() ui->retranslateUi(this); + MinecraftAccountPtr defaultAccount = APPLICATION->accounts()->defaultAccount(); + if(defaultAccount) { + auto profileLabel = profileInUseFilter(defaultAccount->profileName(), defaultAccount->isInUse()); + ui->actionAccountsButton->setText(profileLabel); + } + changeIconButton->setToolTip(ui->actionChangeInstIcon->toolTip()); renameButton->setToolTip(ui->actionRenameInstance->toolTip()); @@ -673,6 +669,15 @@ void MainWindow::repopulateAccountsMenu() { ui->accountsMenu->clear(); + // NOTE: this is done so the accounts button text is not set to the accounts menu title + QMenu *accountsButtonMenu = ui->actionAccountsButton->menu(); + if (accountsButtonMenu) { + accountsButtonMenu->clear(); + } else { + accountsButtonMenu = new QMenu(this); + ui->actionAccountsButton->setMenu(accountsButtonMenu); + } + auto accounts = APPLICATION->accounts(); MinecraftAccountPtr defaultAccount = accounts->defaultAccount(); @@ -687,6 +692,8 @@ void MainWindow::repopulateAccountsMenu() } } + QActionGroup* accountsGroup = new QActionGroup(this); + if (accounts->count() <= 0) { ui->actionNoAccountsAdded->setEnabled(false); @@ -702,6 +709,7 @@ void MainWindow::repopulateAccountsMenu() QAction *action = new QAction(profileLabel, this); action->setData(i); action->setCheckable(true); + action->setActionGroup(accountsGroup); if (defaultAccount == account) { action->setChecked(true); @@ -730,6 +738,7 @@ void MainWindow::repopulateAccountsMenu() ui->actionNoDefaultAccount->setData(-1); ui->actionNoDefaultAccount->setChecked(!defaultAccount); + ui->actionNoDefaultAccount->setActionGroup(accountsGroup); ui->accountsMenu->addAction(ui->actionNoDefaultAccount); @@ -737,6 +746,8 @@ void MainWindow::repopulateAccountsMenu() ui->accountsMenu->addSeparator(); ui->accountsMenu->addAction(ui->actionManageAccounts); + + accountsButtonMenu->addActions(ui->accountsMenu->actions()); } void MainWindow::updatesAllowedChanged(bool allowed) -- cgit From a2d0d5a71d37f39535154df1e6f740625817a9eb Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Tue, 6 Jun 2023 18:25:09 +0100 Subject: Allow arrow key movement, fix auto-focus Signed-off-by: TheKodeToad --- launcher/ui/widgets/VersionSelectWidget.cpp | 29 +++++++++++++++++++++++++---- launcher/ui/widgets/VersionSelectWidget.h | 1 + 2 files changed, 26 insertions(+), 4 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/widgets/VersionSelectWidget.cpp b/launcher/ui/widgets/VersionSelectWidget.cpp index 6aaffaac..a956ddb3 100644 --- a/launcher/ui/widgets/VersionSelectWidget.cpp +++ b/launcher/ui/widgets/VersionSelectWidget.cpp @@ -1,8 +1,11 @@ #include "VersionSelectWidget.h" +#include +#include +#include +#include #include #include -#include #include "VersionProxyModel.h" @@ -45,6 +48,7 @@ VersionSelectWidget::VersionSelectWidget(bool focusSearch, QWidget* parent) } else listView->scrollTo(listView->selectionModel()->currentIndex(), QAbstractItemView::PositionAtCenter); }); + search->installEventFilter(this); sneakyProgressBar = new QProgressBar(this); sneakyProgressBar->setObjectName(QStringLiteral("sneakyProgressBar")); @@ -88,6 +92,23 @@ void VersionSelectWidget::setResizeOn(int column) listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); } +bool VersionSelectWidget::eventFilter(QObject *watched, QEvent *event) { + if (watched == search && event->type() == QEvent::KeyPress) { + const QKeyEvent* keyEvent = (QKeyEvent*)event; + const bool up = keyEvent->key() == Qt::Key_Up; + const bool down = keyEvent->key() == Qt::Key_Down; + if (up || down) { + const QModelIndex index = listView->model()->index(listView->currentIndex().row() + (up ? -1 : 1), 0); + if (index.row() >= 0 && index.row() < listView->model()->rowCount()) { + listView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + return true; + } + } + } + + return QObject::eventFilter(watched, event); +} + void VersionSelectWidget::initialize(BaseVersionList *vlist) { m_vlist = vlist; @@ -95,6 +116,9 @@ void VersionSelectWidget::initialize(BaseVersionList *vlist) listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); + if (focusSearch) + search->setFocus(); + if (!m_vlist->isLoaded()) { loadList(); @@ -105,8 +129,6 @@ void VersionSelectWidget::initialize(BaseVersionList *vlist) { listView->setEmptyMode(VersionListView::String); } - search->setFocus(); - focusSearch = false; preselect(); } } @@ -141,7 +163,6 @@ void VersionSelectWidget::onTaskSucceeded() listView->setEmptyMode(VersionListView::String); } sneakyProgressBar->setHidden(true); - preselect(); loadTask = nullptr; } diff --git a/launcher/ui/widgets/VersionSelectWidget.h b/launcher/ui/widgets/VersionSelectWidget.h index 8d2c900c..be4ba768 100644 --- a/launcher/ui/widgets/VersionSelectWidget.h +++ b/launcher/ui/widgets/VersionSelectWidget.h @@ -74,6 +74,7 @@ public: void setEmptyErrorString(QString emptyErrorString); void setEmptyMode(VersionListView::EmptyMode mode); void setResizeOn(int column); + bool eventFilter(QObject* watched, QEvent* event) override; signals: void selectedVersionChanged(BaseVersion::Ptr version); -- cgit From a807b231a75fdcb95408aa35a3143e2e5f5ca60f Mon Sep 17 00:00:00 2001 From: leo78913 Date: Tue, 6 Jun 2023 15:14:50 -0300 Subject: fix: fix crash when selecting resource/texture/shader packs Signed-off-by: leo78913 --- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 61c48e75..6d90480f 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -253,6 +253,8 @@ QList ResourcePackDownloadDialog::getPages() if (APPLICATION->capabilities() & Application::SupportsFlame) pages.append(FlameResourcePackPage::create(this, *m_instance)); + m_selectedPage = dynamic_cast(pages[0]); + return pages; } @@ -278,6 +280,8 @@ QList TexturePackDownloadDialog::getPages() if (APPLICATION->capabilities() & Application::SupportsFlame) pages.append(FlameTexturePackPage::create(this, *m_instance)); + m_selectedPage = dynamic_cast(pages[0]); + return pages; } @@ -301,6 +305,8 @@ QList ShaderPackDownloadDialog::getPages() pages.append(ModrinthShaderPackPage::create(this, *m_instance)); + m_selectedPage = dynamic_cast(pages[0]); + return pages; } -- cgit From a9302468e78c3e05ff6dd1e0bdcecea99e1a1e99 Mon Sep 17 00:00:00 2001 From: leo78913 Date: Tue, 6 Jun 2023 16:10:01 -0300 Subject: update resource and data pack pack_format_versions Signed-off-by: leo78913 --- launcher/minecraft/mod/DataPack.cpp | 4 +++- launcher/minecraft/mod/ResourcePack.cpp | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/DataPack.cpp b/launcher/minecraft/mod/DataPack.cpp index 5c58f6b2..ca75cd2a 100644 --- a/launcher/minecraft/mod/DataPack.cpp +++ b/launcher/minecraft/mod/DataPack.cpp @@ -33,7 +33,9 @@ static const QMap> s_pack_format_versions = { { 4, { Version("1.13"), Version("1.14.4") } }, { 5, { Version("1.15"), Version("1.16.1") } }, { 6, { Version("1.16.2"), Version("1.16.5") } }, { 7, { Version("1.17"), Version("1.17.1") } }, { 8, { Version("1.18"), Version("1.18.1") } }, { 9, { Version("1.18.2"), Version("1.18.2") } }, - { 10, { Version("1.19"), Version("1.19.3") } }, + { 10, { Version("1.19"), Version("1.19.3") } }, { 11, { Version("23w03a"), Version("23w05a") } }, + { 12, { Version("1.19.4"), Version("1.19.4") } }, { 13, { Version("23w12a"), Version("23w14a") } }, + { 14, { Version("23w16a"), Version("23w17a") } }, { 15, { Version("1.20"), Version("1.20") } }, }; void DataPack::setPackFormat(int new_format_id) diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp index 876d5c3e..759d2b56 100644 --- a/launcher/minecraft/mod/ResourcePack.cpp +++ b/launcher/minecraft/mod/ResourcePack.cpp @@ -18,7 +18,8 @@ static const QMap> s_pack_format_versions = { { 5, { Version("1.15"), Version("1.16.1") } }, { 6, { Version("1.16.2"), Version("1.16.5") } }, { 7, { Version("1.17"), Version("1.17.1") } }, { 8, { Version("1.18"), Version("1.18.2") } }, { 9, { Version("1.19"), Version("1.19.2") } }, { 11, { Version("22w42a"), Version("22w44a") } }, - { 12, { Version("1.19.3"), Version("1.19.3") } }, + { 12, { Version("1.19.3"), Version("1.19.3") } }, { 13, { Version("1.19.4"), Version("1.19.4") } }, + { 14, { Version("1.20"), Version("1.20") } } }; void ResourcePack::setPackFormat(int new_format_id) -- cgit From 1e702ee40f211286f85fa5353704e358e7fe14a9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 7 Jun 2023 00:16:23 +0300 Subject: Added dynamic page extra info Signed-off-by: Trial97 --- launcher/ui/pages/BasePage.h | 24 +++++++++++----------- .../ui/pages/instance/ExternalResourcesPage.cpp | 19 ++++++++++++++++- launcher/ui/pages/instance/ExternalResourcesPage.h | 1 + launcher/ui/widgets/PageContainer.cpp | 4 ++++ 4 files changed, 35 insertions(+), 13 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/BasePage.h b/launcher/ui/pages/BasePage.h index ceb24040..5537c28f 100644 --- a/launcher/ui/pages/BasePage.h +++ b/launcher/ui/pages/BasePage.h @@ -35,15 +35,16 @@ #pragma once -#include #include +#include +#include #include #include "BasePageContainer.h" -class BasePage -{ -public: +class BasePage { + public: + using updateExtraInfoFunc = std::function; virtual ~BasePage() {} virtual QString id() const = 0; virtual QString displayName() const = 0; @@ -63,17 +64,16 @@ public: } virtual void openedImpl() {} virtual void closedImpl() {} - virtual void setParentContainer(BasePageContainer * container) - { - m_container = container; - }; - virtual void retranslate() { } + virtual void setParentContainer(BasePageContainer* container) { m_container = container; }; + virtual void retranslate() {} -public: + public: int stackIndex = -1; int listIndex = -1; -protected: - BasePageContainer * m_container = nullptr; + updateExtraInfoFunc updateExtraInfo; + + protected: + BasePageContainer* m_container = nullptr; bool isOpened = false; }; diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index 1115ddc3..e5567c80 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -9,6 +9,7 @@ #include #include +#include ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared_ptr model, QWidget* parent) : QMainWindow(parent), m_instance(instance), ui(new Ui::ExternalResourcesPage), m_model(model) @@ -43,6 +44,13 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared auto selection_model = ui->treeView->selectionModel(); connect(selection_model, &QItemSelectionModel::currentChanged, this, &ExternalResourcesPage::current); + auto updateExtra = [this]() { + if (updateExtraInfo) + updateExtraInfo(extraHeaderInfoString()); + }; + connect(selection_model, &QItemSelectionModel::selectionChanged, this, updateExtra); + connect(model.get(), &ResourceFolderModel::updateFinished, this, updateExtra); + connect(ui->filterEdit, &QLineEdit::textChanged, this, &ExternalResourcesPage::filterTextChanged); } @@ -248,6 +256,15 @@ bool ExternalResourcesPage::onSelectionChanged(const QModelIndex& current, const int row = sourceCurrent.row(); Resource const& resource = m_model->at(row); ui->frame->updateWithResource(resource); - return true; } + +QString ExternalResourcesPage::extraHeaderInfoString() +{ + if (ui && ui->treeView && ui->treeView->selectionModel()) { + auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); + if (auto count = std::count_if(selection.cbegin(), selection.cend(), [](auto v) { return v.column() == 0; }); count != 0) + return tr("[%1 installed, %2 selected]").arg(m_model->size()).arg(count); + } + return tr("[%1 installed]").arg(m_model->size()); +} diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.h b/launcher/ui/pages/instance/ExternalResourcesPage.h index d17fbb7f..fd200193 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.h +++ b/launcher/ui/pages/instance/ExternalResourcesPage.h @@ -29,6 +29,7 @@ class ExternalResourcesPage : public QMainWindow, public BasePage { virtual QString helpPage() const override = 0; virtual bool shouldDisplay() const override = 0; + QString extraHeaderInfoString(); void openedImpl() override; void closedImpl() override; diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index 38a22897..34df42ec 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -93,6 +93,10 @@ PageContainer::PageContainer(BasePageProvider *pageProvider, QString defaultId, page->listIndex = counter; page->setParentContainer(this); counter++; + page->updateExtraInfo = [this](QString info) { + if (m_currentPage) + m_header->setText(m_currentPage->displayName() + info); + }; } m_model->setPages(pages); -- cgit From f724059b883d584b9f1d9ecd5fe21c7e4d214889 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 7 Jun 2023 01:23:53 +0300 Subject: Added visit mod's page Signed-off-by: Trial97 --- .../ui/pages/instance/ExternalResourcesPage.ui | 11 +++++ launcher/ui/pages/instance/ModFolderPage.cpp | 48 +++++++++++++++++----- launcher/ui/pages/instance/ModFolderPage.h | 1 + 3 files changed, 49 insertions(+), 11 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 33a03336..b110dbfd 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -154,6 +154,17 @@ Try to check or update all selected resources (all resources if none are selected)
+ + + false + + + Visit on mod's page + + + Go to mods home page + + diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 4548af59..d1787e7d 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include "Application.h" @@ -59,6 +60,7 @@ #include "minecraft/mod/Mod.h" #include "minecraft/mod/ModFolderModel.h" +#include "modplatform/ModIndex.h" #include "modplatform/ResourceAPI.h" #include "Version.h" @@ -85,22 +87,29 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionsToolbar->insertActionAfter(ui->actionAddItem, ui->actionUpdateItem); connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods); + ui->actionVisitItemPage->setToolTip(tr("Go to mods home page")); + ui->actionsToolbar->insertActionAfter(ui->actionViewFolder, ui->actionVisitItemPage); + connect(ui->actionVisitItemPage, &QAction::triggered, this, &ModFolderPage::visitModPages); + auto check_allow_update = [this] { - return (!m_instance || !m_instance->isRunning()) && - (ui->treeView->selectionModel()->hasSelection() || !m_model->empty()); + return (!m_instance || !m_instance->isRunning()) && (ui->treeView->selectionModel()->hasSelection() || !m_model->empty()); }; connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); - }); - connect(mods.get(), &ModFolderModel::rowsInserted, this, [this, check_allow_update] { - ui->actionUpdateItem->setEnabled(check_allow_update()); + auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); + auto mods_list = m_model->selectedMods(selection); + auto enableView = std::any_of(mods_list.cbegin(), mods_list.cend(), + [](Mod* v) { return v->metadata() != nullptr || v->homeurl().size() != 0; }); + ui->actionVisitItemPage->setEnabled(enableView); }); - connect(mods.get(), &ModFolderModel::rowsRemoved, this, [this, check_allow_update] { - ui->actionUpdateItem->setEnabled(check_allow_update()); - }); + connect(mods.get(), &ModFolderModel::rowsInserted, this, + [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); + + connect(mods.get(), &ModFolderModel::rowsRemoved, this, + [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); connect(mods.get(), &ModFolderModel::updateFinished, this, [this, check_allow_update, mods] { ui->actionUpdateItem->setEnabled(check_allow_update()); @@ -140,7 +149,7 @@ bool ModFolderPage::onSelectionChanged(const QModelIndex& current, const QModelI return true; } -void ModFolderPage::removeItems(const QItemSelection &selection) +void ModFolderPage::removeItems(const QItemSelection& selection) { m_model->deleteMods(selection.indexes()); } @@ -214,8 +223,7 @@ void ModFolderPage::updateMods() message = tr("All selected mods are up-to-date! :)"); } } - CustomMessageBox::selectable(this, tr("Update checker"), message) - ->exec(); + CustomMessageBox::selectable(this, tr("Update checker"), message)->exec(); return; } @@ -282,3 +290,21 @@ bool NilModFolderPage::shouldDisplay() const { return m_model->dir().exists(); } + +void ModFolderPage::visitModPages() +{ + auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); + for (auto mod : m_model->selectedMods(selection)) + if (auto meta = mod->metadata(); meta != nullptr) { + auto slug = meta->slug.remove(".pw.toml"); + switch (meta->provider) { + case ModPlatform::ResourceProvider::MODRINTH: + DesktopServices::openUrl(QString("https://modrinth.com/mod/%1").arg(slug)); + break; + case ModPlatform::ResourceProvider::FLAME: + DesktopServices::openUrl(QString("https://www.curseforge.com/minecraft/mc-mods/%1").arg(slug)); + break; + } + } else if (mod->homeurl().size() != 0) + DesktopServices::openUrl(mod->homeurl()); +} \ No newline at end of file diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h index 2fc7b574..d36a7995 100644 --- a/launcher/ui/pages/instance/ModFolderPage.h +++ b/launcher/ui/pages/instance/ModFolderPage.h @@ -64,6 +64,7 @@ class ModFolderPage : public ExternalResourcesPage { void installMods(); void updateMods(); + void visitModPages(); protected: std::shared_ptr m_model; -- cgit From e936bc4c60b4262cd70ff1eb3291dc3ead4c53ac Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 7 Jun 2023 01:38:10 +0300 Subject: Added custom text for multiple selection Signed-off-by: Trial97 --- launcher/ui/pages/instance/ModFolderPage.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index d1787e7d..1dbb9f47 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -87,7 +87,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionsToolbar->insertActionAfter(ui->actionAddItem, ui->actionUpdateItem); connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods); - ui->actionVisitItemPage->setToolTip(tr("Go to mods home page")); + ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); ui->actionsToolbar->insertActionAfter(ui->actionViewFolder, ui->actionVisitItemPage); connect(ui->actionVisitItemPage, &QAction::triggered, this, &ModFolderPage::visitModPages); @@ -100,9 +100,16 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); auto mods_list = m_model->selectedMods(selection); - auto enableView = std::any_of(mods_list.cbegin(), mods_list.cend(), + auto selected = std::count_if(mods_list.cbegin(), mods_list.cend(), [](Mod* v) { return v->metadata() != nullptr || v->homeurl().size() != 0; }); - ui->actionVisitItemPage->setEnabled(enableView); + if (selected <= 1) { + ui->actionVisitItemPage->setText(tr("Visit on mod's page")); + ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); + } else { + ui->actionVisitItemPage->setText(tr("Visit the pages of the selected mods")); + ui->actionVisitItemPage->setToolTip(tr("Go to the pages of the selected mods")); + } + ui->actionVisitItemPage->setEnabled(selected != 0); }); connect(mods.get(), &ModFolderModel::rowsInserted, this, -- cgit From d12110b47bb1bb5109e41f2cf0f20908ceb8bc10 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 7 Jun 2023 06:21:01 -0700 Subject: fix #1118 : use `filePath` not `path` on `QFileInfo` Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/InstanceCopyTask.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/InstanceCopyTask.cpp b/launcher/InstanceCopyTask.cpp index 60dcd5a1..57a3143a 100644 --- a/launcher/InstanceCopyTask.cpp +++ b/launcher/InstanceCopyTask.cpp @@ -149,7 +149,7 @@ void InstanceCopyTask::copyFinished() QByteArray allowed_symlinks; if (allowed_symlinks_file.exists()) { - allowed_symlinks.append(FS::read(allowed_symlinks_file.path())); + allowed_symlinks.append(FS::read(allowed_symlinks_file.filePath())); if (allowed_symlinks.right(1) != "\n") allowed_symlinks.append("\n"); // we want to be on a new line } @@ -157,9 +157,9 @@ void InstanceCopyTask::copyFinished() allowed_symlinks.append("\n"); if (allowed_symlinks_file.isSymLink()) FS::deletePath(allowed_symlinks_file - .path()); // we dont want to modify the original. also make sure the resulting file is not itself a link. + .filePath()); // we dont want to modify the original. also make sure the resulting file is not itself a link. - FS::write(allowed_symlinks_file.path(), allowed_symlinks); + FS::write(allowed_symlinks_file.filePath(), allowed_symlinks); } emitSucceeded(); -- cgit From 52054469cd351002143b30d5bb1d8160cdf4b085 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 7 Jun 2023 22:39:12 +0100 Subject: Fix *bug* lol Signed-off-by: TheKodeToad --- launcher/java/JavaInstallList.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index b29af857..9277203a 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -98,6 +98,8 @@ QVariant JavaInstallList::data(const QModelIndex &index, int role) const auto version = std::dynamic_pointer_cast(m_vlist[index.row()]); switch (role) { + case SortRole: + return -index.row(); case VersionPointerRole: return QVariant::fromValue(m_vlist[index.row()]); case VersionIdRole: @@ -117,7 +119,7 @@ QVariant JavaInstallList::data(const QModelIndex &index, int role) const BaseVersionList::RoleList JavaInstallList::providesRoles() const { - return {VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, ArchitectureRole}; + return {VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, LatestRole, PathRole, ArchitectureRole}; } -- cgit From 1191c33c2b40d3fdb4ee66871f8cac4eb8aaf77d Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 7 Jun 2023 22:40:36 +0100 Subject: Remove flawed implementation This seems to add the latest icon (bug) as a fallback if not provided... but it mainly seems to cause problems... :shrug: I swear I did `git add .`. Signed-off-by: TheKodeToad --- launcher/VersionProxyModel.cpp | 8 -------- launcher/java/JavaInstallList.cpp | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'launcher') diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 47cfa5ba..e5c66566 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -212,10 +212,6 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const return tr("Latest"); } } - else if(index.row() == 0) - { - return tr("Latest"); - } } } default: @@ -245,10 +241,6 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const return APPLICATION->getThemedIcon("bug"); } } - else if(index.row() == 0) - { - return APPLICATION->getThemedIcon("bug"); - } QPixmap pixmap; QPixmapCache::find("placeholder", &pixmap); if(!pixmap) diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index 9277203a..04eb2e0f 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -119,7 +119,7 @@ QVariant JavaInstallList::data(const QModelIndex &index, int role) const BaseVersionList::RoleList JavaInstallList::providesRoles() const { - return {VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, LatestRole, PathRole, ArchitectureRole}; + return {VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, ArchitectureRole}; } -- cgit From d33de2e4277dfcd090a36c96e09148ea6a5d2e55 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 8 Jun 2023 00:54:32 +0300 Subject: Made cat scalable Signed-off-by: Trial97 --- launcher/ui/MainWindow.cpp | 17 ++--------------- launcher/ui/instanceview/InstanceView.cpp | 23 ++++++++++++++++++++++- launcher/ui/instanceview/InstanceView.h | 8 ++++---- 3 files changed, 28 insertions(+), 20 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 834f57dd..4b77dd1c 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -901,21 +901,8 @@ void MainWindow::onCatToggled(bool state) void MainWindow::setCatBackground(bool enabled) { - if (enabled) { - view->setStyleSheet(QString(R"( -InstanceView -{ - background-image: url(:/backgrounds/%1); - background-attachment: fixed; - background-clip: padding; - background-position: bottom right; - background-repeat: none; - background-color:palette(base); -})") - .arg(ThemeManager::getCatImage())); - } else { - view->setStyleSheet(QString()); - } + view->setCatVisible(enabled); + view->viewport()->repaint(); } void MainWindow::runModalTask(Task *task) diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp index fbeffe35..4c83e94a 100644 --- a/launcher/ui/instanceview/InstanceView.cpp +++ b/launcher/ui/instanceview/InstanceView.cpp @@ -48,6 +48,7 @@ #include #include "VisualGroup.h" +#include "ui/themes/ThemeManager.h" #include #include @@ -73,6 +74,7 @@ InstanceView::InstanceView(QWidget *parent) setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); setAcceptDrops(true); setAutoScroll(true); + setCatVisible(APPLICATION->settings()->get("TheCat").toBool()); } InstanceView::~InstanceView() @@ -498,12 +500,31 @@ void InstanceView::mouseDoubleClickEvent(QMouseEvent *event) } } -void InstanceView::paintEvent(QPaintEvent *event) +void InstanceView::setCatVisible(bool visible) +{ + m_catVisible = visible; + m_catPixmap.load(QString(":/backgrounds/%1").arg(ThemeManager::getCatImage())); +} + +void InstanceView::paintEvent(QPaintEvent* event) { executeDelayedItemsLayout(); QPainter painter(this->viewport()); + if (m_catVisible) { + int widWidth = this->viewport()->width(); + int widHeight = this->viewport()->height(); + if (m_catPixmap.width() < widWidth) + widWidth = m_catPixmap.width(); + if (m_catPixmap.height() < widHeight) + widHeight = m_catPixmap.height(); + auto pixmap = m_catPixmap.scaled(widWidth, widHeight, Qt::KeepAspectRatio); + QRect rectOfPixmap = pixmap.rect(); + rectOfPixmap.moveBottomRight(this->viewport()->rect().bottomRight()); + painter.drawPixmap(rectOfPixmap.topLeft(), pixmap); + } + #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QStyleOptionViewItem option; initViewItemOption(&option); diff --git a/launcher/ui/instanceview/InstanceView.h b/launcher/ui/instanceview/InstanceView.h index ac338274..a9bd0bd7 100644 --- a/launcher/ui/instanceview/InstanceView.h +++ b/launcher/ui/instanceview/InstanceView.h @@ -85,10 +85,8 @@ public: virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override; - int spacing() const - { - return m_spacing; - }; + int spacing() const { return m_spacing; }; + void setCatVisible(bool visible); public slots: virtual void updateGeometries() override; @@ -139,6 +137,8 @@ private: int m_currentItemsPerRow = -1; int m_currentCursorColumn= -1; mutable QCache geometryCache; + bool m_catVisible = false; + QPixmap m_catPixmap; // point where the currently active mouse action started in geometry coordinates QPoint m_pressedPosition; -- cgit From 0b4807dc1fd723ac2f511a935649ae3a858aa388 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Wed, 7 Jun 2023 22:55:37 +0100 Subject: Questionable fix two Signed-off-by: TheKodeToad --- launcher/ui/widgets/VersionListView.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/widgets/VersionListView.cpp b/launcher/ui/widgets/VersionListView.cpp index 0e126c65..69f88155 100644 --- a/launcher/ui/widgets/VersionListView.cpp +++ b/launcher/ui/widgets/VersionListView.cpp @@ -125,14 +125,9 @@ void VersionListView::paintEvent(QPaintEvent *event) QString VersionListView::currentEmptyString() const { - if(m_itemCount) { - return QString(); - } switch(m_emptyMode) { default: - case VersionListView::Empty: - return QString(); case VersionListView::String: return m_emptyString; case VersionListView::ErrorString: -- cgit From c225ecbb557b656184f35fdd3daa3a8aaa048f1f Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 18:00:14 -0400 Subject: Add sensible defaults in AccountList.cpp Signed-off-by: PandaNinjas --- launcher/minecraft/auth/AccountList.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'launcher') diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index 9e2fd111..9069db6e 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -328,6 +328,9 @@ QVariant AccountList::data(const QModelIndex &index, int role) const case AccountState::Gone: { return tr("Gone", "Account status"); } + case default: { + return tr("Unknown", "Account status"); + } } } -- cgit From 5d425ecc025aa1fc4a5292961a5ff1b18a108885 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 18:12:46 -0400 Subject: Fix the AccountList code Signed-off-by: PandaNinjas --- launcher/minecraft/auth/AccountList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index 9069db6e..e454bcc4 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -328,7 +328,7 @@ QVariant AccountList::data(const QModelIndex &index, int role) const case AccountState::Gone: { return tr("Gone", "Account status"); } - case default: { + default: { return tr("Unknown", "Account status"); } } -- cgit From 318d11481d719cf537ecdc00f8d676494bab22b6 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 19:37:54 -0400 Subject: Resolve other switch fallthrough issues --- launcher/LaunchController.cpp | 4 +- launcher/VersionProxyModel.cpp | 100 ++++++++------------- launcher/meta/Index.cpp | 2 +- launcher/minecraft/auth/AccountList.cpp | 9 +- launcher/minecraft/auth/Yggdrasil.cpp | 1 + launcher/minecraft/mod/DataPack.cpp | 2 + launcher/minecraft/mod/Mod.cpp | 3 + launcher/minecraft/mod/Resource.cpp | 3 + launcher/minecraft/mod/ResourcePack.cpp | 2 + .../flame/FlameInstanceCreationTask.cpp | 3 +- launcher/translations/TranslationsModel.cpp | 1 + .../ui/instanceview/AccessibleInstanceView.cpp | 2 +- launcher/ui/pages/instance/WorldListPage.cpp | 1 + launcher/ui/setupwizard/JavaWizardPage.cpp | 1 + 14 files changed, 60 insertions(+), 74 deletions(-) (limited to 'launcher') diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp index 070ee283..5d84b3bf 100644 --- a/launcher/LaunchController.cpp +++ b/launcher/LaunchController.cpp @@ -187,8 +187,8 @@ void LaunchController::login() { switch(m_accountToUse->accountState()) { case AccountState::Offline: { m_session->wants_online = false; - // NOTE: fallthrough is intentional } + /* fallthrough */ case AccountState::Online: { if(!m_session->wants_online) { // we ask the user for a player name @@ -267,8 +267,8 @@ void LaunchController::login() { // This means some sort of soft error that we can fix with a refresh ... so let's refresh. case AccountState::Unchecked: { m_accountToUse->refresh(); - // NOTE: fallthrough intentional } + /* fallthrough */ case AccountState::Working: { // refresh is in progress, we need to wait for it to finish to proceed. ProgressDialog progDialog(m_parentWidget); diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 6aba268d..3c294873 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -185,80 +185,50 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const return QVariant(); } } - case Qt::ToolTipRole: - { - switch(column) - { - case Name: - { - if(hasRecommended) + case Qt::ToolTipRole: { + if (column == Name && hasRecommended) { + auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if(value.toBool()) { + return tr("Recommended"); + } + else if(hasLatest) { + auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); + if(value.toBool()) { - auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) - { - return tr("Recommended"); - } - else if(hasLatest) - { - auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) - { - return tr("Latest"); - } - } - else if(index.row() == 0) - { - return tr("Latest"); - } + return tr("Latest"); } } - default: - { - return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole); + else if(index.row() == 0) { + return tr("Latest"); } } + return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole); } - case Qt::DecorationRole: - { - switch(column) - { - case Name: - { - if(hasRecommended) - { - auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) - { - return APPLICATION->getThemedIcon("star"); - } - else if(hasLatest) - { - auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) - { - return APPLICATION->getThemedIcon("bug"); - } - } - else if(index.row() == 0) - { - return APPLICATION->getThemedIcon("bug"); - } - QPixmap pixmap; - QPixmapCache::find("placeholder", &pixmap); - if(!pixmap) - { - QPixmap px(16,16); - px.fill(Qt::transparent); - QPixmapCache::insert("placeholder", px); - return px; - } - return pixmap; + case Qt::DecorationRole: { + if (column == Name && hasRecommended) { + auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if(value.toBool()) { + return APPLICATION->getThemedIcon("star"); + } else if(hasLatest) { + auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); + if(value.toBool()) { + return APPLICATION->getThemedIcon("bug"); } } - default: - { - return QVariant(); + else if(index.row() == 0) { + return APPLICATION->getThemedIcon("bug"); + } + QPixmap pixmap; + QPixmapCache::find("placeholder", &pixmap); + if(!pixmap) { + QPixmap px(16,16); + px.fill(Qt::transparent); + QPixmapCache::insert("placeholder", px); + return px; } + return pixmap; + } else { + return QVariant(); } } default: diff --git a/launcher/meta/Index.cpp b/launcher/meta/Index.cpp index 242aad9f..2902f290 100644 --- a/launcher/meta/Index.cpp +++ b/launcher/meta/Index.cpp @@ -48,8 +48,8 @@ QVariant Index::data(const QModelIndex &index, int role) const switch (index.column()) { case 0: return list->humanReadable(); - default: break; } + break; case UidRole: return list->uid(); case NameRole: return list->name(); case ListPtrRole: return QVariant::fromValue(list); diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index e454bcc4..184f8e10 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -357,11 +357,12 @@ QVariant AccountList::data(const QModelIndex &index, int role) const return QVariant::fromValue(account); case Qt::CheckStateRole: - switch (index.column()) - { - case ProfileNameColumn: - return account == m_defaultAccount ? Qt::Checked : Qt::Unchecked; + if (index.column() == ProfileNameColumn) { + return account == m_defaultAccount ? Qt::Checked : Qt::Unchecked; + } else { + return QVariant(); } + default: return QVariant(); diff --git a/launcher/minecraft/auth/Yggdrasil.cpp b/launcher/minecraft/auth/Yggdrasil.cpp index 29978411..d3e7ccdd 100644 --- a/launcher/minecraft/auth/Yggdrasil.cpp +++ b/launcher/minecraft/auth/Yggdrasil.cpp @@ -273,6 +273,7 @@ void Yggdrasil::processReply() { AccountTaskState::STATE_FAILED_GONE, tr("The Mojang account no longer exists. It may have been migrated to a Microsoft account.") ); + return; } default: changeState( diff --git a/launcher/minecraft/mod/DataPack.cpp b/launcher/minecraft/mod/DataPack.cpp index ca75cd2a..c5754638 100644 --- a/launcher/minecraft/mod/DataPack.cpp +++ b/launcher/minecraft/mod/DataPack.cpp @@ -74,6 +74,7 @@ std::pair DataPack::compare(const Resource& other, SortType type) con auto res = Resource::compare(other, type); if (res.first != 0) return res; + break; } case SortType::PACK_FORMAT: { auto this_ver = packFormat(); @@ -83,6 +84,7 @@ std::pair DataPack::compare(const Resource& other, SortType type) con return { 1, type == SortType::PACK_FORMAT }; if (this_ver < other_ver) return { -1, type == SortType::PACK_FORMAT }; + break; } } return { 0, false }; diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index c495cd47..6cda6185 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -89,6 +89,7 @@ std::pair Mod::compare(const Resource& other, SortType type) const auto res = Resource::compare(other, type); if (res.first != 0) return res; + break; } case SortType::VERSION: { auto this_ver = Version(version()); @@ -97,11 +98,13 @@ std::pair Mod::compare(const Resource& other, SortType type) const return { 1, type == SortType::VERSION }; if (this_ver < other_ver) return { -1, type == SortType::VERSION }; + break; } case SortType::PROVIDER: { auto compare_result = QString::compare(provider().value_or("Unknown"), cast_other->provider().value_or("Unknown"), Qt::CaseInsensitive); if (compare_result != 0) return { compare_result, type == SortType::PROVIDER }; + break; } } return { 0, false }; diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index a0b8a4bb..e5077260 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -71,6 +71,7 @@ std::pair Resource::compare(const Resource& other, SortType type) con return { 1, type == SortType::ENABLED }; if (!enabled() && other.enabled()) return { -1, type == SortType::ENABLED }; + break; case SortType::NAME: { QString this_name{ name() }; QString other_name{ other.name() }; @@ -81,12 +82,14 @@ std::pair Resource::compare(const Resource& other, SortType type) con auto compare_result = QString::compare(this_name, other_name, Qt::CaseInsensitive); if (compare_result != 0) return { compare_result, type == SortType::NAME }; + break; } case SortType::DATE: if (dateTimeChanged() > other.dateTimeChanged()) return { 1, type == SortType::DATE }; if (dateTimeChanged() < other.dateTimeChanged()) return { -1, type == SortType::DATE }; + break; } return { 0, false }; diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp index 759d2b56..32a789f5 100644 --- a/launcher/minecraft/mod/ResourcePack.cpp +++ b/launcher/minecraft/mod/ResourcePack.cpp @@ -95,6 +95,7 @@ std::pair ResourcePack::compare(const Resource& other, SortType type) auto res = Resource::compare(other, type); if (res.first != 0) return res; + break; } case SortType::PACK_FORMAT: { auto this_ver = packFormat(); @@ -104,6 +105,7 @@ std::pair ResourcePack::compare(const Resource& other, SortType type) return { 1, type == SortType::PACK_FORMAT }; if (this_ver < other_ver) return { -1, type == SortType::PACK_FORMAT }; + break; } } return { 0, false }; diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index dae93d1c..11365a21 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -467,8 +467,9 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop) switch (result.type) { case Flame::File::Type::Folder: { logWarning(tr("This 'Folder' may need extracting: %1").arg(relpath)); - // fall-through intentional, we treat these as plain old mods and dump them wherever. + // fallthrough intentional, we treat these as plain old mods and dump them wherever. } + /* fallthrough */ case Flame::File::Type::SingleFile: case Flame::File::Type::Mod: { if (!result.url.isEmpty()) { diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp index 23e55c51..489dff86 100644 --- a/launcher/translations/TranslationsModel.cpp +++ b/launcher/translations/TranslationsModel.cpp @@ -454,6 +454,7 @@ QVariant TranslationsModel::data(const QModelIndex& index, int role) const return QString("%1%").arg(lang.percentTranslated(), 3, 'f', 1); } } + qWarning("TranslationModel::data not implemented when role is DisplayRole"); } case Qt::ToolTipRole: { diff --git a/launcher/ui/instanceview/AccessibleInstanceView.cpp b/launcher/ui/instanceview/AccessibleInstanceView.cpp index 7de3ac72..2e7b8300 100644 --- a/launcher/ui/instanceview/AccessibleInstanceView.cpp +++ b/launcher/ui/instanceview/AccessibleInstanceView.cpp @@ -248,8 +248,8 @@ bool AccessibleInstanceView::selectColumn(int column) if (view()->selectionBehavior() != QAbstractItemView::SelectColumns && rowCount() > 1) { return false; } - // fallthrough intentional } + /* fallthrough */ case QAbstractItemView::ContiguousSelection: { if ((!column || !view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex())) && !view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) { view()->clearSelection(); diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index b6ad159e..b5dc5a17 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -338,6 +338,7 @@ void WorldListPage::mceditState(LoggedProcess::State state) case LoggedProcess::Aborted: { failed = true; + break; } case LoggedProcess::Running: case LoggedProcess::Finished: diff --git a/launcher/ui/setupwizard/JavaWizardPage.cpp b/launcher/ui/setupwizard/JavaWizardPage.cpp index 14683778..e8833535 100644 --- a/launcher/ui/setupwizard/JavaWizardPage.cpp +++ b/launcher/ui/setupwizard/JavaWizardPage.cpp @@ -69,6 +69,7 @@ bool JavaWizardPage::validatePage() case JavaSettingsWidget::ValidationStatus::AllOK: { settings->set("JavaPath", m_java_widget->javaPath()); + break; } case JavaSettingsWidget::ValidationStatus::JavaBad: { -- cgit From 534328f16d0322c937a690f2f15eaa81489a54fe Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 19:45:23 -0400 Subject: Remove unnecessary switch statement Signed-off-by: PandaNinjas DCO Remediation Commit for PandaNinjas I, PandaNinjas , hereby add my Signed-off-by to this commit: 318d11481d719cf537ecdc00f8d676494bab22b6 Signed-off-by: PandaNinjas --- launcher/meta/Index.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'launcher') diff --git a/launcher/meta/Index.cpp b/launcher/meta/Index.cpp index 2902f290..0c6ecccf 100644 --- a/launcher/meta/Index.cpp +++ b/launcher/meta/Index.cpp @@ -45,11 +45,11 @@ QVariant Index::data(const QModelIndex &index, int role) const switch (role) { case Qt::DisplayRole: - switch (index.column()) - { - case 0: return list->humanReadable(); + if (list.column() == 0) { + return list->humanReadable(); + } else { + break; } - break; case UidRole: return list->uid(); case NameRole: return list->name(); case ListPtrRole: return QVariant::fromValue(list); -- cgit From 886b372adef86d84ca50d2e3e5b7ac39f1a5a42e Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 20:03:36 -0400 Subject: Fix accidentally renamed variable Signed-off-by: PandaNinjas --- launcher/meta/Index.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/meta/Index.cpp b/launcher/meta/Index.cpp index 0c6ecccf..4dccccca 100644 --- a/launcher/meta/Index.cpp +++ b/launcher/meta/Index.cpp @@ -45,7 +45,7 @@ QVariant Index::data(const QModelIndex &index, int role) const switch (role) { case Qt::DisplayRole: - if (list.column() == 0) { + if (index.column() == 0) { return list->humanReadable(); } else { break; -- cgit From 11cbeb8f96b9e6bc86290581128e28554123a427 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 22:13:57 -0400 Subject: Fix shadowing and add copyright header Signed-off-by: PandaNinjas --- launcher/VersionProxyModel.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'launcher') diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 3c294873..15ae1cc3 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu - * * 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. @@ -187,13 +187,13 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const } case Qt::ToolTipRole: { if (column == Name && hasRecommended) { - auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) { + auto recommendedValue = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if(recommendedValue.toBool()) { return tr("Recommended"); } else if(hasLatest) { - auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) + auto latestValue = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); + if(latestValue.toBool()) { return tr("Latest"); } @@ -206,12 +206,12 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const } case Qt::DecorationRole: { if (column == Name && hasRecommended) { - auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) { + auto recommendedValue = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if(recommendedValue.toBool()) { return APPLICATION->getThemedIcon("star"); } else if(hasLatest) { - auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) { + auto latestValue = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); + if(latestValue.toBool()) { return APPLICATION->getThemedIcon("bug"); } } -- cgit From e6872aba75231d409b19da5b876bb518b24976cc Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Wed, 7 Jun 2023 22:15:44 -0400 Subject: Readd deleted line Signed-off-by: PandaNinjas --- launcher/VersionProxyModel.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'launcher') diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 15ae1cc3..aca7ef00 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -3,6 +3,7 @@ * PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * * 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. -- cgit From 95f6860005341ebf81a7bed60a4e267f3057d2a6 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Thu, 8 Jun 2023 10:12:27 -0400 Subject: Apply suggestions from code review Signed-off-by: PandaNinjas --- launcher/VersionProxyModel.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'launcher') diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index aca7ef00..0dbd1c95 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -1,6 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu * -- cgit From f96b135ef72a762220941681cf1b314a3b2db266 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 8 Jun 2023 20:26:09 +0300 Subject: Higlight installed mods Signed-off-by: Trial97 --- launcher/minecraft/MinecraftInstance.cpp | 40 +++++++++------------- launcher/minecraft/MinecraftInstance.h | 16 ++++----- launcher/minecraft/WorldList.cpp | 3 +- launcher/minecraft/WorldList.h | 4 +-- launcher/minecraft/mod/ModFolderModel.cpp | 2 +- launcher/minecraft/mod/ModFolderModel.h | 2 +- launcher/minecraft/mod/ResourceFolderModel.cpp | 2 +- launcher/minecraft/mod/ResourceFolderModel.h | 4 +-- launcher/minecraft/mod/ResourcePackFolderModel.cpp | 2 +- launcher/minecraft/mod/ResourcePackFolderModel.h | 2 +- launcher/minecraft/mod/ShaderPackFolderModel.h | 4 +-- launcher/minecraft/mod/TexturePackFolderModel.cpp | 3 +- launcher/minecraft/mod/TexturePackFolderModel.h | 4 +-- launcher/ui/pages/modplatform/ModModel.cpp | 12 +++++++ launcher/ui/pages/modplatform/ModModel.h | 1 + launcher/ui/pages/modplatform/ResourceModel.cpp | 3 ++ launcher/ui/pages/modplatform/ResourceModel.h | 2 ++ launcher/ui/pages/modplatform/flame/FlameModel.cpp | 2 ++ .../pages/modplatform/modrinth/ModrinthModel.cpp | 2 ++ launcher/ui/widgets/ProjectItem.cpp | 5 +++ launcher/ui/widgets/ProjectItem.h | 3 +- 21 files changed, 67 insertions(+), 51 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 2c624a36..76ff5723 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -1109,10 +1109,9 @@ JavaVersion MinecraftInstance::getJavaVersion() return JavaVersion(settings()->get("JavaVersion").toString()); } -std::shared_ptr MinecraftInstance::loaderModList() +std::shared_ptr MinecraftInstance::loaderModList() const { - if (!m_loader_mod_list) - { + if (!m_loader_mod_list) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_loader_mod_list.reset(new ModFolderModel(modsRoot(), this, is_indexed)); m_loader_mod_list->disableInteraction(isRunning()); @@ -1121,10 +1120,9 @@ std::shared_ptr MinecraftInstance::loaderModList() return m_loader_mod_list; } -std::shared_ptr MinecraftInstance::coreModList() +std::shared_ptr MinecraftInstance::coreModList() const { - if (!m_core_mod_list) - { + if (!m_core_mod_list) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_core_mod_list.reset(new ModFolderModel(coreModsDir(), this, is_indexed)); m_core_mod_list->disableInteraction(isRunning()); @@ -1133,10 +1131,9 @@ std::shared_ptr MinecraftInstance::coreModList() return m_core_mod_list; } -std::shared_ptr MinecraftInstance::nilModList() +std::shared_ptr MinecraftInstance::nilModList() const { - if (!m_nil_mod_list) - { + if (!m_nil_mod_list) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_nil_mod_list.reset(new ModFolderModel(nilModsDir(), this, is_indexed, false)); m_nil_mod_list->disableInteraction(isRunning()); @@ -1145,46 +1142,41 @@ std::shared_ptr MinecraftInstance::nilModList() return m_nil_mod_list; } -std::shared_ptr MinecraftInstance::resourcePackList() +std::shared_ptr MinecraftInstance::resourcePackList() const { - if (!m_resource_pack_list) - { + if (!m_resource_pack_list) { m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir(), this)); } return m_resource_pack_list; } -std::shared_ptr MinecraftInstance::texturePackList() +std::shared_ptr MinecraftInstance::texturePackList() const { - if (!m_texture_pack_list) - { + if (!m_texture_pack_list) { m_texture_pack_list.reset(new TexturePackFolderModel(texturePacksDir(), this)); } return m_texture_pack_list; } -std::shared_ptr MinecraftInstance::shaderPackList() +std::shared_ptr MinecraftInstance::shaderPackList() const { - if (!m_shader_pack_list) - { + if (!m_shader_pack_list) { m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir(), this)); } return m_shader_pack_list; } -std::shared_ptr MinecraftInstance::worldList() +std::shared_ptr MinecraftInstance::worldList() const { - if (!m_world_list) - { + if (!m_world_list) { m_world_list.reset(new WorldList(worldDir(), this)); } return m_world_list; } -std::shared_ptr MinecraftInstance::gameOptionsModel() +std::shared_ptr MinecraftInstance::gameOptionsModel() const { - if (!m_game_options) - { + if (!m_game_options) { m_game_options.reset(new GameOptions(FS::PathCombine(gameRoot(), "options.txt"))); } return m_game_options; diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index 068b3008..a75fa481 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -115,14 +115,14 @@ public: std::shared_ptr getPackProfile() const; ////// Mod Lists ////// - std::shared_ptr loaderModList(); - std::shared_ptr coreModList(); - std::shared_ptr nilModList(); - std::shared_ptr resourcePackList(); - std::shared_ptr texturePackList(); - std::shared_ptr shaderPackList(); - std::shared_ptr worldList(); - std::shared_ptr gameOptionsModel(); + std::shared_ptr loaderModList() const; + std::shared_ptr coreModList() const; + std::shared_ptr nilModList() const; + std::shared_ptr resourcePackList() const; + std::shared_ptr texturePackList() const; + std::shared_ptr shaderPackList() const; + std::shared_ptr worldList() const; + std::shared_ptr gameOptionsModel() const; ////// Launch stuff ////// Task::Ptr createUpdateTask(Net::Mode mode) override; diff --git a/launcher/minecraft/WorldList.cpp b/launcher/minecraft/WorldList.cpp index 0feee299..42772df5 100644 --- a/launcher/minecraft/WorldList.cpp +++ b/launcher/minecraft/WorldList.cpp @@ -45,8 +45,7 @@ #include #include -WorldList::WorldList(const QString &dir, BaseInstance* instance) - : QAbstractListModel(), m_instance(instance), m_dir(dir) +WorldList::WorldList(const QString& dir, const BaseInstance* instance) : QAbstractListModel(), m_instance(instance), m_dir(dir) { FS::ensureFolderPathExists(m_dir.absolutePath()); m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs); diff --git a/launcher/minecraft/WorldList.h b/launcher/minecraft/WorldList.h index 96b64193..92d02b9b 100644 --- a/launcher/minecraft/WorldList.h +++ b/launcher/minecraft/WorldList.h @@ -50,7 +50,7 @@ public: IconFileRole }; - WorldList(const QString &dir, BaseInstance* instance); + WorldList(const QString& dir, const BaseInstance* instance); virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; @@ -128,7 +128,7 @@ signals: void changed(); protected: - BaseInstance* m_instance; + const BaseInstance* m_instance; QFileSystemWatcher *m_watcher; bool is_watching; QDir m_dir; diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 5e3b31e0..eccfe4ae 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -54,7 +54,7 @@ #include "minecraft/mod/tasks/ModFolderLoadTask.h" #include "modplatform/ModIndex.h" -ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool is_indexed, bool create_dir) +ModFolderModel::ModFolderModel(const QString& dir, const BaseInstance* instance, bool is_indexed, bool create_dir) : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed) { m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER }; diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index d337fe29..261a007a 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -75,7 +75,7 @@ public: Enable, Toggle }; - ModFolderModel(const QString &dir, BaseInstance* instance, bool is_indexed = false, bool create_dir = true); + ModFolderModel(const QString& dir, const BaseInstance* instance, bool is_indexed = false, bool create_dir = true); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index d2d875e4..5664ea85 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -16,7 +16,7 @@ #include "tasks/Task.h" -ResourceFolderModel::ResourceFolderModel(QDir dir, BaseInstance* instance, QObject* parent, bool create_dir) +ResourceFolderModel::ResourceFolderModel(QDir dir, const BaseInstance* instance, QObject* parent, bool create_dir) : QAbstractListModel(parent), m_dir(dir), m_instance(instance), m_watcher(this) { if (create_dir) { diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 0a35e1bc..d853b443 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -26,7 +26,7 @@ class QSortFilterProxyModel; class ResourceFolderModel : public QAbstractListModel { Q_OBJECT public: - ResourceFolderModel(QDir, BaseInstance* instance, QObject* parent = nullptr, bool create_dir = true); + ResourceFolderModel(QDir, const BaseInstance* instance, QObject* parent = nullptr, bool create_dir = true); ~ResourceFolderModel() override; /** Starts watching the paths for changes. @@ -191,7 +191,7 @@ class ResourceFolderModel : public QAbstractListModel { bool m_can_interact = true; QDir m_dir; - BaseInstance* m_instance; + const BaseInstance* m_instance; QFileSystemWatcher m_watcher; bool m_is_watching = false; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index c12d1f23..8036292b 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -45,7 +45,7 @@ #include "minecraft/mod/tasks/BasicFolderLoadTask.h" #include "minecraft/mod/tasks/LocalResourcePackParseTask.h" -ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstance* instance) +ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, const BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) { m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE }; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.h b/launcher/minecraft/mod/ResourcePackFolderModel.h index db4b14fb..9d96253a 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.h +++ b/launcher/minecraft/mod/ResourcePackFolderModel.h @@ -17,7 +17,7 @@ public: NUM_COLUMNS }; - explicit ResourcePackFolderModel(const QString &dir, BaseInstance* instance); + explicit ResourcePackFolderModel(const QString& dir, const BaseInstance* instance); [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; diff --git a/launcher/minecraft/mod/ShaderPackFolderModel.h b/launcher/minecraft/mod/ShaderPackFolderModel.h index dc5acf80..c05bec1d 100644 --- a/launcher/minecraft/mod/ShaderPackFolderModel.h +++ b/launcher/minecraft/mod/ShaderPackFolderModel.h @@ -6,7 +6,5 @@ class ShaderPackFolderModel : public ResourceFolderModel { Q_OBJECT public: - explicit ShaderPackFolderModel(const QString& dir, BaseInstance* instance) - : ResourceFolderModel(QDir(dir), instance) - {} + explicit ShaderPackFolderModel(const QString& dir, const BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) {} }; diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index c6609ed1..dadf8f77 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -39,8 +39,7 @@ #include "minecraft/mod/tasks/BasicFolderLoadTask.h" #include "minecraft/mod/tasks/LocalTexturePackParseTask.h" -TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance* instance) - : ResourceFolderModel(QDir(dir), instance) +TexturePackFolderModel::TexturePackFolderModel(const QString& dir, const BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) {} Task* TexturePackFolderModel::createUpdateTask() diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h index 425a71e4..a1492f8b 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.h +++ b/launcher/minecraft/mod/TexturePackFolderModel.h @@ -42,8 +42,8 @@ class TexturePackFolderModel : public ResourceFolderModel { Q_OBJECT -public: - explicit TexturePackFolderModel(const QString &dir, BaseInstance* instance); + public: + explicit TexturePackFolderModel(const QString& dir, const BaseInstance* instance); [[nodiscard]] Task* createUpdateTask() override; [[nodiscard]] Task* createParseTask(Resource&) override; }; diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index afd8b292..1579bbf4 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -6,8 +6,10 @@ #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" +#include "minecraft/mod/ModFolderModel.h" #include +#include namespace ResourceDownload { @@ -67,4 +69,14 @@ void ModModel::searchWithTerm(const QString& term, unsigned int sort, bool filte refresh(); } +bool ModModel::isPackInstalled(ModPlatform::IndexedPack::Ptr pack) const +{ + auto allMods = static_cast(m_base_instance).loaderModList()->allMods(); + return std::any_of(allMods.cbegin(), allMods.cend(), [pack](Mod* mod) { + if (auto meta = mod->metadata(); meta) + return meta->provider == pack->provider && meta->project_id == pack->addonId; + return false; + }); +} + } // namespace ResourceDownload diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index 5d4a7785..938ce32e 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -42,6 +42,7 @@ class ModModel : public ResourceModel { protected: auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0; + virtual bool isPackInstalled(ModPlatform::IndexedPack::Ptr) const override; protected: const BaseInstance& m_base_instance; diff --git a/launcher/ui/pages/modplatform/ResourceModel.cpp b/launcher/ui/pages/modplatform/ResourceModel.cpp index a5ea1ca9..49405a02 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.cpp +++ b/launcher/ui/pages/modplatform/ResourceModel.cpp @@ -77,6 +77,8 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant return pack->description; case UserDataTypes::SELECTED: return pack->isAnyVersionSelected(); + case UserDataTypes::INSTALLED: + return this->isPackInstalled(pack); default: break; } @@ -95,6 +97,7 @@ QHash ResourceModel::roleNames() const roles[UserDataTypes::TITLE] = "title"; roles[UserDataTypes::DESCRIPTION] = "description"; roles[UserDataTypes::SELECTED] = "selected"; + roles[UserDataTypes::INSTALLED] = "installed"; return roles; } diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h index 69e23473..6533d9c6 100644 --- a/launcher/ui/pages/modplatform/ResourceModel.h +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -116,6 +116,8 @@ class ResourceModel : public QAbstractListModel { virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&); virtual void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&); + virtual bool isPackInstalled(ModPlatform::IndexedPack::Ptr) const { return false; } + protected: /* Basic search parameters */ enum class SearchState { None, CanFetchMore, ResetRequested, Finished } m_search_state = SearchState::None; diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index 5961ea02..d9d5ef5b 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -60,6 +60,8 @@ QVariant ListModel::data(const QModelIndex& index, int role) const return pack.description; case UserDataTypes::SELECTED: return false; + case UserDataTypes::INSTALLED: + return false; default: break; } diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 346a00b0..55d287b0 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -106,6 +106,8 @@ auto ModpackListModel::data(const QModelIndex& index, int role) const -> QVarian return pack.description; case UserDataTypes::SELECTED: return false; + case UserDataTypes::INSTALLED: + return false; default: break; } diff --git a/launcher/ui/widgets/ProjectItem.cpp b/launcher/ui/widgets/ProjectItem.cpp index d1ff9dbc..e8349c10 100644 --- a/launcher/ui/widgets/ProjectItem.cpp +++ b/launcher/ui/widgets/ProjectItem.cpp @@ -64,6 +64,11 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o font.setBold(true); font.setUnderline(true); } + if (index.data(UserDataTypes::INSTALLED).toBool()) { + // Set nice font + font.setItalic(true); + font.setOverline(true); + } font.setPointSize(font.pointSize() + 2); painter->setFont(font); diff --git a/launcher/ui/widgets/ProjectItem.h b/launcher/ui/widgets/ProjectItem.h index f668edf6..196055ea 100644 --- a/launcher/ui/widgets/ProjectItem.h +++ b/launcher/ui/widgets/ProjectItem.h @@ -6,7 +6,8 @@ enum UserDataTypes { TITLE = 257, // QString DESCRIPTION = 258, // QString - SELECTED = 259 // bool + SELECTED = 259, // bool + INSTALLED = 260 // bool }; /** This is an item delegate composed of: -- cgit From f2932c6d0387c41bd876d4af4148a7ffb5c83154 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 9 Jun 2023 21:23:41 +0300 Subject: Fixed some crashes Signed-off-by: Trial97 --- launcher/net/ByteArraySink.h | 15 ++++++++++++--- launcher/tasks/ConcurrentTask.cpp | 3 +-- launcher/ui/pages/modplatform/ResourcePage.cpp | 9 ++++++--- 3 files changed, 19 insertions(+), 8 deletions(-) (limited to 'launcher') diff --git a/launcher/net/ByteArraySink.h b/launcher/net/ByteArraySink.h index 501318a1..0d77727e 100644 --- a/launcher/net/ByteArraySink.h +++ b/launcher/net/ByteArraySink.h @@ -53,7 +53,10 @@ class ByteArraySink : public Sink { public: auto init(QNetworkRequest& request) -> Task::State override { - m_output->clear(); + if (m_output) + m_output->clear(); + else + qWarning() << "ByteArraySink was not cleared because it's not adresable"; if (initAllValidators(request)) return Task::State::Running; return Task::State::Failed; @@ -61,7 +64,10 @@ class ByteArraySink : public Sink { auto write(QByteArray& data) -> Task::State override { - m_output->append(data); + if (m_output) + m_output->append(data); + else + qWarning() << "ByteArraySink no write because it's not adresable"; if (writeAllValidators(data)) return Task::State::Running; return Task::State::Failed; @@ -69,7 +75,10 @@ class ByteArraySink : public Sink { auto abort() -> Task::State override { - m_output->clear(); + if (m_output) + m_output->clear(); + else + qWarning() << "ByteArraySink no clear because it's not adresable"; failAllValidators(); return Task::State::Failed; } diff --git a/launcher/tasks/ConcurrentTask.cpp b/launcher/tasks/ConcurrentTask.cpp index 5ee14505..9aada5e6 100644 --- a/launcher/tasks/ConcurrentTask.cpp +++ b/launcher/tasks/ConcurrentTask.cpp @@ -138,19 +138,18 @@ void ConcurrentTask::startNext() connect(next.get(), &Task::progress, this, [this, next](qint64 current, qint64 total) { subTaskProgress(next, current, total); }); m_doing.insert(next.get(), next); + qsizetype num_starts = qMin(m_queue.size(), m_total_max_size - m_doing.size()); auto task_progress = std::make_shared(next->getUid()); m_task_progress.insert(next->getUid(), task_progress); updateState(); updateStepProgress(*task_progress.get(), Operation::ADDED); - QCoreApplication::processEvents(); QMetaObject::invokeMethod(next.get(), &Task::start, Qt::QueuedConnection); // Allow going up the number of concurrent tasks in case of tasks being added in the middle of a running task. - int num_starts = qMin(m_queue.size(), m_total_max_size - m_doing.size()); for (int i = 0; i < num_starts; i++) QMetaObject::invokeMethod(this, &ConcurrentTask::startNext, Qt::QueuedConnection); } diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 736034ad..2bb86777 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -240,10 +240,13 @@ void ResourcePage::updateSelectionButton() } m_ui->resourceSelectionButton->setEnabled(true); - if (!getCurrentPack()->isVersionSelected(m_selected_version_index)) { - m_ui->resourceSelectionButton->setText(tr("Select %1 for download").arg(resourceString())); + if (getCurrentPack()) { + if (!getCurrentPack()->isVersionSelected(m_selected_version_index)) + m_ui->resourceSelectionButton->setText(tr("Select %1 for download").arg(resourceString())); + else + m_ui->resourceSelectionButton->setText(tr("Deselect %1 for download").arg(resourceString())); } else { - m_ui->resourceSelectionButton->setText(tr("Deselect %1 for download").arg(resourceString())); + qWarning() << "Try to update selection but there is not a pack selected"; } } -- cgit From b3d743635c86aac583fb802c1e3c7aa25e12dc88 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 9 Jun 2023 21:29:12 +0300 Subject: Updated the messages Signed-off-by: Trial97 --- launcher/net/ByteArraySink.h | 6 +++--- launcher/ui/pages/modplatform/ResourcePage.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'launcher') diff --git a/launcher/net/ByteArraySink.h b/launcher/net/ByteArraySink.h index 0d77727e..728193b3 100644 --- a/launcher/net/ByteArraySink.h +++ b/launcher/net/ByteArraySink.h @@ -56,7 +56,7 @@ class ByteArraySink : public Sink { if (m_output) m_output->clear(); else - qWarning() << "ByteArraySink was not cleared because it's not adresable"; + qWarning() << "ByteArraySink did not initialize the buffer because it's not addressable"; if (initAllValidators(request)) return Task::State::Running; return Task::State::Failed; @@ -67,7 +67,7 @@ class ByteArraySink : public Sink { if (m_output) m_output->append(data); else - qWarning() << "ByteArraySink no write because it's not adresable"; + qWarning() << "ByteArraySink did not write the buffer because it's not addressable"; if (writeAllValidators(data)) return Task::State::Running; return Task::State::Failed; @@ -78,7 +78,7 @@ class ByteArraySink : public Sink { if (m_output) m_output->clear(); else - qWarning() << "ByteArraySink no clear because it's not adresable"; + qWarning() << "ByteArraySink did not clear the buffer because it's not addressable"; failAllValidators(); return Task::State::Failed; } diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 2bb86777..1d2509d8 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -246,7 +246,7 @@ void ResourcePage::updateSelectionButton() else m_ui->resourceSelectionButton->setText(tr("Deselect %1 for download").arg(resourceString())); } else { - qWarning() << "Try to update selection but there is not a pack selected"; + qWarning() << "Tried to update the selected button but there is not a pack selected"; } } -- cgit From b7d82354cbf4d13c428555c5625db183dffd15d7 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 10 Jun 2023 14:42:27 +0100 Subject: [ci skip] License headers!! (yay) Signed-off-by: TheKodeToad --- launcher/java/JavaInstallList.cpp | 3 ++- launcher/ui/widgets/VersionListView.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp index 04eb2e0f..3407fdf7 100644 --- a/launcher/java/JavaInstallList.cpp +++ b/launcher/java/JavaInstallList.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/launcher/ui/widgets/VersionListView.cpp b/launcher/ui/widgets/VersionListView.cpp index 69f88155..06e58d22 100644 --- a/launcher/ui/widgets/VersionListView.cpp +++ b/launcher/ui/widgets/VersionListView.cpp @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2023 TheKodeToad * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- cgit From ae9e8dbafd457ef5be2b02529647c8b974488f7a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 10 Jun 2023 22:04:08 +0300 Subject: Removed const specification Signed-off-by: Trial97 --- launcher/minecraft/MinecraftInstance.cpp | 40 +++++++++++++--------- launcher/minecraft/MinecraftInstance.h | 16 ++++----- launcher/minecraft/WorldList.cpp | 3 +- launcher/minecraft/WorldList.h | 4 +-- launcher/minecraft/mod/ModFolderModel.cpp | 2 +- launcher/minecraft/mod/ModFolderModel.h | 2 +- launcher/minecraft/mod/ResourceFolderModel.cpp | 2 +- launcher/minecraft/mod/ResourceFolderModel.h | 4 +-- launcher/minecraft/mod/ResourcePackFolderModel.cpp | 2 +- launcher/minecraft/mod/ResourcePackFolderModel.h | 2 +- launcher/minecraft/mod/ShaderPackFolderModel.h | 4 ++- launcher/minecraft/mod/TexturePackFolderModel.cpp | 3 +- launcher/minecraft/mod/TexturePackFolderModel.h | 4 +-- launcher/ui/pages/modplatform/ModModel.cpp | 6 ++-- launcher/ui/pages/modplatform/ModModel.h | 4 +-- .../modplatform/flame/FlameResourceModels.cpp | 2 +- .../pages/modplatform/flame/FlameResourceModels.h | 2 +- .../modrinth/ModrinthResourceModels.cpp | 2 +- .../modplatform/modrinth/ModrinthResourceModels.h | 2 +- 19 files changed, 59 insertions(+), 47 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 76ff5723..2c624a36 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -1109,9 +1109,10 @@ JavaVersion MinecraftInstance::getJavaVersion() return JavaVersion(settings()->get("JavaVersion").toString()); } -std::shared_ptr MinecraftInstance::loaderModList() const +std::shared_ptr MinecraftInstance::loaderModList() { - if (!m_loader_mod_list) { + if (!m_loader_mod_list) + { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_loader_mod_list.reset(new ModFolderModel(modsRoot(), this, is_indexed)); m_loader_mod_list->disableInteraction(isRunning()); @@ -1120,9 +1121,10 @@ std::shared_ptr MinecraftInstance::loaderModList() const return m_loader_mod_list; } -std::shared_ptr MinecraftInstance::coreModList() const +std::shared_ptr MinecraftInstance::coreModList() { - if (!m_core_mod_list) { + if (!m_core_mod_list) + { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_core_mod_list.reset(new ModFolderModel(coreModsDir(), this, is_indexed)); m_core_mod_list->disableInteraction(isRunning()); @@ -1131,9 +1133,10 @@ std::shared_ptr MinecraftInstance::coreModList() const return m_core_mod_list; } -std::shared_ptr MinecraftInstance::nilModList() const +std::shared_ptr MinecraftInstance::nilModList() { - if (!m_nil_mod_list) { + if (!m_nil_mod_list) + { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_nil_mod_list.reset(new ModFolderModel(nilModsDir(), this, is_indexed, false)); m_nil_mod_list->disableInteraction(isRunning()); @@ -1142,41 +1145,46 @@ std::shared_ptr MinecraftInstance::nilModList() const return m_nil_mod_list; } -std::shared_ptr MinecraftInstance::resourcePackList() const +std::shared_ptr MinecraftInstance::resourcePackList() { - if (!m_resource_pack_list) { + if (!m_resource_pack_list) + { m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir(), this)); } return m_resource_pack_list; } -std::shared_ptr MinecraftInstance::texturePackList() const +std::shared_ptr MinecraftInstance::texturePackList() { - if (!m_texture_pack_list) { + if (!m_texture_pack_list) + { m_texture_pack_list.reset(new TexturePackFolderModel(texturePacksDir(), this)); } return m_texture_pack_list; } -std::shared_ptr MinecraftInstance::shaderPackList() const +std::shared_ptr MinecraftInstance::shaderPackList() { - if (!m_shader_pack_list) { + if (!m_shader_pack_list) + { m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir(), this)); } return m_shader_pack_list; } -std::shared_ptr MinecraftInstance::worldList() const +std::shared_ptr MinecraftInstance::worldList() { - if (!m_world_list) { + if (!m_world_list) + { m_world_list.reset(new WorldList(worldDir(), this)); } return m_world_list; } -std::shared_ptr MinecraftInstance::gameOptionsModel() const +std::shared_ptr MinecraftInstance::gameOptionsModel() { - if (!m_game_options) { + if (!m_game_options) + { m_game_options.reset(new GameOptions(FS::PathCombine(gameRoot(), "options.txt"))); } return m_game_options; diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index a75fa481..068b3008 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -115,14 +115,14 @@ public: std::shared_ptr getPackProfile() const; ////// Mod Lists ////// - std::shared_ptr loaderModList() const; - std::shared_ptr coreModList() const; - std::shared_ptr nilModList() const; - std::shared_ptr resourcePackList() const; - std::shared_ptr texturePackList() const; - std::shared_ptr shaderPackList() const; - std::shared_ptr worldList() const; - std::shared_ptr gameOptionsModel() const; + std::shared_ptr loaderModList(); + std::shared_ptr coreModList(); + std::shared_ptr nilModList(); + std::shared_ptr resourcePackList(); + std::shared_ptr texturePackList(); + std::shared_ptr shaderPackList(); + std::shared_ptr worldList(); + std::shared_ptr gameOptionsModel(); ////// Launch stuff ////// Task::Ptr createUpdateTask(Net::Mode mode) override; diff --git a/launcher/minecraft/WorldList.cpp b/launcher/minecraft/WorldList.cpp index 42772df5..0feee299 100644 --- a/launcher/minecraft/WorldList.cpp +++ b/launcher/minecraft/WorldList.cpp @@ -45,7 +45,8 @@ #include #include -WorldList::WorldList(const QString& dir, const BaseInstance* instance) : QAbstractListModel(), m_instance(instance), m_dir(dir) +WorldList::WorldList(const QString &dir, BaseInstance* instance) + : QAbstractListModel(), m_instance(instance), m_dir(dir) { FS::ensureFolderPathExists(m_dir.absolutePath()); m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs); diff --git a/launcher/minecraft/WorldList.h b/launcher/minecraft/WorldList.h index 92d02b9b..96b64193 100644 --- a/launcher/minecraft/WorldList.h +++ b/launcher/minecraft/WorldList.h @@ -50,7 +50,7 @@ public: IconFileRole }; - WorldList(const QString& dir, const BaseInstance* instance); + WorldList(const QString &dir, BaseInstance* instance); virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; @@ -128,7 +128,7 @@ signals: void changed(); protected: - const BaseInstance* m_instance; + BaseInstance* m_instance; QFileSystemWatcher *m_watcher; bool is_watching; QDir m_dir; diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index eccfe4ae..5e3b31e0 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -54,7 +54,7 @@ #include "minecraft/mod/tasks/ModFolderLoadTask.h" #include "modplatform/ModIndex.h" -ModFolderModel::ModFolderModel(const QString& dir, const BaseInstance* instance, bool is_indexed, bool create_dir) +ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool is_indexed, bool create_dir) : ResourceFolderModel(QDir(dir), instance, nullptr, create_dir), m_is_indexed(is_indexed) { m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER }; diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index 261a007a..d337fe29 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -75,7 +75,7 @@ public: Enable, Toggle }; - ModFolderModel(const QString& dir, const BaseInstance* instance, bool is_indexed = false, bool create_dir = true); + ModFolderModel(const QString &dir, BaseInstance* instance, bool is_indexed = false, bool create_dir = true); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 5664ea85..d2d875e4 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -16,7 +16,7 @@ #include "tasks/Task.h" -ResourceFolderModel::ResourceFolderModel(QDir dir, const BaseInstance* instance, QObject* parent, bool create_dir) +ResourceFolderModel::ResourceFolderModel(QDir dir, BaseInstance* instance, QObject* parent, bool create_dir) : QAbstractListModel(parent), m_dir(dir), m_instance(instance), m_watcher(this) { if (create_dir) { diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index d853b443..0a35e1bc 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -26,7 +26,7 @@ class QSortFilterProxyModel; class ResourceFolderModel : public QAbstractListModel { Q_OBJECT public: - ResourceFolderModel(QDir, const BaseInstance* instance, QObject* parent = nullptr, bool create_dir = true); + ResourceFolderModel(QDir, BaseInstance* instance, QObject* parent = nullptr, bool create_dir = true); ~ResourceFolderModel() override; /** Starts watching the paths for changes. @@ -191,7 +191,7 @@ class ResourceFolderModel : public QAbstractListModel { bool m_can_interact = true; QDir m_dir; - const BaseInstance* m_instance; + BaseInstance* m_instance; QFileSystemWatcher m_watcher; bool m_is_watching = false; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 8036292b..c12d1f23 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -45,7 +45,7 @@ #include "minecraft/mod/tasks/BasicFolderLoadTask.h" #include "minecraft/mod/tasks/LocalResourcePackParseTask.h" -ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, const BaseInstance* instance) +ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) { m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE }; diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.h b/launcher/minecraft/mod/ResourcePackFolderModel.h index 9d96253a..db4b14fb 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.h +++ b/launcher/minecraft/mod/ResourcePackFolderModel.h @@ -17,7 +17,7 @@ public: NUM_COLUMNS }; - explicit ResourcePackFolderModel(const QString& dir, const BaseInstance* instance); + explicit ResourcePackFolderModel(const QString &dir, BaseInstance* instance); [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; diff --git a/launcher/minecraft/mod/ShaderPackFolderModel.h b/launcher/minecraft/mod/ShaderPackFolderModel.h index c05bec1d..dc5acf80 100644 --- a/launcher/minecraft/mod/ShaderPackFolderModel.h +++ b/launcher/minecraft/mod/ShaderPackFolderModel.h @@ -6,5 +6,7 @@ class ShaderPackFolderModel : public ResourceFolderModel { Q_OBJECT public: - explicit ShaderPackFolderModel(const QString& dir, const BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) {} + explicit ShaderPackFolderModel(const QString& dir, BaseInstance* instance) + : ResourceFolderModel(QDir(dir), instance) + {} }; diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp index dadf8f77..c6609ed1 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.cpp +++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp @@ -39,7 +39,8 @@ #include "minecraft/mod/tasks/BasicFolderLoadTask.h" #include "minecraft/mod/tasks/LocalTexturePackParseTask.h" -TexturePackFolderModel::TexturePackFolderModel(const QString& dir, const BaseInstance* instance) : ResourceFolderModel(QDir(dir), instance) +TexturePackFolderModel::TexturePackFolderModel(const QString& dir, BaseInstance* instance) + : ResourceFolderModel(QDir(dir), instance) {} Task* TexturePackFolderModel::createUpdateTask() diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h index a1492f8b..425a71e4 100644 --- a/launcher/minecraft/mod/TexturePackFolderModel.h +++ b/launcher/minecraft/mod/TexturePackFolderModel.h @@ -42,8 +42,8 @@ class TexturePackFolderModel : public ResourceFolderModel { Q_OBJECT - public: - explicit TexturePackFolderModel(const QString& dir, const BaseInstance* instance); +public: + explicit TexturePackFolderModel(const QString &dir, BaseInstance* instance); [[nodiscard]] Task* createUpdateTask() override; [[nodiscard]] Task* createParseTask(Resource&) override; }; diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index 1579bbf4..b7537890 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -13,7 +13,7 @@ namespace ResourceDownload { -ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) {} +ModModel::ModModel(BaseInstance& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) {} /******** Make data requests ********/ @@ -26,7 +26,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments() std::optional> versions{}; - { // Version filter + { // Version filter if (!m_filter->versions.empty()) versions = m_filter->versions; } @@ -71,7 +71,7 @@ void ModModel::searchWithTerm(const QString& term, unsigned int sort, bool filte bool ModModel::isPackInstalled(ModPlatform::IndexedPack::Ptr pack) const { - auto allMods = static_cast(m_base_instance).loaderModList()->allMods(); + auto allMods = static_cast(m_base_instance).loaderModList()->allMods(); return std::any_of(allMods.cbegin(), allMods.cend(), [pack](Mod* mod) { if (auto meta = mod->metadata(); meta) return meta->provider == pack->provider && meta->project_id == pack->addonId; diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index 938ce32e..805d8b9a 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -24,7 +24,7 @@ class ModModel : public ResourceModel { Q_OBJECT public: - ModModel(const BaseInstance&, ResourceAPI* api); + ModModel(BaseInstance&, ResourceAPI* api); /* Ask the API for more information */ void searchWithTerm(const QString& term, unsigned int sort, bool filter_changed); @@ -45,7 +45,7 @@ class ModModel : public ResourceModel { virtual bool isPackInstalled(ModPlatform::IndexedPack::Ptr) const override; protected: - const BaseInstance& m_base_instance; + BaseInstance& m_base_instance; std::shared_ptr m_filter = nullptr; }; diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp index e3d0bc14..667a52d0 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.cpp @@ -11,7 +11,7 @@ namespace ResourceDownload { -FlameModModel::FlameModModel(BaseInstance const& base) : ModModel(base, new FlameAPI) {} +FlameModModel::FlameModModel(BaseInstance& base) : ModModel(base, new FlameAPI) {} void FlameModModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) { diff --git a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h index 0252ac40..221c8f7a 100644 --- a/launcher/ui/pages/modplatform/flame/FlameResourceModels.h +++ b/launcher/ui/pages/modplatform/flame/FlameResourceModels.h @@ -14,7 +14,7 @@ class FlameModModel : public ModModel { Q_OBJECT public: - FlameModModel(const BaseInstance&); + FlameModModel(BaseInstance&); ~FlameModModel() override = default; private: diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp index f5d1cc28..7f857485 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.cpp @@ -25,7 +25,7 @@ namespace ResourceDownload { -ModrinthModModel::ModrinthModModel(BaseInstance const& base) : ModModel(base, new ModrinthAPI) {} +ModrinthModModel::ModrinthModModel(BaseInstance& base) : ModModel(base, new ModrinthAPI) {} void ModrinthModModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) { diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h index b351b19b..66461807 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthResourceModels.h @@ -30,7 +30,7 @@ class ModrinthModModel : public ModModel { Q_OBJECT public: - ModrinthModModel(const BaseInstance&); + ModrinthModModel(BaseInstance&); ~ModrinthModModel() override = default; private: -- cgit From 5aa1c340dc6c353e34d0fbcac84fb89798a06481 Mon Sep 17 00:00:00 2001 From: Tayou Date: Sun, 11 Jun 2023 01:58:37 +0200 Subject: rainbow konami & toggle Signed-off-by: Tayou --- launcher/ui/MainWindow.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 834f57dd..dfee3b47 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -470,7 +470,23 @@ void MainWindow::lockToolbars(bool state) void MainWindow::konamiTriggered() { - qDebug() << "Super Secret Mode ACTIVATED!"; + QString gradient = " stop:0 rgba(125, 0, 0, 255), stop:0.166 rgba(125, 125, 0, 255), stop:0.333 rgba(0, 125, 0, 255), stop:0.5 rgba(0, 125, 125, 255), stop:0.666 rgba(0, 0, 125, 255), stop:0.833 rgba(125, 0, 125, 255), stop:1 rgba(125, 0, 0, 255));"; + QString stylesheet = "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0," + gradient; + if (ui->mainToolBar->styleSheet() == stylesheet) { + ui->mainToolBar->setStyleSheet(""); + ui->instanceToolBar->setStyleSheet(""); + ui->centralWidget->setStyleSheet(""); + ui->newsToolBar->setStyleSheet(""); + ui->statusBar->setStyleSheet(""); + qDebug() << "Super Secret Mode DEACTIVATED!"; + } else { + ui->mainToolBar->setStyleSheet(stylesheet); + ui->instanceToolBar->setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1," + gradient); + ui->centralWidget->setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1," + gradient); + ui->newsToolBar->setStyleSheet(stylesheet); + ui->statusBar->setStyleSheet(stylesheet); + qDebug() << "Super Secret Mode ACTIVATED!"; + } } void MainWindow::showInstanceContextMenu(const QPoint &pos) -- cgit From d6c7b4e813a254a2fb78547a7947aa913d80dbbb Mon Sep 17 00:00:00 2001 From: leo78913 Date: Sun, 11 Jun 2023 21:49:33 -0300 Subject: add icons to export menu Signed-off-by: leo78913 --- launcher/ui/MainWindow.cpp | 9 ++++++--- launcher/ui/MainWindow.ui | 10 ++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 834f57dd..bb7844d3 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -187,7 +187,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi } - // set the menu for the folders help, and accounts tool buttons + // set the menu for the folders help, accounts, and export tool buttons { auto foldersMenuButton = dynamic_cast(ui->mainToolBar->widgetForAction(ui->actionFoldersButton)); ui->actionFoldersButton->setMenu(ui->foldersMenu); @@ -201,6 +201,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi auto accountMenuButton = dynamic_cast(ui->mainToolBar->widgetForAction(ui->actionAccountsButton)); accountMenuButton->setPopupMode(QToolButton::InstantPopup); + + auto exportInstanceMenu = new QMenu(this); + exportInstanceMenu->addAction(ui->actionExportInstanceZip); + exportInstanceMenu->addAction(ui->actionExportInstanceMrPack); + ui->actionExportInstance->setMenu(exportInstanceMenu); } // hide, disable and show stuff @@ -397,8 +402,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi // removing this looks stupid view->setFocus(); - ui->actionExportInstance->setMenu(ui->exportInstanceMenu); - retranslateUi(); } diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index 4a89bc10..9e639ab0 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -150,10 +150,6 @@ - - - - @@ -467,11 +463,17 @@ + + + Prism Launcher (zip) + + + Modrinth (mrpack) -- cgit From 94ddc8bbf7a65f08079c4cf42deb4eea86b1e53b Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 12 Jun 2023 14:14:50 +0100 Subject: Could this work? Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 29df90dd..eff47b37 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -27,7 +27,7 @@ #include "minecraft/PackProfile.h" #include "minecraft/mod/ModFolderModel.h" -const QStringList ModrinthPackExportTask::PREFIXES({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" }); +const QStringList ModrinthPackExportTask::PREFIXES({ "mods/", "coremods/", "resourcepacks/", "texturepacks/", "shaderpacks/" }); const QStringList ModrinthPackExportTask::FILE_EXTENSIONS({ "jar", "litemod", "zip" }); ModrinthPackExportTask::ModrinthPackExportTask(const QString& name, @@ -99,14 +99,12 @@ void ModrinthPackExportTask::collectHashes() const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); // require sensible file types - if (!std::any_of(PREFIXES.begin(), PREFIXES.end(), - [&relative](const QString& prefix) { return relative.startsWith(prefix + QDir::separator()); })) + if (!std::any_of(PREFIXES.begin(), PREFIXES.end(), [&relative](const QString& prefix) { return relative.startsWith(prefix); })) continue; if (!std::any_of(FILE_EXTENSIONS.begin(), FILE_EXTENSIONS.end(), [&relative](const QString& extension) { return relative.endsWith('.' + extension) || relative.endsWith('.' + extension + ".disabled"); - })) { + })) continue; - } QCryptographicHash sha512(QCryptographicHash::Algorithm::Sha512); -- cgit From f4a814b5e639641bad40bcea6abaf34f9c253046 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 12 Jun 2023 15:46:15 +0100 Subject: Remove unnecessary code Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index eff47b37..bff9bf42 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -301,9 +301,7 @@ QByteArray ModrinthPackExportTask::generateIndex() const ResolvedFile& value = iterator.value(); QJsonObject file; - QString path = iterator.key(); - path.replace(QDir::separator(), "/"); - file["path"] = path; + file["path"] = iterator.key(); file["downloads"] = QJsonArray({ iterator.value().url }); QJsonObject hashes; -- cgit From b77fb059083ba04a3ccbc1b6e9ce4f5353b200ad Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 13 Jun 2023 21:07:05 +0300 Subject: Added back the INIFile read function Signed-off-by: Trial97 --- launcher/settings/INIFile.cpp | 85 +++++++++++++++++++++++++++++++++++++++---- tests/INIFile_test.cpp | 56 +++++++++++++++++++--------- 2 files changed, 115 insertions(+), 26 deletions(-) (limited to 'launcher') diff --git a/launcher/settings/INIFile.cpp b/launcher/settings/INIFile.cpp index f0347cab..cb909ae7 100644 --- a/launcher/settings/INIFile.cpp +++ b/launcher/settings/INIFile.cpp @@ -45,12 +45,12 @@ #include -INIFile::INIFile() -{ -} +INIFile::INIFile() {} bool INIFile::saveFile(QString fileName) { + if (!contains("ConfigVersion")) + insert("ConfigVersion", "1.1"); QSettings _settings_obj{ fileName, QSettings::Format::IniFormat }; _settings_obj.setFallbacksEnabled(false); @@ -71,6 +71,67 @@ bool INIFile::saveFile(QString fileName) return true; } +QString unescape(QString orig) +{ + QString out; + QChar prev = QChar::Null; + for (auto c : orig) { + if (prev == '\\') { + if (c == 'n') + out += '\n'; + else if (c == 't') + out += '\t'; + else if (c == '#') + out += '#'; + else + out += c; + prev = QChar::Null; + } else { + if (c == '\\') { + prev = c; + continue; + } + out += c; + prev = QChar::Null; + } + } + return out; +} +bool parseOldFileFormat(QIODevice& device, QSettings::SettingsMap& map) +{ + QTextStream in(device.readAll()); +#if QT_VERSION <= QT_VERSION_CHECK(6, 0, 0) + in.setCodec("UTF-8"); +#endif + + QStringList lines = in.readAll().split('\n'); + for (int i = 0; i < lines.count(); i++) { + QString& lineRaw = lines[i]; + // Ignore comments. + int commentIndex = 0; + QString line = lineRaw; + // Search for comments until no more escaped # are available + while ((commentIndex = line.indexOf('#', commentIndex + 1)) != -1) { + if (commentIndex > 0 && line.at(commentIndex - 1) == '\\') { + continue; + } + line = line.left(lineRaw.indexOf('#')).trimmed(); + } + + int eqPos = line.indexOf('='); + if (eqPos == -1) + continue; + QString key = line.left(eqPos).trimmed(); + QString valueStr = line.right(line.length() - eqPos - 1).trimmed(); + + valueStr = unescape(valueStr); + + QVariant value(valueStr); + map.insert(key, value); + } + + return true; +} bool INIFile::loadFile(QString fileName) { @@ -84,10 +145,19 @@ bool INIFile::loadFile(QString fileName) qCritical() << "A format error occurred (e.g. loading a malformed INI file)."; return false; } - - for (auto&& key : _settings_obj.allKeys()) - insert(key, _settings_obj.value(key)); - + if (!_settings_obj.value("ConfigVersion").isValid()) { + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) + return false; + QSettings::SettingsMap map; + parseOldFileFormat(file, map); + file.close(); + for (auto&& key : map.keys()) + insert(key, map.value(key)); + insert("ConfigVersion", "1.1"); + } else + for (auto&& key : _settings_obj.allKeys()) + insert(key, _settings_obj.value(key)); return true; } @@ -103,4 +173,3 @@ void INIFile::set(QString key, QVariant val) { this->operator[](key) = val; } - diff --git a/tests/INIFile_test.cpp b/tests/INIFile_test.cpp index 4be8133c..2f49e573 100644 --- a/tests/INIFile_test.cpp +++ b/tests/INIFile_test.cpp @@ -1,24 +1,16 @@ #include +#include #include #include -#include #include -class IniFileTest : public QObject -{ +class IniFileTest : public QObject { Q_OBJECT -private -slots: - void initTestCase() - { - - } - void cleanupTestCase() - { - - } + private slots: + void initTestCase() {} + void cleanupTestCase() {} void test_Escape_data() { @@ -47,17 +39,17 @@ slots: // load INIFile f2; f2.loadFile(filename); - QCOMPARE(f2.get("a","NOT SET").toString(), a); - QCOMPARE(f2.get("b","NOT SET").toString(), b); + QCOMPARE(f2.get("a", "NOT SET").toString(), a); + QCOMPARE(f2.get("b", "NOT SET").toString(), b); } void test_SaveLoadLists() { QString slist_strings = "(\"a\",\"b\",\"c\")"; - QStringList list_strings = {"a", "b", "c"}; + QStringList list_strings = { "a", "b", "c" }; QString slist_numbers = "(1,2,3,10)"; - QList list_numbers = {1, 2, 3, 10}; + QList list_numbers = { 1, 2, 3, 10 }; QString filename = "test_SaveLoadLists.ini"; @@ -72,13 +64,41 @@ slots: QStringList out_list_strings = f2.get("list_strings", QStringList()).toStringList(); qDebug() << "OutStringList" << out_list_strings; - + QList out_list_numbers = QVariantUtils::toList(f2.get("list_numbers", QVariantUtils::fromList(QList()))); qDebug() << "OutNumbersList" << out_list_numbers; QCOMPARE(out_list_strings, list_strings); QCOMPARE(out_list_numbers, list_numbers); } + + void test_SaveAleardyExistingFile() + { + QString fileName = "test_SaveAleardyExistingFile.ini"; + QString fileContent = R"(InstanceType=OneSix +iconKey=vanillia_icon +name=Minecraft Vanillia +OverrideCommands=true +PreLaunchCommand="$INST_JAVA" -jar packwiz-installer-bootstrap.jar link +)"; + QFile file(fileName); + + if (file.open(QFile::WriteOnly | QFile::Text)) { + QTextStream stream(&file); + stream << fileContent; + file.close(); + } + + // load + INIFile f1; + f1.loadFile(fileName); + QCOMPARE(f1.get("PreLaunchCommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link"); + f1.saveFile(fileName); + INIFile f2; + f2.loadFile(fileName); + QCOMPARE(f2.get("PreLaunchCommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link"); + QCOMPARE(f2.get("ConfigVersion", "NOT SET").toString(), "1.1"); + } }; QTEST_GUILESS_MAIN(IniFileTest) -- cgit From d4f2059b78bd53fccb20657d11b3386e427ec795 Mon Sep 17 00:00:00 2001 From: clickdevin Date: Wed, 14 Jun 2023 10:42:37 -0400 Subject: Fix bugs when updating curseforge modpacks Signed-off-by: clickdevin --- launcher/modplatform/flame/FlameInstanceCreationTask.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index dae93d1c..35443e71 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -153,6 +153,9 @@ bool FlameCreationTask::updateInstance() old_files.remove(file.key()); files_iterator = files.erase(files_iterator); + + if (files_iterator != files.begin()) + files_iterator--; } } -- cgit From e0b901169aaa5ebc7b74c15cd3f01f08ee98c4f1 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 15 Jun 2023 00:27:20 +0300 Subject: Added new migration for special characters Signed-off-by: Trial97 --- launcher/settings/INIFile.cpp | 19 ++++++++++-- tests/INIFile_test.cpp | 67 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 4 deletions(-) (limited to 'launcher') diff --git a/launcher/settings/INIFile.cpp b/launcher/settings/INIFile.cpp index cb909ae7..1d2f9611 100644 --- a/launcher/settings/INIFile.cpp +++ b/launcher/settings/INIFile.cpp @@ -50,7 +50,7 @@ INIFile::INIFile() {} bool INIFile::saveFile(QString fileName) { if (!contains("ConfigVersion")) - insert("ConfigVersion", "1.1"); + insert("ConfigVersion", "1.2"); QSettings _settings_obj{ fileName, QSettings::Format::IniFormat }; _settings_obj.setFallbacksEnabled(false); @@ -125,6 +125,10 @@ bool parseOldFileFormat(QIODevice& device, QSettings::SettingsMap& map) QString valueStr = line.right(line.length() - eqPos - 1).trimmed(); valueStr = unescape(valueStr); + if ((valueStr.contains(QChar(';')) || valueStr.contains(QChar('=')) || valueStr.contains(QChar(','))) && valueStr.endsWith("\"") && + valueStr.startsWith("\"")) { + valueStr = valueStr.removeFirst().removeLast(); + } QVariant value(valueStr); map.insert(key, value); @@ -154,7 +158,18 @@ bool INIFile::loadFile(QString fileName) file.close(); for (auto&& key : map.keys()) insert(key, map.value(key)); - insert("ConfigVersion", "1.1"); + insert("ConfigVersion", "1.2"); + } else if (_settings_obj.value("ConfigVersion").toString() == "1.1") { + for (auto&& key : _settings_obj.allKeys()) { + if (auto valueStr = _settings_obj.value(key).toString(); + (valueStr.contains(QChar(';')) || valueStr.contains(QChar('=')) || valueStr.contains(QChar(','))) && + valueStr.endsWith("\"") && valueStr.startsWith("\"")) { + valueStr = valueStr.removeFirst().removeLast(); + insert(key, valueStr); + } else + insert(key, _settings_obj.value(key)); + } + insert("ConfigVersion", "1.2"); } else for (auto&& key : _settings_obj.allKeys()) insert(key, _settings_obj.value(key)); diff --git a/tests/INIFile_test.cpp b/tests/INIFile_test.cpp index 2f49e573..5d9c9cd8 100644 --- a/tests/INIFile_test.cpp +++ b/tests/INIFile_test.cpp @@ -2,7 +2,9 @@ #include #include +#include #include +#include "FileSystem.h" #include @@ -80,7 +82,10 @@ iconKey=vanillia_icon name=Minecraft Vanillia OverrideCommands=true PreLaunchCommand="$INST_JAVA" -jar packwiz-installer-bootstrap.jar link -)"; +Wrapperommand=)"; + fileContent += "\""; + fileContent += +R"(\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link =)"; + fileContent += "\"\n"; QFile file(fileName); if (file.open(QFile::WriteOnly | QFile::Text)) { @@ -93,11 +98,69 @@ PreLaunchCommand="$INST_JAVA" -jar packwiz-installer-bootstrap.jar link INIFile f1; f1.loadFile(fileName); QCOMPARE(f1.get("PreLaunchCommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link"); + QCOMPARE(f1.get("Wrapperommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link ="); f1.saveFile(fileName); INIFile f2; f2.loadFile(fileName); QCOMPARE(f2.get("PreLaunchCommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link"); - QCOMPARE(f2.get("ConfigVersion", "NOT SET").toString(), "1.1"); + QCOMPARE(f2.get("Wrapperommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link ="); + QCOMPARE(f2.get("ConfigVersion", "NOT SET").toString(), "1.2"); + } + + void test_SaveAleardyExistingFileWithSpecialChars() + { + QString fileName = "test_SaveAleardyExistingFileWithSpecialChars.ini"; + FS::deletePath(fileName); // just to clean the previous test run + QSettings settings{ fileName, QSettings::Format::IniFormat }; + settings.setFallbacksEnabled(false); + + settings.setValue("simple", "value1"); + settings.setValue("withQuotes", R"("value2" with quotes)"); + settings.setValue("withSpecialCharacters", "env mesa=true"); + settings.setValue("withSpecialCharacters2", "1,2,3,4"); + settings.setValue("withSpecialCharacters2", "1;2;3;4"); + settings.setValue("withAll", "val=\"$INST_JAVA\" -jar; ls "); + + settings.sync(); + + QCOMPARE(settings.status(), QSettings::Status::NoError); + + // load + INIFile f1; + f1.loadFile(fileName); + for (auto key : settings.allKeys()) + QCOMPARE(f1.get(key, "NOT SET").toString(), settings.value(key).toString()); + f1.saveFile(fileName); + INIFile f2; + f2.loadFile(fileName); + for (auto key : settings.allKeys()) + QCOMPARE(f2.get(key, "NOT SET").toString(), settings.value(key).toString()); + QCOMPARE(f2.get("ConfigVersion", "NOT SET").toString(), "1.2"); + } + + void test_SaveAleardyExistingFileWithSpecialCharsV1() + { + QString fileName = "test_SaveAleardyExistingFileWithSpecialCharsV1.ini"; + QString fileContent = R"(InstanceType=OneSix +ConfigVersion=1.1 +iconKey=vanillia_icon +name=Minecraft Vanillia +OverrideCommands=true +PreLaunchCommand=)"; + fileContent += "\"\\\"env mesa=true\\\"\"\n"; + QFile file(fileName); + + if (file.open(QFile::WriteOnly | QFile::Text)) { + QTextStream stream(&file); + stream << fileContent; + file.close(); + } + + // load + INIFile f1; + f1.loadFile(fileName); + QCOMPARE(f1.get("PreLaunchCommand", "NOT SET").toString(), "env mesa=true"); + QCOMPARE(f1.get("ConfigVersion", "NOT SET").toString(), "1.2"); } }; -- cgit From cf4c1605ebe2f1db302928f847398e23236aed16 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 15 Jun 2023 00:37:32 +0300 Subject: Fixed qt5 build Signed-off-by: Trial97 --- launcher/settings/INIFile.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'launcher') diff --git a/launcher/settings/INIFile.cpp b/launcher/settings/INIFile.cpp index 1d2f9611..37846d11 100644 --- a/launcher/settings/INIFile.cpp +++ b/launcher/settings/INIFile.cpp @@ -97,6 +97,20 @@ QString unescape(QString orig) } return out; } + +QString unquete(QString str) +{ + if ((str.contains(QChar(';')) || str.contains(QChar('=')) || str.contains(QChar(','))) && str.endsWith("\"") && str.startsWith("\"")) { +#if QT_VERSION <= QT_VERSION_CHECK(6, 0, 0) + str = str.remove(0, 1); + str = str.remove(str.size() - 1, 1); +#else + str = str.removeFirst().removeLast(); +#endif + } + return str; +} + bool parseOldFileFormat(QIODevice& device, QSettings::SettingsMap& map) { QTextStream in(device.readAll()); @@ -124,11 +138,7 @@ bool parseOldFileFormat(QIODevice& device, QSettings::SettingsMap& map) QString key = line.left(eqPos).trimmed(); QString valueStr = line.right(line.length() - eqPos - 1).trimmed(); - valueStr = unescape(valueStr); - if ((valueStr.contains(QChar(';')) || valueStr.contains(QChar('=')) || valueStr.contains(QChar(','))) && valueStr.endsWith("\"") && - valueStr.startsWith("\"")) { - valueStr = valueStr.removeFirst().removeLast(); - } + valueStr = unquete(unescape(valueStr)); QVariant value(valueStr); map.insert(key, value); @@ -164,8 +174,7 @@ bool INIFile::loadFile(QString fileName) if (auto valueStr = _settings_obj.value(key).toString(); (valueStr.contains(QChar(';')) || valueStr.contains(QChar('=')) || valueStr.contains(QChar(','))) && valueStr.endsWith("\"") && valueStr.startsWith("\"")) { - valueStr = valueStr.removeFirst().removeLast(); - insert(key, valueStr); + insert(key, unquete(valueStr)); } else insert(key, _settings_obj.value(key)); } -- cgit From 811c79423fa048c5f4dd567b1121630d16aa3b0c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 15 Jun 2023 00:43:05 +0300 Subject: Fixed version comparation Signed-off-by: Trial97 --- launcher/settings/INIFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/settings/INIFile.cpp b/launcher/settings/INIFile.cpp index 37846d11..ad600ab9 100644 --- a/launcher/settings/INIFile.cpp +++ b/launcher/settings/INIFile.cpp @@ -101,7 +101,7 @@ QString unescape(QString orig) QString unquete(QString str) { if ((str.contains(QChar(';')) || str.contains(QChar('=')) || str.contains(QChar(','))) && str.endsWith("\"") && str.startsWith("\"")) { -#if QT_VERSION <= QT_VERSION_CHECK(6, 0, 0) +#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) str = str.remove(0, 1); str = str.remove(str.size() - 1, 1); #else -- cgit From be0df38453977c37ae8b6b241e82ace41149fdcc Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 15 Jun 2023 11:40:39 +0300 Subject: Added tooltip for name label Signed-off-by: Trial97 --- launcher/ui/pages/instance/ModFolderPage.cpp | 1 + launcher/ui/pages/instance/ModFolderPage.h | 3 +- launcher/ui/widgets/InfoFrame.cpp | 111 +++++++++++++++------------ launcher/ui/widgets/InfoFrame.h | 45 +++++++---- 4 files changed, 97 insertions(+), 63 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 1dbb9f47..650bf5bd 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -4,6 +4,7 @@ * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2022 TheKodeToad + * Copyright (c) 2023 Trial97 * * 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 diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h index d36a7995..2c1a9c77 100644 --- a/launcher/ui/pages/instance/ModFolderPage.h +++ b/launcher/ui/pages/instance/ModFolderPage.h @@ -4,6 +4,7 @@ * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2022 TheKodeToad + * Copyright (c) 2023 Trial97 * * 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 @@ -60,7 +61,7 @@ class ModFolderPage : public ExternalResourcesPage { private slots: void runningStateChanged(bool running); - void removeItems(const QItemSelection &selection) override; + void removeItems(const QItemSelection& selection) override; void installMods(); void updateMods(); diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index fdc581b4..d0b55c0b 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -1,37 +1,38 @@ // SPDX-License-Identifier: GPL-3.0-only /* -* PolyMC - Minecraft Launcher -* Copyright (c) 2022 flowln -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, version 3. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* This file incorporates work covered by the following copyright and -* permission notice: -* -* Copyright 2013-2021 MultiMC Contributors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2022 flowln + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #include @@ -57,34 +58,47 @@ InfoFrame::~InfoFrame() void InfoFrame::updateWithMod(Mod const& m) { - if (m.type() == ResourceType::FOLDER) - { + if (m.type() == ResourceType::FOLDER) { clear(); return; } QString text = ""; QString name = ""; + QString link = ""; + QString toolTip = ""; if (m.name().isEmpty()) name = m.internal_id(); else name = m.name(); - if (m.homeurl().isEmpty()) + if (auto meta = m.metadata(); meta != nullptr) { + auto slug = meta->slug.remove(".pw.toml"); + switch (meta->provider) { + case ModPlatform::ResourceProvider::MODRINTH: + link = QString("https://modrinth.com/mod/%1").arg(slug); + break; + case ModPlatform::ResourceProvider::FLAME: + link = QString("https://www.curseforge.com/minecraft/mc-mods/%1").arg(slug); + break; + } + } else if (!m.homeurl().isEmpty()) + link = m.homeurl(); + + if (link.isEmpty()) text = name; - else - text = "" + name + ""; + else { + text = "" + name + ""; + toolTip = tr("Go to mod's home page"); + } if (!m.authors().isEmpty()) text += " by " + m.authors().join(", "); - setName(text); + setName(text, toolTip); - if (m.description().isEmpty()) - { + if (m.description().isEmpty()) { setDescription(QString()); - } - else - { + } else { setDescription(m.description()); } @@ -191,16 +205,15 @@ void InfoFrame::updateHiddenState() } } -void InfoFrame::setName(QString text) +void InfoFrame::setName(QString text, QString toolTip) { - if(text.isEmpty()) - { + if (text.isEmpty()) { ui->nameLabel->setHidden(true); - } - else - { + ui->nameLabel->setToolTip({}); + } else { ui->nameLabel->setText(text); ui->nameLabel->setHidden(false); + ui->nameLabel->setToolTip(toolTip); } updateHiddenState(); } diff --git a/launcher/ui/widgets/InfoFrame.h b/launcher/ui/widgets/InfoFrame.h index 84523e28..4f6adc6d 100644 --- a/launcher/ui/widgets/InfoFrame.h +++ b/launcher/ui/widgets/InfoFrame.h @@ -1,16 +1,36 @@ -/* Copyright 2013-2021 MultiMC Contributors +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 * - * 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 + * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. * - * 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. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #pragma once @@ -21,8 +41,7 @@ #include "minecraft/mod/ResourcePack.h" #include "minecraft/mod/TexturePack.h" -namespace Ui -{ +namespace Ui { class InfoFrame; } @@ -33,7 +52,7 @@ class InfoFrame : public QFrame { InfoFrame(QWidget* parent = nullptr); ~InfoFrame() override; - void setName(QString text = {}); + void setName(QString text = {}, QString toolTip = {}); void setDescription(QString text = {}); void setImage(QPixmap img = {}); -- cgit From 6667ff9330cc080ca3c5fc2dd90af6b8420bf3fc Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 15 Jun 2023 12:32:48 +0300 Subject: Updated text and fixed mod page text update Signed-off-by: Trial97 --- .../ui/pages/instance/ExternalResourcesPage.cpp | 39 ++++++++++++++++++++-- launcher/ui/pages/instance/ModFolderPage.cpp | 27 ++++++--------- 2 files changed, 47 insertions(+), 19 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index e5567c80..e50fa635 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -1,3 +1,38 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "ExternalResourcesPage.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui_ExternalResourcesPage.h" @@ -264,7 +299,7 @@ QString ExternalResourcesPage::extraHeaderInfoString() if (ui && ui->treeView && ui->treeView->selectionModel()) { auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); if (auto count = std::count_if(selection.cbegin(), selection.cend(), [](auto v) { return v.column() == 0; }); count != 0) - return tr("[%1 installed, %2 selected]").arg(m_model->size()).arg(count); + return tr(" (%1 installed, %2 selected)").arg(m_model->size()).arg(count); } - return tr("[%1 installed]").arg(m_model->size()); + return tr(" (%1 installed)").arg(m_model->size()); } diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 4548af59..1d090ef4 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -4,6 +4,7 @@ * Copyright (c) 2022 Jamie Mansfield * Copyright (C) 2022 Sefa Eyeoglu * Copyright (C) 2022 TheKodeToad + * Copyright (c) 2023 Trial97 * * 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 @@ -86,28 +87,20 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods); auto check_allow_update = [this] { - return (!m_instance || !m_instance->isRunning()) && - (ui->treeView->selectionModel()->hasSelection() || !m_model->empty()); + return (!m_instance || !m_instance->isRunning()) && (ui->treeView->selectionModel()->hasSelection() || !m_model->empty()); }; - connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this, check_allow_update] { - ui->actionUpdateItem->setEnabled(check_allow_update()); - }); + connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, + [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); - connect(mods.get(), &ModFolderModel::rowsInserted, this, [this, check_allow_update] { - ui->actionUpdateItem->setEnabled(check_allow_update()); - }); + connect(mods.get(), &ModFolderModel::rowsInserted, this, + [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); - connect(mods.get(), &ModFolderModel::rowsRemoved, this, [this, check_allow_update] { - ui->actionUpdateItem->setEnabled(check_allow_update()); - }); + connect(mods.get(), &ModFolderModel::rowsRemoved, this, + [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); - connect(mods.get(), &ModFolderModel::updateFinished, this, [this, check_allow_update, mods] { - ui->actionUpdateItem->setEnabled(check_allow_update()); - - // Prevent a weird crash when trying to open the mods page twice in a session o.O - disconnect(mods.get(), &ModFolderModel::updateFinished, this, 0); - }); + connect(mods.get(), &ModFolderModel::updateFinished, this, + [this, check_allow_update, mods] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); connect(m_instance, &BaseInstance::runningStatusChanged, this, &ModFolderPage::runningStateChanged); ModFolderPage::runningStateChanged(m_instance && m_instance->isRunning()); -- cgit From cb52be433d2a55338df2205d2cebbf3e4d2f5eb5 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 15 Jun 2023 13:20:08 +0300 Subject: Made the installed mods more apparent Signed-off-by: Trial97 --- launcher/ui/widgets/ProjectItem.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'launcher') diff --git a/launcher/ui/widgets/ProjectItem.cpp b/launcher/ui/widgets/ProjectItem.cpp index e8349c10..0b00a9bd 100644 --- a/launcher/ui/widgets/ProjectItem.cpp +++ b/launcher/ui/widgets/ProjectItem.cpp @@ -65,9 +65,15 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o font.setUnderline(true); } if (index.data(UserDataTypes::INSTALLED).toBool()) { + auto rect = opt.rect; + rect.setX(rect.x() + 1); + rect.setY(rect.y() + 1); + rect.setHeight(rect.height() - 2); + rect.setWidth(rect.width() - 2); // Set nice font font.setItalic(true); font.setOverline(true); + painter->drawRect(rect); } font.setPointSize(font.pointSize() + 2); -- cgit From 7ad9abf9bce2f2d7ec0e9e6848673753fefba3dd Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 15 Jun 2023 12:42:45 +0200 Subject: fix: add JavaVendor as an instance override This should suppress a critical error that gets printed every time an instance gets launched, as JavaCheck wants to store the vendor in the instance settings. Signed-off-by: Sefa Eyeoglu --- launcher/minecraft/MinecraftInstance.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 2c624a36..f8ed5214 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -149,9 +149,10 @@ void MinecraftInstance::loadSpecificSettings() // special! m_settings->registerPassthrough(global_settings->getSetting("JavaTimestamp"), javaOrLocation); - m_settings->registerPassthrough(global_settings->getSetting("JavaVersion"), javaOrLocation); m_settings->registerPassthrough(global_settings->getSetting("JavaArchitecture"), javaOrLocation); m_settings->registerPassthrough(global_settings->getSetting("JavaRealArchitecture"), javaOrLocation); + m_settings->registerPassthrough(global_settings->getSetting("JavaVersion"), javaOrLocation); + m_settings->registerPassthrough(global_settings->getSetting("JavaVendor"), javaOrLocation); // Window Size auto windowSetting = m_settings->registerSetting("OverrideWindow", false); -- cgit From 6812823b55678230dd1fcd14973abc8d9a5d7245 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 15 Jun 2023 12:48:22 +0200 Subject: fix: simplify resolving of data path Co-authored-by: TheKodeToad Signed-off-by: Sefa Eyeoglu --- launcher/ui/MainWindow.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 629ace83..6b219197 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1203,9 +1203,7 @@ void MainWindow::on_actionViewInstanceFolder_triggered() void MainWindow::on_actionViewLauncherRootFolder_triggered() { - QDir dataDir = QDir::current(); - QString dataPath = dataDir.absolutePath(); - + const QString dataPath = QDir::currentPath(); DesktopServices::openDirectory(dataPath); } -- cgit From 98a07da39bbc41529b67cf515849d403280af07c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 15 Jun 2023 14:12:29 +0300 Subject: Renamed variable Signed-off-by: Trial97 --- launcher/ui/widgets/ProjectItem.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/widgets/ProjectItem.cpp b/launcher/ui/widgets/ProjectItem.cpp index 0b00a9bd..0085d6b2 100644 --- a/launcher/ui/widgets/ProjectItem.cpp +++ b/launcher/ui/widgets/ProjectItem.cpp @@ -65,15 +65,15 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o font.setUnderline(true); } if (index.data(UserDataTypes::INSTALLED).toBool()) { - auto rect = opt.rect; - rect.setX(rect.x() + 1); - rect.setY(rect.y() + 1); - rect.setHeight(rect.height() - 2); - rect.setWidth(rect.width() - 2); + auto hRect = opt.rect; + hRect.setX(hRect.x() + 1); + hRect.setY(hRect.y() + 1); + hRect.setHeight(hRect.height() - 2); + hRect.setWidth(hRect.width() - 2); // Set nice font font.setItalic(true); font.setOverline(true); - painter->drawRect(rect); + painter->drawRect(hRect); } font.setPointSize(font.pointSize() + 2); -- cgit From 1b42b9a08e5777fcf0d2578f3ffa05e354e47f9a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 15 Jun 2023 14:25:58 +0300 Subject: Fixed tests Signed-off-by: Trial97 --- launcher/settings/INIFile.cpp | 6 +++--- tests/INIFile_test.cpp | 39 ++++++++++++++++++++------------------- 2 files changed, 23 insertions(+), 22 deletions(-) (limited to 'launcher') diff --git a/launcher/settings/INIFile.cpp b/launcher/settings/INIFile.cpp index ad600ab9..d16256b9 100644 --- a/launcher/settings/INIFile.cpp +++ b/launcher/settings/INIFile.cpp @@ -98,7 +98,7 @@ QString unescape(QString orig) return out; } -QString unquete(QString str) +QString unquote(QString str) { if ((str.contains(QChar(';')) || str.contains(QChar('=')) || str.contains(QChar(','))) && str.endsWith("\"") && str.startsWith("\"")) { #if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) @@ -138,7 +138,7 @@ bool parseOldFileFormat(QIODevice& device, QSettings::SettingsMap& map) QString key = line.left(eqPos).trimmed(); QString valueStr = line.right(line.length() - eqPos - 1).trimmed(); - valueStr = unquete(unescape(valueStr)); + valueStr = unquote(unescape(valueStr)); QVariant value(valueStr); map.insert(key, value); @@ -174,7 +174,7 @@ bool INIFile::loadFile(QString fileName) if (auto valueStr = _settings_obj.value(key).toString(); (valueStr.contains(QChar(';')) || valueStr.contains(QChar('=')) || valueStr.contains(QChar(','))) && valueStr.endsWith("\"") && valueStr.startsWith("\"")) { - insert(key, unquete(valueStr)); + insert(key, unquote(valueStr)); } else insert(key, _settings_obj.value(key)); } diff --git a/tests/INIFile_test.cpp b/tests/INIFile_test.cpp index 5d9c9cd8..eaf077d4 100644 --- a/tests/INIFile_test.cpp +++ b/tests/INIFile_test.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "FileSystem.h" @@ -74,9 +75,8 @@ class IniFileTest : public QObject { QCOMPARE(out_list_numbers, list_numbers); } - void test_SaveAleardyExistingFile() + void test_SaveAlreadyExistingFile() { - QString fileName = "test_SaveAleardyExistingFile.ini"; QString fileContent = R"(InstanceType=OneSix iconKey=vanillia_icon name=Minecraft Vanillia @@ -86,9 +86,10 @@ Wrapperommand=)"; fileContent += "\""; fileContent += +R"(\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link =)"; fileContent += "\"\n"; - QFile file(fileName); + QTemporaryFile file; - if (file.open(QFile::WriteOnly | QFile::Text)) { + // QFile file(fileName); + if (file.open()) { QTextStream stream(&file); stream << fileContent; file.close(); @@ -96,22 +97,23 @@ Wrapperommand=)"; // load INIFile f1; - f1.loadFile(fileName); + f1.loadFile(file.fileName()); QCOMPARE(f1.get("PreLaunchCommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link"); QCOMPARE(f1.get("Wrapperommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link ="); - f1.saveFile(fileName); + f1.saveFile(file.fileName()); INIFile f2; - f2.loadFile(fileName); + f2.loadFile(file.fileName()); QCOMPARE(f2.get("PreLaunchCommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link"); QCOMPARE(f2.get("Wrapperommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link ="); QCOMPARE(f2.get("ConfigVersion", "NOT SET").toString(), "1.2"); } - void test_SaveAleardyExistingFileWithSpecialChars() + void test_SaveAlreadyExistingFileWithSpecialChars() { - QString fileName = "test_SaveAleardyExistingFileWithSpecialChars.ini"; - FS::deletePath(fileName); // just to clean the previous test run - QSettings settings{ fileName, QSettings::Format::IniFormat }; + QTemporaryFile file; + file.open(); + file.close(); + QSettings settings{ file.fileName(), QSettings::Format::IniFormat }; settings.setFallbacksEnabled(false); settings.setValue("simple", "value1"); @@ -127,20 +129,20 @@ Wrapperommand=)"; // load INIFile f1; - f1.loadFile(fileName); + f1.loadFile(file.fileName()); for (auto key : settings.allKeys()) QCOMPARE(f1.get(key, "NOT SET").toString(), settings.value(key).toString()); - f1.saveFile(fileName); + f1.saveFile(file.fileName()); INIFile f2; - f2.loadFile(fileName); + f2.loadFile(file.fileName()); for (auto key : settings.allKeys()) QCOMPARE(f2.get(key, "NOT SET").toString(), settings.value(key).toString()); QCOMPARE(f2.get("ConfigVersion", "NOT SET").toString(), "1.2"); } - void test_SaveAleardyExistingFileWithSpecialCharsV1() + void test_SaveAlreadyExistingFileWithSpecialCharsV1() { - QString fileName = "test_SaveAleardyExistingFileWithSpecialCharsV1.ini"; + QTemporaryFile file; QString fileContent = R"(InstanceType=OneSix ConfigVersion=1.1 iconKey=vanillia_icon @@ -148,9 +150,8 @@ name=Minecraft Vanillia OverrideCommands=true PreLaunchCommand=)"; fileContent += "\"\\\"env mesa=true\\\"\"\n"; - QFile file(fileName); - if (file.open(QFile::WriteOnly | QFile::Text)) { + if (file.open()) { QTextStream stream(&file); stream << fileContent; file.close(); @@ -158,7 +159,7 @@ PreLaunchCommand=)"; // load INIFile f1; - f1.loadFile(fileName); + f1.loadFile(file.fileName()); QCOMPARE(f1.get("PreLaunchCommand", "NOT SET").toString(), "env mesa=true"); QCOMPARE(f1.get("ConfigVersion", "NOT SET").toString(), "1.2"); } -- cgit From 13804f80de2cef845a917564adff9d9906c0eb5c Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 15 Jun 2023 16:37:03 +0100 Subject: Fix trailing space in instance name Signed-off-by: TheKodeToad --- launcher/InstanceTask.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/InstanceTask.cpp b/launcher/InstanceTask.cpp index 06682782..b16a40ba 100644 --- a/launcher/InstanceTask.cpp +++ b/launcher/InstanceTask.cpp @@ -45,7 +45,10 @@ QString InstanceName::name() const { if (!m_modified_name.isEmpty()) return modifiedName(); - return QString("%1 %2").arg(m_original_name, m_original_version); + if (!m_original_version.isEmpty()) + return QString("%1 %2").arg(m_original_name, m_original_version); + + return m_original_name; } QString InstanceName::originalName() const -- cgit From 147366bc0a905869f41bd8577337354bc7894e88 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 15 Jun 2023 22:59:41 +0300 Subject: Made ByteSynkArray to use shared_ptr Signed-off-by: Trial97 --- launcher/modplatform/EnsureMetadataTask.cpp | 16 +- launcher/modplatform/ResourceAPI.h | 4 +- .../modplatform/atlauncher/ATLPackInstallTask.cpp | 17 +- .../modplatform/atlauncher/ATLPackInstallTask.h | 9 +- launcher/modplatform/flame/FileResolvingTask.cpp | 25 +- launcher/modplatform/flame/FlameAPI.cpp | 20 +- launcher/modplatform/flame/FlameAPI.h | 14 +- launcher/modplatform/flame/FlameCheckUpdate.cpp | 4 +- .../flame/FlameInstanceCreationTask.cpp | 2 +- .../modplatform/helpers/NetworkResourceAPI.cpp | 31 +- launcher/modplatform/helpers/NetworkResourceAPI.h | 3 +- launcher/modplatform/legacy_ftb/PackFetchTask.cpp | 68 ++-- launcher/modplatform/legacy_ftb/PackFetchTask.h | 26 +- launcher/modplatform/modrinth/ModrinthAPI.cpp | 22 +- launcher/modplatform/modrinth/ModrinthAPI.h | 18 +- .../modplatform/modrinth/ModrinthCheckUpdate.cpp | 2 +- .../modrinth/ModrinthPackExportTask.cpp | 4 +- .../modplatform/modrinth/ModrinthPackExportTask.h | 2 +- .../modplatform/technic/SolderPackInstallTask.cpp | 33 +- .../modplatform/technic/SolderPackInstallTask.h | 73 ++-- launcher/net/ByteArraySink.h | 7 +- launcher/net/Download.cpp | 3 +- launcher/net/Download.h | 2 +- launcher/net/Upload.cpp | 366 +++++++++++---------- launcher/net/Upload.h | 42 +-- launcher/news/NewsChecker.cpp | 19 +- launcher/news/NewsChecker.h | 2 +- launcher/ui/pages/instance/ManagedPackPage.cpp | 4 +- .../pages/modplatform/atlauncher/AtlListModel.cpp | 8 +- .../ui/pages/modplatform/atlauncher/AtlListModel.h | 29 +- .../atlauncher/AtlOptionalModDialog.cpp | 8 +- .../modplatform/atlauncher/AtlOptionalModDialog.h | 4 +- launcher/ui/pages/modplatform/flame/FlameModel.cpp | 6 +- launcher/ui/pages/modplatform/flame/FlameModel.h | 53 ++- launcher/ui/pages/modplatform/flame/FlamePage.cpp | 7 +- .../pages/modplatform/modrinth/ModrinthModel.cpp | 18 +- .../ui/pages/modplatform/modrinth/ModrinthModel.h | 4 +- .../ui/pages/modplatform/modrinth/ModrinthPage.cpp | 20 +- .../ui/pages/modplatform/technic/TechnicModel.cpp | 12 +- .../ui/pages/modplatform/technic/TechnicModel.h | 27 +- .../ui/pages/modplatform/technic/TechnicPage.cpp | 15 +- .../ui/pages/modplatform/technic/TechnicPage.h | 2 +- 42 files changed, 492 insertions(+), 559 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp index 34d969f0..080dd580 100644 --- a/launcher/modplatform/EnsureMetadataTask.cpp +++ b/launcher/modplatform/EnsureMetadataTask.cpp @@ -212,12 +212,12 @@ Task::Ptr EnsureMetadataTask::modrinthVersionsTask() { auto hash_type = ProviderCaps.hashType(ModPlatform::ResourceProvider::MODRINTH).first(); - auto* response = new QByteArray(); + auto response = std::make_shared(); auto ver_task = modrinth_api.currentVersions(m_mods.keys(), hash_type, response); // Prevents unfortunate timings when aborting the task if (!ver_task) - return Task::Ptr{nullptr}; + return Task::Ptr{ nullptr }; connect(ver_task.get(), &Task::succeeded, this, [this, response] { QJsonParseError parse_error{}; @@ -264,7 +264,7 @@ Task::Ptr EnsureMetadataTask::modrinthProjectsTask() for (auto const& data : m_temp_versions) addonIds.insert(data.addonId.toString(), data.hash); - auto response = new QByteArray(); + auto response = std::make_shared(); Task::Ptr proj_task; if (addonIds.isEmpty()) { @@ -277,7 +277,7 @@ Task::Ptr EnsureMetadataTask::modrinthProjectsTask() // Prevents unfortunate timings when aborting the task if (!proj_task) - return Task::Ptr{nullptr}; + return Task::Ptr{ nullptr }; connect(proj_task.get(), &Task::succeeded, this, [this, response, addonIds] { QJsonParseError parse_error{}; @@ -345,7 +345,7 @@ Task::Ptr EnsureMetadataTask::modrinthProjectsTask() // Flame Task::Ptr EnsureMetadataTask::flameVersionsTask() { - auto* response = new QByteArray(); + auto response = std::make_shared(); QList fingerprints; for (auto& murmur : m_mods.keys()) { @@ -413,7 +413,7 @@ Task::Ptr EnsureMetadataTask::flameProjectsTask() QHash addonIds; for (auto const& hash : m_mods.keys()) { if (m_temp_versions.contains(hash)) { - auto const& data = m_temp_versions.find(hash).value(); + auto data = m_temp_versions.find(hash).value(); auto id_str = data.addonId.toString(); if (!id_str.isEmpty()) @@ -421,7 +421,7 @@ Task::Ptr EnsureMetadataTask::flameProjectsTask() } } - auto response = new QByteArray(); + auto response = std::make_shared(); Task::Ptr proj_task; if (addonIds.isEmpty()) { @@ -434,7 +434,7 @@ Task::Ptr EnsureMetadataTask::flameProjectsTask() // Prevents unfortunate timings when aborting the task if (!proj_task) - return Task::Ptr{nullptr}; + return Task::Ptr{ nullptr }; connect(proj_task.get(), &Task::succeeded, this, [this, response, addonIds] { QJsonParseError parse_error{}; diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index 34f33779..e24971d5 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -121,12 +121,12 @@ class ResourceAPI { qWarning() << "TODO"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getProject(QString addonId, QByteArray* response) const + [[nodiscard]] virtual Task::Ptr getProject(QString addonId, std::shared_ptr response) const { qWarning() << "TODO"; return nullptr; } - [[nodiscard]] virtual Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const + [[nodiscard]] virtual Task::Ptr getProjects(QStringList addonIds, std::shared_ptr response) const { qWarning() << "TODO"; return nullptr; diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 07e0bf23..2522020d 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -82,9 +82,9 @@ void PackInstallTask::executeTask() { qDebug() << "PackInstallTask::executeTask: " << QThread::currentThreadId(); NetJob::Ptr netJob{ new NetJob("ATLauncher::VersionFetch", APPLICATION->network()) }; - auto searchUrl = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.json") - .arg(m_pack_safe_name).arg(m_version_name); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); + auto searchUrl = + QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.json").arg(m_pack_safe_name).arg(m_version_name); + netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response)); QObject::connect(netJob.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded); QObject::connect(netJob.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed); @@ -99,11 +99,12 @@ void PackInstallTask::onDownloadSucceeded() qDebug() << "PackInstallTask::onDownloadSucceeded: " << QThread::currentThreadId(); jobPtr.reset(); - QJsonParseError parse_error {}; - QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); - if(parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from ATLauncher at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << response; + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response.get(), &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from ATLauncher at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response.get(); return; } auto obj = doc.object(); diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.h b/launcher/modplatform/atlauncher/ATLPackInstallTask.h index 90e25ae2..bfe4d90a 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.h +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.h @@ -40,12 +40,13 @@ #include "ATLPackManifest.h" #include "InstanceTask.h" -#include "net/NetJob.h" -#include "settings/INISettingsObject.h" +#include "meta/Version.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" -#include "meta/Version.h" +#include "net/NetJob.h" +#include "settings/INISettingsObject.h" +#include #include namespace ATLauncher { @@ -123,7 +124,7 @@ private: bool abortable = false; NetJob::Ptr jobPtr; - QByteArray response; + std::shared_ptr response = std::make_shared(); InstallMode m_install_mode; QString m_pack_name; diff --git a/launcher/modplatform/flame/FileResolvingTask.cpp b/launcher/modplatform/flame/FileResolvingTask.cpp index 83db642e..ce7a6055 100644 --- a/launcher/modplatform/flame/FileResolvingTask.cpp +++ b/launcher/modplatform/flame/FileResolvingTask.cpp @@ -25,15 +25,16 @@ void Flame::FileResolvingTask::executeTask() setProgress(0, 3); m_dljob.reset(new NetJob("Mod id resolver", m_network)); result.reset(new QByteArray()); - //build json data to send + // build json data to send QJsonObject object; - object["fileIds"] = QJsonArray::fromVariantList(std::accumulate(m_toProcess.files.begin(), m_toProcess.files.end(), QVariantList(), [](QVariantList& l, const File& s) { - l.push_back(s.fileId); - return l; - })); + object["fileIds"] = QJsonArray::fromVariantList( + std::accumulate(m_toProcess.files.begin(), m_toProcess.files.end(), QVariantList(), [](QVariantList& l, const File& s) { + l.push_back(s.fileId); + return l; + })); QByteArray data = Json::toText(object); - auto dl = Net::Upload::makeByteArray(QUrl("https://api.curseforge.com/v1/mods/files"), result.get(), data); + auto dl = Net::Upload::makeByteArray(QUrl("https://api.curseforge.com/v1/mods/files"), result, data); m_dljob->addNetAction(dl); auto step_progress = std::make_shared(); @@ -87,17 +88,15 @@ void Flame::FileResolvingTask::netJobFinished() auto fileid = Json::requireInteger(Json::requireObject(file)["id"]); auto& out = m_toProcess.files[fileid]; try { - out.parseFromObject(Json::requireObject(file)); + out.parseFromObject(Json::requireObject(file)); } catch (const JSONValidationError& e) { qDebug() << "Blocked mod on curseforge" << out.fileName; auto hash = out.hash; - if(!hash.isEmpty()) { + if (!hash.isEmpty()) { auto url = QString("https://api.modrinth.com/v2/version_file/%1?algorithm=sha1").arg(hash); auto output = std::make_shared(); - auto dl = Net::Download::makeByteArray(QUrl(url), output.get()); - QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() { - out.resolved = true; - }); + auto dl = Net::Download::makeByteArray(QUrl(url), output); + QObject::connect(dl.get(), &Net::Download::succeeded, [&out]() { out.resolved = true; }); m_checkJob->addNetAction(dl); blockedProjects.insert(&out, output); @@ -169,7 +168,7 @@ void Flame::FileResolvingTask::modrinthCheckFinished() { auto projectId = mod->projectId; auto output = std::make_shared(); auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(projectId); - auto dl = Net::Download::makeByteArray(url, output.get()); + auto dl = Net::Download::makeByteArray(url, output); qDebug() << "Fetching url slug for file:" << mod->fileName; QObject::connect(dl.get(), &Net::Download::succeeded, [block, index, output]() { auto mod = block->at(index); // use the shared_ptr so it is captured and only freed when we are done diff --git a/launcher/modplatform/flame/FlameAPI.cpp b/launcher/modplatform/flame/FlameAPI.cpp index 92590a08..5b0b1d8b 100644 --- a/launcher/modplatform/flame/FlameAPI.cpp +++ b/launcher/modplatform/flame/FlameAPI.cpp @@ -11,7 +11,7 @@ #include "net/NetJob.h" #include "net/Upload.h" -Task::Ptr FlameAPI::matchFingerprints(const QList& fingerprints, QByteArray* response) +Task::Ptr FlameAPI::matchFingerprints(const QList& fingerprints, std::shared_ptr response) { auto netJob = makeShared(QString("Flame::MatchFingerprints"), APPLICATION->network()); @@ -28,8 +28,6 @@ Task::Ptr FlameAPI::matchFingerprints(const QList& fingerprints, QByteArra netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/fingerprints"), response, body_raw)); - QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); - return netJob; } @@ -43,7 +41,7 @@ auto FlameAPI::getModFileChangelog(int modId, int fileId) -> QString netJob->addNetAction(Net::Download::makeByteArray( QString("https://api.curseforge.com/v1/mods/%1/files/%2/changelog") .arg(QString::fromStdString(std::to_string(modId)), QString::fromStdString(std::to_string(fileId))), - response.get())); + response)); QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &changelog] { QJsonParseError parse_error{}; @@ -75,8 +73,8 @@ auto FlameAPI::getModDescription(int modId) -> QString auto netJob = makeShared(QString("Flame::ModDescription"), APPLICATION->network()); auto response = std::make_shared(); - netJob->addNetAction(Net::Download::makeByteArray( - QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response.get())); + netJob->addNetAction( + Net::Download::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response)); QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] { QJsonParseError parse_error{}; @@ -115,7 +113,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe auto response = std::make_shared(); ModPlatform::IndexedVersion ver; - netJob->addNetAction(Net::Download::makeByteArray(versions_url, response.get())); + netJob->addNetAction(Net::Download::makeByteArray(versions_url, response)); QObject::connect(netJob.get(), &NetJob::succeeded, [response, args, &ver] { QJsonParseError parse_error{}; @@ -137,7 +135,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe for (auto file : arr) { auto file_obj = Json::requireObject(file); auto file_tmp = FlameMod::loadIndexedPackVersion(file_obj); - if(file_tmp.date > ver_tmp.date) { + if (file_tmp.date > ver_tmp.date) { ver_tmp = file_tmp; latest_file_obj = file_obj; } @@ -160,7 +158,7 @@ auto FlameAPI::getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::Indexe return ver; } -Task::Ptr FlameAPI::getProjects(QStringList addonIds, QByteArray* response) const +Task::Ptr FlameAPI::getProjects(QStringList addonIds, std::shared_ptr response) const { auto netJob = makeShared(QString("Flame::GetProjects"), APPLICATION->network()); @@ -177,13 +175,12 @@ Task::Ptr FlameAPI::getProjects(QStringList addonIds, QByteArray* response) cons netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/mods"), response, body_raw)); - QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; }); return netJob; } -Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, QByteArray* response) const +Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, std::shared_ptr response) const { auto netJob = makeShared(QString("Flame::GetFiles"), APPLICATION->network()); @@ -200,7 +197,6 @@ Task::Ptr FlameAPI::getFiles(const QStringList& fileIds, QByteArray* response) c netJob->addNetAction(Net::Upload::makeByteArray(QString("https://api.curseforge.com/v1/mods/files"), response, body_raw)); - QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); QObject::connect(netJob.get(), &NetJob::failed, [body_raw] { qDebug() << body_raw; }); return netJob; diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 5811d717..49ba12b0 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -4,6 +4,7 @@ #pragma once +#include #include "modplatform/ModIndex.h" #include "modplatform/helpers/NetworkResourceAPI.h" @@ -14,9 +15,9 @@ class FlameAPI : public NetworkResourceAPI { auto getLatestVersion(VersionSearchArgs&& args) -> ModPlatform::IndexedVersion; - Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const override; - Task::Ptr matchFingerprints(const QList& fingerprints, QByteArray* response); - Task::Ptr getFiles(const QStringList& fileIds, QByteArray* response) const; + Task::Ptr getProjects(QStringList addonIds, std::shared_ptr response) const override; + Task::Ptr matchFingerprints(const QList& fingerprints, std::shared_ptr response); + Task::Ptr getFiles(const QStringList& fileIds, std::shared_ptr response) const; [[nodiscard]] auto getSortingMethods() const -> QList override; @@ -41,14 +42,15 @@ class FlameAPI : public NetworkResourceAPI { return 4; // TODO: remove this once Quilt drops official Fabric support if (loaders & Quilt) // NOTE: Most if not all Fabric mods should work *currently* - return 4; // Quilt would probably be 5 + return 4; // Quilt would probably be 5 return 0; } private: [[nodiscard]] std::optional getSearchURL(SearchArgs const& args) const override { - auto gameVersionStr = args.versions.has_value() ? QString("gameVersion=%1").arg(args.versions.value().front().toString()) : QString(); + auto gameVersionStr = + args.versions.has_value() ? QString("gameVersion=%1").arg(args.versions.value().front().toString()) : QString(); QStringList get_arguments; get_arguments.append(QString("classId=%1").arg(getClassId(args.type))); @@ -73,7 +75,7 @@ class FlameAPI : public NetworkResourceAPI { [[nodiscard]] std::optional getVersionsURL(VersionSearchArgs const& args) const override { - QString url{QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(args.pack.addonId.toString())}; + QString url{ QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(args.pack.addonId.toString()) }; QStringList get_parameters; if (args.mcVersions.has_value()) diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index e09aeb3d..a2628e34 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -31,7 +31,7 @@ ModPlatform::IndexedPack getProjectInfo(ModPlatform::IndexedVersion& ver_info) auto get_project_job = new NetJob("Flame::GetProjectJob", APPLICATION->network()); - auto response = new QByteArray(); + auto response = std::make_shared(); auto url = QString("https://api.curseforge.com/v1/mods/%1").arg(ver_info.addonId.toString()); auto dl = Net::Download::makeByteArray(url, response); get_project_job->addNetAction(dl); @@ -75,7 +75,7 @@ ModPlatform::IndexedVersion getFileInfo(int addonId, int fileId) auto get_file_info_job = new NetJob("Flame::GetFileInfoJob", APPLICATION->network()); - auto response = new QByteArray(); + auto response = std::make_shared(); auto url = QString("https://api.curseforge.com/v1/mods/%1/files/%2").arg(QString::number(addonId), QString::number(fileId)); auto dl = Net::Download::makeByteArray(url, response); get_file_info_job->addNetAction(dl); diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index dae93d1c..3aa156e1 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -179,7 +179,7 @@ bool FlameCreationTask::updateInstance() fileIds.append(QString::number(file.fileId)); } - auto* raw_response = new QByteArray; + auto raw_response = std::make_shared(); auto job = api.getFiles(fileIds, raw_response); QEventLoop loop; diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.cpp b/launcher/modplatform/helpers/NetworkResourceAPI.cpp index a3c592fd..0ed2410e 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.cpp +++ b/launcher/modplatform/helpers/NetworkResourceAPI.cpp @@ -3,6 +3,7 @@ // SPDX-License-Identifier: GPL-3.0-only #include "NetworkResourceAPI.h" +#include #include "Application.h" #include "net/NetJob.h" @@ -19,12 +20,12 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks& auto search_url = search_url_optional.value(); - auto response = new QByteArray(); + auto response = std::make_shared(); auto netJob = makeShared(QString("%1::Search").arg(debugName()), APPLICATION->network()); netJob->addNetAction(Net::Download::makeByteArray(QUrl(search_url), response)); - QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks]{ + QObject::connect(netJob.get(), &NetJob::succeeded, [this, response, callbacks] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { @@ -40,27 +41,21 @@ Task::Ptr NetworkResourceAPI::searchProjects(SearchArgs&& args, SearchCallbacks& callbacks.on_succeed(doc); }); - QObject::connect(netJob.get(), &NetJob::failed, [&netJob, callbacks](QString reason){ + QObject::connect(netJob.get(), &NetJob::failed, [&netJob, callbacks](QString reason) { int network_error_code = -1; if (auto* failed_action = netJob->getFailedActions().at(0); failed_action && failed_action->m_reply) network_error_code = failed_action->m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - callbacks.on_fail(reason, network_error_code); - }); - QObject::connect(netJob.get(), &NetJob::aborted, [callbacks]{ - callbacks.on_abort(); - }); - QObject::connect(netJob.get(), &NetJob::finished, [response] { - delete response; + callbacks.on_fail(reason, network_error_code); }); - + QObject::connect(netJob.get(), &NetJob::aborted, [callbacks] { callbacks.on_abort(); }); return netJob; } Task::Ptr NetworkResourceAPI::getProjectInfo(ProjectInfoArgs&& args, ProjectInfoCallbacks&& callbacks) const { - auto response = new QByteArray(); + auto response = std::make_shared(); auto job = getProject(args.pack.addonId.toString(), response); QObject::connect(job.get(), &NetJob::succeeded, [response, callbacks, args] { @@ -88,7 +83,7 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi auto versions_url = versions_url_optional.value(); auto netJob = makeShared(QString("%1::Versions").arg(args.pack.name), APPLICATION->network()); - auto response = new QByteArray(); + auto response = std::make_shared(); netJob->addNetAction(Net::Download::makeByteArray(versions_url, response)); @@ -105,14 +100,10 @@ Task::Ptr NetworkResourceAPI::getProjectVersions(VersionSearchArgs&& args, Versi callbacks.on_succeed(doc, args.pack); }); - QObject::connect(netJob.get(), &NetJob::finished, [response] { - delete response; - }); - return netJob; } -Task::Ptr NetworkResourceAPI::getProject(QString addonId, QByteArray* response) const +Task::Ptr NetworkResourceAPI::getProject(QString addonId, std::shared_ptr response) const { auto project_url_optional = getInfoURL(addonId); if (!project_url_optional.has_value()) @@ -124,9 +115,5 @@ Task::Ptr NetworkResourceAPI::getProject(QString addonId, QByteArray* response) netJob->addNetAction(Net::Download::makeByteArray(QUrl(project_url), response)); - QObject::connect(netJob.get(), &NetJob::finished, [response] { - delete response; - }); - return netJob; } diff --git a/launcher/modplatform/helpers/NetworkResourceAPI.h b/launcher/modplatform/helpers/NetworkResourceAPI.h index 94813bec..84604e41 100644 --- a/launcher/modplatform/helpers/NetworkResourceAPI.h +++ b/launcher/modplatform/helpers/NetworkResourceAPI.h @@ -4,13 +4,14 @@ #pragma once +#include #include "modplatform/ResourceAPI.h" class NetworkResourceAPI : public ResourceAPI { public: Task::Ptr searchProjects(SearchArgs&&, SearchCallbacks&&) const override; - Task::Ptr getProject(QString addonId, QByteArray* response) const override; + Task::Ptr getProject(QString addonId, std::shared_ptr response) const override; Task::Ptr getProjectInfo(ProjectInfoArgs&&, ProjectInfoCallbacks&&) const override; Task::Ptr getProjectVersions(VersionSearchArgs&&, VersionSearchCallbacks&&) const override; diff --git a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp index e8768c5c..a8a0fc2c 100644 --- a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp +++ b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp @@ -51,11 +51,11 @@ void PackFetchTask::fetch() QUrl publicPacksUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/modpacks.xml"); qDebug() << "Downloading public version info from" << publicPacksUrl.toString(); - jobPtr->addNetAction(Net::Download::makeByteArray(publicPacksUrl, &publicModpacksXmlFileData)); + jobPtr->addNetAction(Net::Download::makeByteArray(publicPacksUrl, publicModpacksXmlFileData)); QUrl thirdPartyUrl = QUrl(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/thirdparty.xml"); qDebug() << "Downloading thirdparty version info from" << thirdPartyUrl.toString(); - jobPtr->addNetAction(Net::Download::makeByteArray(thirdPartyUrl, &thirdPartyModpacksXmlFileData)); + jobPtr->addNetAction(Net::Download::makeByteArray(thirdPartyUrl, thirdPartyModpacksXmlFileData)); QObject::connect(jobPtr.get(), &NetJob::succeeded, this, &PackFetchTask::fileDownloadFinished); QObject::connect(jobPtr.get(), &NetJob::failed, this, &PackFetchTask::fileDownloadFailed); @@ -64,22 +64,19 @@ void PackFetchTask::fetch() jobPtr->start(); } -void PackFetchTask::fetchPrivate(const QStringList & toFetch) +void PackFetchTask::fetchPrivate(const QStringList& toFetch) { QString privatePackBaseUrl = BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1.xml"; - for (auto &packCode: toFetch) - { - QByteArray *data = new QByteArray(); - NetJob *job = new NetJob("Fetching private pack", m_network); + for (auto& packCode : toFetch) { + auto data = std::make_shared(); + NetJob* job = new NetJob("Fetching private pack", m_network); job->addNetAction(Net::Download::makeByteArray(privatePackBaseUrl.arg(packCode), data)); - QObject::connect(job, &NetJob::succeeded, this, [this, job, data, packCode] - { + QObject::connect(job, &NetJob::succeeded, this, [this, job, data, packCode] { ModpackList packs; parseAndAddPacks(*data, PackType::Private, packs); - foreach(Modpack currentPack, packs) - { + foreach (Modpack currentPack, packs) { currentPack.packCode = packCode; emit privateFileDownloadFinished(currentPack); } @@ -87,24 +84,20 @@ void PackFetchTask::fetchPrivate(const QStringList & toFetch) job->deleteLater(); data->clear(); - delete data; }); - QObject::connect(job, &NetJob::failed, this, [this, job, packCode, data](QString reason) - { + QObject::connect(job, &NetJob::failed, this, [this, job, packCode, data](QString reason) { emit privateFileDownloadFailed(reason, packCode); job->deleteLater(); data->clear(); - delete data; }); - QObject::connect(job, &NetJob::aborted, this, [this, job, data]{ + QObject::connect(job, &NetJob::aborted, this, [this, job, data] { emit aborted(); job->deleteLater(); data->clear(); - delete data; }); job->start(); @@ -117,27 +110,22 @@ void PackFetchTask::fileDownloadFinished() QStringList failedLists; - if(!parseAndAddPacks(publicModpacksXmlFileData, PackType::Public, publicPacks)) - { + if (!parseAndAddPacks(*publicModpacksXmlFileData, PackType::Public, publicPacks)) { failedLists.append(tr("Public Packs")); } - if(!parseAndAddPacks(thirdPartyModpacksXmlFileData, PackType::ThirdParty, thirdPartyPacks)) - { + if (!parseAndAddPacks(*thirdPartyModpacksXmlFileData, PackType::ThirdParty, thirdPartyPacks)) { failedLists.append(tr("Third Party Packs")); } - if(failedLists.size() > 0) - { + if (failedLists.size() > 0) { emit failed(tr("Failed to download some pack lists: %1").arg(failedLists.join("\n- "))); - } - else - { + } else { emit finished(publicPacks, thirdPartyPacks); } } -bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, ModpackList &list) +bool PackFetchTask::parseAndAddPacks(QByteArray& data, PackType packType, ModpackList& list) { QDomDocument doc; @@ -145,8 +133,7 @@ bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, Modpac int errorLine = -1; int errorCol = -1; - if(!doc.setContent(data, false, &errorMsg, &errorLine, &errorCol)) - { + if (!doc.setContent(data, false, &errorMsg, &errorLine, &errorCol)) { auto fullErrMsg = QString("Failed to fetch modpack data: %1 %2:%3!").arg(errorMsg).arg(errorLine).arg(errorCol); qWarning() << fullErrMsg; data.clear(); @@ -154,8 +141,7 @@ bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, Modpac } QDomNodeList nodes = doc.elementsByTagName("modpack"); - for(int i = 0; i < nodes.length(); i++) - { + for (int i = 0; i < nodes.length(); i++) { QDomElement element = nodes.at(i).toElement(); Modpack modpack; @@ -169,26 +155,20 @@ bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, Modpac modpack.broken = false; modpack.bugged = false; - //remove empty if the xml is bugged - for(QString curr : modpack.oldVersions) - { - if(curr.isNull() || curr.isEmpty()) - { + // remove empty if the xml is bugged + for (QString curr : modpack.oldVersions) { + if (curr.isNull() || curr.isEmpty()) { modpack.oldVersions.removeAll(curr); modpack.bugged = true; qWarning() << "Removed some empty versions from" << modpack.name; } } - if(modpack.oldVersions.size() < 1) - { - if(!modpack.currentVersion.isNull() && !modpack.currentVersion.isEmpty()) - { + if (modpack.oldVersions.size() < 1) { + if (!modpack.currentVersion.isNull() && !modpack.currentVersion.isEmpty()) { modpack.oldVersions.append(modpack.currentVersion); qWarning() << "Added current version to oldVersions because oldVersions was empty! (" + modpack.name + ")"; - } - else - { + } else { modpack.broken = true; qWarning() << "Broken pack:" << modpack.name << " => No valid version!"; } @@ -218,4 +198,4 @@ void PackFetchTask::fileDownloadAborted() emit aborted(); } -} +} // namespace LegacyFTB diff --git a/launcher/modplatform/legacy_ftb/PackFetchTask.h b/launcher/modplatform/legacy_ftb/PackFetchTask.h index 8f3c4f3b..f2116ce9 100644 --- a/launcher/modplatform/legacy_ftb/PackFetchTask.h +++ b/launcher/modplatform/legacy_ftb/PackFetchTask.h @@ -1,41 +1,41 @@ #pragma once -#include "net/NetJob.h" -#include #include #include +#include +#include #include "PackHelpers.h" +#include "net/NetJob.h" namespace LegacyFTB { class PackFetchTask : public QObject { - Q_OBJECT -public: - PackFetchTask(shared_qobject_ptr network) : QObject(nullptr), m_network(network) {}; + public: + PackFetchTask(shared_qobject_ptr network) : QObject(nullptr), m_network(network){}; virtual ~PackFetchTask() = default; void fetch(); - void fetchPrivate(const QStringList &toFetch); + void fetchPrivate(const QStringList& toFetch); -private: + private: shared_qobject_ptr m_network; NetJob::Ptr jobPtr; - QByteArray publicModpacksXmlFileData; - QByteArray thirdPartyModpacksXmlFileData; + std::shared_ptr publicModpacksXmlFileData = std::make_shared(); + std::shared_ptr thirdPartyModpacksXmlFileData = std::make_shared(); - bool parseAndAddPacks(QByteArray &data, PackType packType, ModpackList &list); + bool parseAndAddPacks(QByteArray& data, PackType packType, ModpackList& list); ModpackList publicPacks; ModpackList thirdPartyPacks; -protected slots: + protected slots: void fileDownloadFinished(); void fileDownloadFailed(QString reason); void fileDownloadAborted(); -signals: + signals: void finished(ModpackList publicPacks, ModpackList thirdPartyPacks); void failed(QString reason); void aborted(); @@ -44,4 +44,4 @@ signals: void privateFileDownloadFailed(QString reason, QString packCode); }; -} +} // namespace LegacyFTB diff --git a/launcher/modplatform/modrinth/ModrinthAPI.cpp b/launcher/modplatform/modrinth/ModrinthAPI.cpp index 29e3d129..364cf3f3 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.cpp +++ b/launcher/modplatform/modrinth/ModrinthAPI.cpp @@ -9,19 +9,17 @@ #include "net/NetJob.h" #include "net/Upload.h" -Task::Ptr ModrinthAPI::currentVersion(QString hash, QString hash_format, QByteArray* response) +Task::Ptr ModrinthAPI::currentVersion(QString hash, QString hash_format, std::shared_ptr response) { auto netJob = makeShared(QString("Modrinth::GetCurrentVersion"), APPLICATION->network()); netJob->addNetAction(Net::Download::makeByteArray( QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1?algorithm=%2").arg(hash, hash_format), response)); - QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); - return netJob; } -Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_format, QByteArray* response) +Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_format, std::shared_ptr response) { auto netJob = makeShared(QString("Modrinth::GetCurrentVersions"), APPLICATION->network()); @@ -35,8 +33,6 @@ Task::Ptr ModrinthAPI::currentVersions(const QStringList& hashes, QString hash_f netJob->addNetAction(Net::Upload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files"), response, body_raw)); - QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); - return netJob; } @@ -44,7 +40,7 @@ Task::Ptr ModrinthAPI::latestVersion(QString hash, QString hash_format, std::optional> mcVersions, std::optional loaders, - QByteArray* response) + std::shared_ptr response) { auto netJob = makeShared(QString("Modrinth::GetLatestVersion"), APPLICATION->network()); @@ -67,8 +63,6 @@ Task::Ptr ModrinthAPI::latestVersion(QString hash, netJob->addNetAction(Net::Upload::makeByteArray( QString(BuildConfig.MODRINTH_PROD_URL + "/version_file/%1/update?algorithm=%2").arg(hash, hash_format), response, body_raw)); - QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); - return netJob; } @@ -76,7 +70,7 @@ Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes, QString hash_format, std::optional> mcVersions, std::optional loaders, - QByteArray* response) + std::shared_ptr response) { auto netJob = makeShared(QString("Modrinth::GetLatestVersions"), APPLICATION->network()); @@ -101,22 +95,16 @@ Task::Ptr ModrinthAPI::latestVersions(const QStringList& hashes, netJob->addNetAction(Net::Upload::makeByteArray(QString(BuildConfig.MODRINTH_PROD_URL + "/version_files/update"), response, body_raw)); - QObject::connect(netJob.get(), &NetJob::finished, [response] { delete response; }); - return netJob; } -Task::Ptr ModrinthAPI::getProjects(QStringList addonIds, QByteArray* response) const +Task::Ptr ModrinthAPI::getProjects(QStringList addonIds, std::shared_ptr response) const { auto netJob = makeShared(QString("Modrinth::GetProjects"), APPLICATION->network()); auto searchUrl = getMultipleModInfoURL(addonIds); netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response)); - QObject::connect(netJob.get(), &NetJob::finished, [response, netJob] { - delete response; - }); - return netJob; } diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index b91ac5c1..98f20b51 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -12,27 +12,23 @@ class ModrinthAPI : public NetworkResourceAPI { public: - auto currentVersion(QString hash, - QString hash_format, - QByteArray* response) -> Task::Ptr; + auto currentVersion(QString hash, QString hash_format, std::shared_ptr response) -> Task::Ptr; - auto currentVersions(const QStringList& hashes, - QString hash_format, - QByteArray* response) -> Task::Ptr; + auto currentVersions(const QStringList& hashes, QString hash_format, std::shared_ptr response) -> Task::Ptr; auto latestVersion(QString hash, QString hash_format, std::optional> mcVersions, std::optional loaders, - QByteArray* response) -> Task::Ptr; + std::shared_ptr response) -> Task::Ptr; auto latestVersions(const QStringList& hashes, QString hash_format, - std::optional> mcVersions, - std::optional loaders, - QByteArray* response) -> Task::Ptr; + std::optional> mcVersions, + std::optional loaders, + std::shared_ptr response) -> Task::Ptr; - Task::Ptr getProjects(QStringList addonIds, QByteArray* response) const override; + Task::Ptr getProjects(QStringList addonIds, std::shared_ptr response) const override; public: [[nodiscard]] auto getSortingMethods() const -> QList override; diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index 4fe91ce7..6a3f12f9 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -71,7 +71,7 @@ void ModrinthCheckUpdate::executeTask() hashing_task.start(); loop.exec(); - auto* response = new QByteArray(); + auto response = std::make_shared(); auto job = api.latestVersions(hashes, best_hash_type, m_game_versions, m_loaders, response); QEventLoop lock; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index bff9bf42..c607bb89 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -157,7 +157,7 @@ void ModrinthPackExportTask::makeApiRequest() if (pendingHashes.isEmpty()) buildZip(); else { - QByteArray* response = new QByteArray; + auto response = std::make_shared(); task = api.currentVersions(pendingHashes.values(), "sha512", response); connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); connect(task.get(), &NetJob::failed, this, &ModrinthPackExportTask::emitFailed); @@ -165,7 +165,7 @@ void ModrinthPackExportTask::makeApiRequest() } } -void ModrinthPackExportTask::parseApiResponse(const QByteArray* response) +void ModrinthPackExportTask::parseApiResponse(const std::shared_ptr response) { task = nullptr; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h index af00ffaa..96f292c1 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h @@ -69,7 +69,7 @@ class ModrinthPackExportTask : public Task { void collectFiles(); void collectHashes(); void makeApiRequest(); - void parseApiResponse(const QByteArray* response); + void parseApiResponse(const std::shared_ptr response); void buildZip(); void finish(); diff --git a/launcher/modplatform/technic/SolderPackInstallTask.cpp b/launcher/modplatform/technic/SolderPackInstallTask.cpp index c26d6a5a..6a05d17a 100644 --- a/launcher/modplatform/technic/SolderPackInstallTask.cpp +++ b/launcher/modplatform/technic/SolderPackInstallTask.cpp @@ -37,20 +37,19 @@ #include #include -#include #include +#include -#include "TechnicPackProcessor.h" #include "SolderPackManifest.h" +#include "TechnicPackProcessor.h" #include "net/ChecksumValidator.h" -Technic::SolderPackInstallTask::SolderPackInstallTask( - shared_qobject_ptr network, - const QUrl &solderUrl, - const QString &pack, - const QString &version, - const QString &minecraftVersion -) { +Technic::SolderPackInstallTask::SolderPackInstallTask(shared_qobject_ptr network, + const QUrl& solderUrl, + const QString& pack, + const QString& version, + const QString& minecraftVersion) +{ m_solderUrl = solderUrl; m_pack = pack; m_version = version; @@ -58,9 +57,9 @@ Technic::SolderPackInstallTask::SolderPackInstallTask( m_minecraftVersion = minecraftVersion; } -bool Technic::SolderPackInstallTask::abort() { - if(m_abortable) - { +bool Technic::SolderPackInstallTask::abort() +{ + if (m_abortable) { return m_filesNetJob->abort(); } return false; @@ -72,7 +71,7 @@ void Technic::SolderPackInstallTask::executeTask() m_filesNetJob.reset(new NetJob(tr("Resolving modpack files"), m_network)); auto sourceUrl = QString("%1/modpack/%2/%3").arg(m_solderUrl.toString(), m_pack, m_version); - m_filesNetJob->addNetAction(Net::Download::makeByteArray(sourceUrl, &m_response)); + m_filesNetJob->addNetAction(Net::Download::makeByteArray(sourceUrl, m_response)); auto job = m_filesNetJob.get(); connect(job, &NetJob::succeeded, this, &Technic::SolderPackInstallTask::fileListSucceeded); @@ -85,11 +84,11 @@ void Technic::SolderPackInstallTask::fileListSucceeded() { setStatus(tr("Downloading modpack")); - QJsonParseError parse_error {}; - QJsonDocument doc = QJsonDocument::fromJson(m_response, &parse_error); + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*m_response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from Solder at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << m_response; + qWarning() << *m_response; return; } auto obj = doc.object(); @@ -110,7 +109,7 @@ void Technic::SolderPackInstallTask::fileListSucceeded() m_filesNetJob.reset(new NetJob(tr("Downloading modpack"), m_network)); int i = 0; - for (const auto &mod : build.mods) { + for (const auto& mod : build.mods) { auto path = FS::PathCombine(m_outputDir.path(), QString("%1").arg(i)); auto dl = Net::Download::makeFile(mod.url, path); diff --git a/launcher/modplatform/technic/SolderPackInstallTask.h b/launcher/modplatform/technic/SolderPackInstallTask.h index aa14ce88..f2c6a83a 100644 --- a/launcher/modplatform/technic/SolderPackInstallTask.h +++ b/launcher/modplatform/technic/SolderPackInstallTask.h @@ -40,45 +40,48 @@ #include #include +#include -namespace Technic -{ - class SolderPackInstallTask : public InstanceTask - { - Q_OBJECT - public: - explicit SolderPackInstallTask(shared_qobject_ptr network, const QUrl &solderUrl, const QString& pack, const QString& version, const QString &minecraftVersion); +namespace Technic { +class SolderPackInstallTask : public InstanceTask { + Q_OBJECT + public: + explicit SolderPackInstallTask(shared_qobject_ptr network, + const QUrl& solderUrl, + const QString& pack, + const QString& version, + const QString& minecraftVersion); - bool canAbort() const override { return true; } - bool abort() override; + bool canAbort() const override { return true; } + bool abort() override; - protected: - //! Entry point for tasks. - virtual void executeTask() override; + protected: + //! Entry point for tasks. + virtual void executeTask() override; - private slots: - void fileListSucceeded(); - void downloadSucceeded(); - void downloadFailed(QString reason); - void downloadProgressChanged(qint64 current, qint64 total); - void downloadAborted(); - void extractFinished(); - void extractAborted(); + private slots: + void fileListSucceeded(); + void downloadSucceeded(); + void downloadFailed(QString reason); + void downloadProgressChanged(qint64 current, qint64 total); + void downloadAborted(); + void extractFinished(); + void extractAborted(); - private: - bool m_abortable = false; + private: + bool m_abortable = false; - shared_qobject_ptr m_network; + shared_qobject_ptr m_network; - NetJob::Ptr m_filesNetJob; - QUrl m_solderUrl; - QString m_pack; - QString m_version; - QString m_minecraftVersion; - QByteArray m_response; - QTemporaryDir m_outputDir; - int m_modCount; - QFuture m_extractFuture; - QFutureWatcher m_extractFutureWatcher; - }; -} + NetJob::Ptr m_filesNetJob; + QUrl m_solderUrl; + QString m_pack; + QString m_version; + QString m_minecraftVersion; + std::shared_ptr m_response = std::make_shared(); + QTemporaryDir m_outputDir; + int m_modCount; + QFuture m_extractFuture; + QFutureWatcher m_extractFutureWatcher; +}; +} // namespace Technic diff --git a/launcher/net/ByteArraySink.h b/launcher/net/ByteArraySink.h index 728193b3..d6b17d60 100644 --- a/launcher/net/ByteArraySink.h +++ b/launcher/net/ByteArraySink.h @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher - Minecraft Launcher * Copyright (c) 2022 flowln + * Copyright (c) 2023 Trial97 * * 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 @@ -46,7 +47,7 @@ namespace Net { */ class ByteArraySink : public Sink { public: - ByteArraySink(QByteArray* output) : m_output(output){}; + ByteArraySink(std::shared_ptr output) : m_output(output){}; virtual ~ByteArraySink() = default; @@ -93,6 +94,6 @@ class ByteArraySink : public Sink { auto hasLocalData() -> bool override { return false; } private: - QByteArray* m_output; + std::shared_ptr m_output; }; } // namespace Net diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index 7f8d3a06..4ea45c63 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -41,6 +41,7 @@ #include #include +#include #include "ByteArraySink.h" #include "ChecksumValidator.h" @@ -69,7 +70,7 @@ auto Download::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Down return dl; } -auto Download::makeByteArray(QUrl url, QByteArray* output, Options options) -> Download::Ptr +auto Download::makeByteArray(QUrl url, std::shared_ptr output, Options options) -> Download::Ptr { auto dl = makeShared(); dl->m_url = url; diff --git a/launcher/net/Download.h b/launcher/net/Download.h index 920164a3..2e861732 100644 --- a/launcher/net/Download.h +++ b/launcher/net/Download.h @@ -60,7 +60,7 @@ class Download : public NetAction { ~Download() override = default; static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr; - static auto makeByteArray(QUrl url, QByteArray* output, Options options = Option::NoOptions) -> Download::Ptr; + static auto makeByteArray(QUrl url, std::shared_ptr output, Options options = Option::NoOptions) -> Download::Ptr; static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; public: diff --git a/launcher/net/Upload.cpp b/launcher/net/Upload.cpp index 4f9553ed..3f6f5829 100644 --- a/launcher/net/Upload.cpp +++ b/launcher/net/Upload.cpp @@ -39,218 +39,226 @@ #include "Upload.h" #include -#include "ByteArraySink.h" -#include "BuildConfig.h" #include "Application.h" +#include "BuildConfig.h" +#include "ByteArraySink.h" #include "net/Logging.h" namespace Net { - bool Upload::abort() - { - if (m_reply) { - m_reply->abort(); - } else { - m_state = State::AbortedByUser; - } - return true; +bool Upload::abort() +{ + if (m_reply) { + m_reply->abort(); + } else { + m_state = State::AbortedByUser; } + return true; +} - void Upload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { - setProgress(bytesReceived, bytesTotal); - } +void Upload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + setProgress(bytesReceived, bytesTotal); +} - void Upload::downloadError(QNetworkReply::NetworkError error) { - if (error == QNetworkReply::OperationCanceledError) { - qCCritical(taskUploadLogC) << getUid().toString() << "Aborted " << m_url.toString(); - m_state = State::AbortedByUser; - } else { - // error happened during download. - qCCritical(taskUploadLogC) << getUid().toString() << "Failed " << m_url.toString() << " with reason " << error; - m_state = State::Failed; - } +void Upload::downloadError(QNetworkReply::NetworkError error) +{ + if (error == QNetworkReply::OperationCanceledError) { + qCCritical(taskUploadLogC) << getUid().toString() << "Aborted " << m_url.toString(); + m_state = State::AbortedByUser; + } else { + // error happened during download. + qCCritical(taskUploadLogC) << getUid().toString() << "Failed " << m_url.toString() << " with reason " << error; + m_state = State::Failed; } +} - void Upload::sslErrors(const QList &errors) { - int i = 1; - for (const auto& error : errors) { - qCCritical(taskUploadLogC) << getUid().toString() << "Upload" << m_url.toString() << "SSL Error #" << i << " : " << error.errorString(); - auto cert = error.certificate(); - qCCritical(taskUploadLogC) << getUid().toString() << "Certificate in question:\n" << cert.toText(); - i++; - } +void Upload::sslErrors(const QList& errors) +{ + int i = 1; + for (const auto& error : errors) { + qCCritical(taskUploadLogC) << getUid().toString() << "Upload" << m_url.toString() << "SSL Error #" << i << " : " + << error.errorString(); + auto cert = error.certificate(); + qCCritical(taskUploadLogC) << getUid().toString() << "Certificate in question:\n" << cert.toText(); + i++; } +} - bool Upload::handleRedirect() - { - QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl(); - if (!redirect.isValid()) { - if (!m_reply->hasRawHeader("Location")) { - // no redirect -> it's fine to continue - return false; - } - // there is a Location header, but it's not correct. we need to apply some workarounds... - QByteArray redirectBA = m_reply->rawHeader("Location"); - if (redirectBA.size() == 0) { - // empty, yet present redirect header? WTF? - return false; - } - QString redirectStr = QString::fromUtf8(redirectBA); - - if (redirectStr.startsWith("//")) { - /* - * IF the URL begins with //, we need to insert the URL scheme. - * See: https://bugreports.qt.io/browse/QTBUG-41061 - * See: http://tools.ietf.org/html/rfc3986#section-4.2 - */ - redirectStr = m_reply->url().scheme() + ":" + redirectStr; - } else if (redirectStr.startsWith("/")) { - /* - * IF the URL begins with /, we need to process it as a relative URL - */ - auto url = m_reply->url(); - url.setPath(redirectStr, QUrl::TolerantMode); - redirectStr = url.toString(); - } +bool Upload::handleRedirect() +{ + QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl(); + if (!redirect.isValid()) { + if (!m_reply->hasRawHeader("Location")) { + // no redirect -> it's fine to continue + return false; + } + // there is a Location header, but it's not correct. we need to apply some workarounds... + QByteArray redirectBA = m_reply->rawHeader("Location"); + if (redirectBA.size() == 0) { + // empty, yet present redirect header? WTF? + return false; + } + QString redirectStr = QString::fromUtf8(redirectBA); + if (redirectStr.startsWith("//")) { /* - * Next, make sure the URL is parsed in tolerant mode. Qt doesn't parse the location header in tolerant mode, which causes issues. - * FIXME: report Qt bug for this + * IF the URL begins with //, we need to insert the URL scheme. + * See: https://bugreports.qt.io/browse/QTBUG-41061 + * See: http://tools.ietf.org/html/rfc3986#section-4.2 */ - redirect = QUrl(redirectStr, QUrl::TolerantMode); - if (!redirect.isValid()) { - qCWarning(taskUploadLogC) << getUid().toString() << "Failed to parse redirect URL:" << redirectStr; - downloadError(QNetworkReply::ProtocolFailure); - return false; - } - qCDebug(taskUploadLogC) << getUid().toString() << "Fixed location header:" << redirect; - } else { - qCDebug(taskUploadLogC) << getUid().toString() << "Location header:" << redirect; + redirectStr = m_reply->url().scheme() + ":" + redirectStr; + } else if (redirectStr.startsWith("/")) { + /* + * IF the URL begins with /, we need to process it as a relative URL + */ + auto url = m_reply->url(); + url.setPath(redirectStr, QUrl::TolerantMode); + redirectStr = url.toString(); } - m_url = QUrl(redirect.toString()); - qCDebug(taskUploadLogC) << getUid().toString() << "Following redirect to " << m_url.toString(); - startAction(m_network); - return true; - } - - void Upload::downloadFinished() { - // handle HTTP redirection first - // very unlikely for post requests, still can happen - if (handleRedirect()) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload redirected:" << m_url.toString(); - return; + /* + * Next, make sure the URL is parsed in tolerant mode. Qt doesn't parse the location header in tolerant mode, which causes issues. + * FIXME: report Qt bug for this + */ + redirect = QUrl(redirectStr, QUrl::TolerantMode); + if (!redirect.isValid()) { + qCWarning(taskUploadLogC) << getUid().toString() << "Failed to parse redirect URL:" << redirectStr; + downloadError(QNetworkReply::ProtocolFailure); + return false; } + qCDebug(taskUploadLogC) << getUid().toString() << "Fixed location header:" << redirect; + } else { + qCDebug(taskUploadLogC) << getUid().toString() << "Location header:" << redirect; + } - // if the download failed before this point ... - if (m_state == State::Succeeded) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed but we are allowed to proceed:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit succeeded(); - return; - } else if (m_state == State::Failed) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed in previous step:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit failed(""); - return; - } else if (m_state == State::AbortedByUser) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload aborted in previous step:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit aborted(); - return; - } + m_url = QUrl(redirect.toString()); + qCDebug(taskUploadLogC) << getUid().toString() << "Following redirect to " << m_url.toString(); + startAction(m_network); + return true; +} - // make sure we got all the remaining data, if any - auto data = m_reply->readAll(); - if (data.size()) { - qCDebug(taskUploadLogC) << getUid().toString() << "Writing extra" << data.size() << "bytes"; - m_state = m_sink->write(data); - } +void Upload::downloadFinished() +{ + // handle HTTP redirection first + // very unlikely for post requests, still can happen + if (handleRedirect()) { + qCDebug(taskUploadLogC) << getUid().toString() << "Upload redirected:" << m_url.toString(); + return; + } - // otherwise, finalize the whole graph - m_state = m_sink->finalize(*m_reply.get()); - if (m_state != State::Succeeded) { - qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed to finalize:" << m_url.toString(); - m_sink->abort(); - m_reply.reset(); - emit failed(""); - return; - } + // if the download failed before this point ... + if (m_state == State::Succeeded) { + qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed but we are allowed to proceed:" << m_url.toString(); + m_sink->abort(); m_reply.reset(); - qCDebug(taskUploadLogC) << getUid().toString() << "Upload succeeded:" << m_url.toString(); emit succeeded(); + return; + } else if (m_state == State::Failed) { + qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed in previous step:" << m_url.toString(); + m_sink->abort(); + m_reply.reset(); + emit failed(""); + return; + } else if (m_state == State::AbortedByUser) { + qCDebug(taskUploadLogC) << getUid().toString() << "Upload aborted in previous step:" << m_url.toString(); + m_sink->abort(); + m_reply.reset(); + emit aborted(); + return; } - void Upload::downloadReadyRead() { - if (m_state == State::Running) { - auto data = m_reply->readAll(); - m_state = m_sink->write(data); - } + // make sure we got all the remaining data, if any + auto data = m_reply->readAll(); + if (data.size()) { + qCDebug(taskUploadLogC) << getUid().toString() << "Writing extra" << data.size() << "bytes"; + m_state = m_sink->write(data); + } + + // otherwise, finalize the whole graph + m_state = m_sink->finalize(*m_reply.get()); + if (m_state != State::Succeeded) { + qCDebug(taskUploadLogC) << getUid().toString() << "Upload failed to finalize:" << m_url.toString(); + m_sink->abort(); + m_reply.reset(); + emit failed(""); + return; } + m_reply.reset(); + qCDebug(taskUploadLogC) << getUid().toString() << "Upload succeeded:" << m_url.toString(); + emit succeeded(); +} - void Upload::executeTask() { - setStatus(tr("Uploading %1").arg(m_url.toString())); +void Upload::downloadReadyRead() +{ + if (m_state == State::Running) { + auto data = m_reply->readAll(); + m_state = m_sink->write(data); + } +} - if (m_state == State::AbortedByUser) { - qCWarning(taskUploadLogC) << getUid().toString() << "Attempt to start an aborted Upload:" << m_url.toString(); - emit aborted(); +void Upload::executeTask() +{ + setStatus(tr("Uploading %1").arg(m_url.toString())); + + if (m_state == State::AbortedByUser) { + qCWarning(taskUploadLogC) << getUid().toString() << "Attempt to start an aborted Upload:" << m_url.toString(); + emit aborted(); + return; + } + QNetworkRequest request(m_url); + m_state = m_sink->init(request); + switch (m_state) { + case State::Succeeded: + emitSucceeded(); + qCDebug(taskUploadLogC) << getUid().toString() << "Upload cache hit " << m_url.toString(); return; - } - QNetworkRequest request(m_url); - m_state = m_sink->init(request); - switch (m_state) { - case State::Succeeded: - emitSucceeded(); - qCDebug(taskUploadLogC) << getUid().toString() << "Upload cache hit " << m_url.toString(); - return; - case State::Running: - qCDebug(taskUploadLogC) << getUid().toString() << "Uploading " << m_url.toString(); - break; - case State::Inactive: - case State::Failed: - emitFailed(""); - return; - case State::AbortedByUser: - emitAborted(); - return; - } + case State::Running: + qCDebug(taskUploadLogC) << getUid().toString() << "Uploading " << m_url.toString(); + break; + case State::Inactive: + case State::Failed: + emitFailed(""); + return; + case State::AbortedByUser: + emitAborted(); + return; + } - request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8()); - // TODO remove duplication - if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) { - request.setRawHeader("x-api-key", APPLICATION->getFlameAPIKey().toUtf8()); - } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || - request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { - QString token = APPLICATION->getModrinthAPIToken(); - if (!token.isNull()) - request.setRawHeader("Authorization", token.toUtf8()); - } + request.setHeader(QNetworkRequest::UserAgentHeader, APPLICATION->getUserAgent().toUtf8()); + // TODO remove duplication + if (APPLICATION->capabilities() & Application::SupportsFlame && request.url().host() == QUrl(BuildConfig.FLAME_BASE_URL).host()) { + request.setRawHeader("x-api-key", APPLICATION->getFlameAPIKey().toUtf8()); + } else if (request.url().host() == QUrl(BuildConfig.MODRINTH_PROD_URL).host() || + request.url().host() == QUrl(BuildConfig.MODRINTH_STAGING_URL).host()) { + QString token = APPLICATION->getModrinthAPIToken(); + if (!token.isNull()) + request.setRawHeader("Authorization", token.toUtf8()); + } - //TODO other types of post requests ? - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QNetworkReply* rep = m_network->post(request, m_post_data); + // TODO other types of post requests ? + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + QNetworkReply* rep = m_network->post(request, m_post_data); - m_reply.reset(rep); - connect(rep, &QNetworkReply::downloadProgress, this, &Upload::downloadProgress); - connect(rep, &QNetworkReply::finished, this, &Upload::downloadFinished); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 - connect(rep, &QNetworkReply::errorOccurred, this, &Upload::downloadError); + m_reply.reset(rep); + connect(rep, &QNetworkReply::downloadProgress, this, &Upload::downloadProgress); + connect(rep, &QNetworkReply::finished, this, &Upload::downloadFinished); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 + connect(rep, &QNetworkReply::errorOccurred, this, &Upload::downloadError); #else - connect(rep, QOverload::of(&QNetworkReply::error), this, &Upload::downloadError); + connect(rep, QOverload::of(&QNetworkReply::error), this, &Upload::downloadError); #endif - connect(rep, &QNetworkReply::sslErrors, this, &Upload::sslErrors); - connect(rep, &QNetworkReply::readyRead, this, &Upload::downloadReadyRead); - } + connect(rep, &QNetworkReply::sslErrors, this, &Upload::sslErrors); + connect(rep, &QNetworkReply::readyRead, this, &Upload::downloadReadyRead); +} - Upload::Ptr Upload::makeByteArray(QUrl url, QByteArray *output, QByteArray m_post_data) { - auto up = makeShared(); - up->m_url = std::move(url); - up->m_sink.reset(new ByteArraySink(output)); - up->m_post_data = std::move(m_post_data); - return up; - } -} // Net +Upload::Ptr Upload::makeByteArray(QUrl url, std::shared_ptr output, QByteArray m_post_data) +{ + auto up = makeShared(); + up->m_url = std::move(url); + up->m_sink.reset(new ByteArraySink(output)); + up->m_post_data = std::move(m_post_data); + return up; +} +} // namespace Net diff --git a/launcher/net/Upload.h b/launcher/net/Upload.h index e8f0ea40..0b0c9497 100644 --- a/launcher/net/Upload.h +++ b/launcher/net/Upload.h @@ -42,31 +42,31 @@ namespace Net { - class Upload : public NetAction { - Q_OBJECT +class Upload : public NetAction { + Q_OBJECT - public: - using Ptr = shared_qobject_ptr; + public: + using Ptr = shared_qobject_ptr; - static Upload::Ptr makeByteArray(QUrl url, QByteArray *output, QByteArray m_post_data); - auto abort() -> bool override; - auto canAbort() const -> bool override { return true; }; + static Upload::Ptr makeByteArray(QUrl url, std::shared_ptr output, QByteArray m_post_data); + auto abort() -> bool override; + auto canAbort() const -> bool override { return true; }; - protected slots: - void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; - void downloadError(QNetworkReply::NetworkError error) override; - void sslErrors(const QList & errors) override; - void downloadFinished() override; - void downloadReadyRead() override; + protected slots: + void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; + void downloadError(QNetworkReply::NetworkError error) override; + void sslErrors(const QList& errors) override; + void downloadFinished() override; + void downloadReadyRead() override; - public slots: - void executeTask() override; - private: - std::unique_ptr m_sink; - QByteArray m_post_data; + public slots: + void executeTask() override; - bool handleRedirect(); - }; + private: + std::unique_ptr m_sink; + QByteArray m_post_data; -} // Net + bool handleRedirect(); +}; +} // namespace Net diff --git a/launcher/news/NewsChecker.cpp b/launcher/news/NewsChecker.cpp index 1f1520d0..4f02bf5e 100644 --- a/launcher/news/NewsChecker.cpp +++ b/launcher/news/NewsChecker.cpp @@ -58,7 +58,7 @@ void NewsChecker::reloadNews() qDebug() << "Reloading news."; NetJob::Ptr job{ new NetJob("News RSS Feed", m_network) }; - job->addNetAction(Net::Download::makeByteArray(m_feedUrl, &newsData)); + job->addNetAction(Net::Download::makeByteArray(m_feedUrl, newsData)); QObject::connect(job.get(), &NetJob::succeeded, this, &NewsChecker::rssDownloadFinished); QObject::connect(job.get(), &NetJob::failed, this, &NewsChecker::rssDownloadFailed); m_newsNetJob.reset(job); @@ -79,32 +79,27 @@ void NewsChecker::rssDownloadFinished() int errorCol = -1; // Parse the XML. - if (!doc.setContent(newsData, false, &errorMsg, &errorLine, &errorCol)) - { + if (!doc.setContent(*newsData, false, &errorMsg, &errorLine, &errorCol)) { QString fullErrorMsg = QString("Error parsing RSS feed XML. %1 at %2:%3.").arg(errorMsg).arg(errorLine).arg(errorCol); fail(fullErrorMsg); - newsData.clear(); + newsData->clear(); return; } - newsData.clear(); + newsData->clear(); } // If the parsing succeeded, read it. QDomNodeList items = doc.elementsByTagName("entry"); m_newsEntries.clear(); - for (int i = 0; i < items.length(); i++) - { + for (int i = 0; i < items.length(); i++) { QDomElement element = items.at(i).toElement(); NewsEntryPtr entry; entry.reset(new NewsEntry()); QString errorMsg = "An unknown error occurred."; - if (NewsEntry::fromXmlElement(element, entry.get(), &errorMsg)) - { + if (NewsEntry::fromXmlElement(element, entry.get(), &errorMsg)) { qDebug() << "Loaded news entry" << entry->title; m_newsEntries.append(entry); - } - else - { + } else { qWarning() << "Failed to load news entry at index" << i << ":" << errorMsg; } } diff --git a/launcher/news/NewsChecker.h b/launcher/news/NewsChecker.h index 8467a541..41babfff 100644 --- a/launcher/news/NewsChecker.h +++ b/launcher/news/NewsChecker.h @@ -85,7 +85,7 @@ protected: /* data */ //! True if news has been loaded. bool m_loadedNews; - QByteArray newsData; + std::shared_ptr newsData = std::make_shared(); /*! * Gets the error message that was given last time the news was loaded. diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index d0701a7a..e0a7314f 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -226,7 +226,7 @@ void ModrinthManagedPackPage::parseManagedPack() QString id = m_inst->getManagedPackID(); - m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response.get())); + m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/project/%2/version").arg(BuildConfig.MODRINTH_PROD_URL, id), response)); QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] { QJsonParseError parse_error{}; @@ -369,7 +369,7 @@ void FlameManagedPackPage::parseManagedPack() QString id = m_inst->getManagedPackID(); - m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response.get())); + m_fetch_job->addNetAction(Net::Download::makeByteArray(QString("%1/mods/%2/files").arg(BuildConfig.FLAME_BASE_URL, id), response)); QObject::connect(m_fetch_job.get(), &NetJob::succeeded, this, [this, response, id] { QJsonParseError parse_error{}; diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp index 9ad26f47..2ab86529 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp @@ -88,7 +88,7 @@ void ListModel::request() auto netJob = makeShared("Atl::Request", APPLICATION->network()); auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/json/packsnew.json"); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response)); + netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), response)); jobPtr = netJob; jobPtr->start(); @@ -101,10 +101,10 @@ void ListModel::requestFinished() jobPtr.reset(); QJsonParseError parse_error; - QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if(parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << response; + qWarning() << *response; return; } @@ -120,7 +120,7 @@ void ListModel::requestFinished() ATLauncher::loadIndexedPack(pack, packObj); } catch (const JSONValidationError &e) { - qDebug() << QString::fromUtf8(response); + qDebug() << QString::fromUtf8(*response); qWarning() << "Error while reading pack manifest from ATLauncher: " << e.cause(); return; } diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.h b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.h index 2574c48d..ed1fdc9f 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.h @@ -18,42 +18,41 @@ #include -#include "net/NetJob.h" -#include #include +#include +#include "net/NetJob.h" namespace Atl { typedef QMap LogoMap; typedef std::function LogoCallback; -class ListModel : public QAbstractListModel -{ +class ListModel : public QAbstractListModel { Q_OBJECT -public: - ListModel(QObject *parent); + public: + ListModel(QObject* parent); virtual ~ListModel(); - int rowCount(const QModelIndex &parent) const override; - int columnCount(const QModelIndex &parent) const override; - QVariant data(const QModelIndex &index, int role) const override; + int rowCount(const QModelIndex& parent) const override; + int columnCount(const QModelIndex& parent) const override; + QVariant data(const QModelIndex& index, int role) const override; void request(); - void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback); + void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); -private slots: + private slots: void requestFinished(); void requestFailed(QString reason); void logoFailed(QString logo); void logoLoaded(QString logo, QIcon out); -private: + private: void requestLogo(QString file, QString url); -private: + private: QList modpacks; QStringList m_failedLogos; @@ -62,7 +61,7 @@ private: QMap waitingCallbacks; NetJob::Ptr jobPtr; - QByteArray response; + std::shared_ptr response = std::make_shared(); }; -} +} // namespace Atl diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp index cdb4532c..7b61daa7 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp @@ -152,7 +152,7 @@ Qt::ItemFlags AtlOptionalModListModel::flags(const QModelIndex &index) const { void AtlOptionalModListModel::useShareCode(const QString& code) { m_jobPtr.reset(new NetJob("Atl::Request", APPLICATION->network())); auto url = QString(BuildConfig.ATL_API_BASE_URL + "share-codes/" + code); - m_jobPtr->addNetAction(Net::Download::makeByteArray(QUrl(url), &m_response)); + m_jobPtr->addNetAction(Net::Download::makeByteArray(QUrl(url), m_response)); connect(m_jobPtr.get(), &NetJob::succeeded, this, &AtlOptionalModListModel::shareCodeSuccess); @@ -166,10 +166,10 @@ void AtlOptionalModListModel::shareCodeSuccess() { m_jobPtr.reset(); QJsonParseError parse_error {}; - auto doc = QJsonDocument::fromJson(m_response, &parse_error); + auto doc = QJsonDocument::fromJson(*m_response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << m_response; + qWarning() << *m_response; return; } auto obj = doc.object(); @@ -179,7 +179,7 @@ void AtlOptionalModListModel::shareCodeSuccess() { ATLauncher::loadShareCodeResponse(response, obj); } catch (const JSONValidationError& e) { - qDebug() << QString::fromUtf8(m_response); + qDebug() << QString::fromUtf8(*m_response); qWarning() << "Error while reading response from ATLauncher: " << e.cause(); return; } diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h index 8e02444e..639f0d48 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.h @@ -82,9 +82,9 @@ private: void toggleMod(ATLauncher::VersionMod mod, int index); void setMod(ATLauncher::VersionMod mod, int index, bool enable, bool shouldEmit = true); -private: + private: NetJob::Ptr m_jobPtr; - QByteArray m_response; + std::shared_ptr m_response = std::make_shared(); ATLauncher::PackVersion m_version; QVector m_mods; diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.cpp b/launcher/ui/pages/modplatform/flame/FlameModel.cpp index 5961ea02..54d0b003 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModel.cpp @@ -169,7 +169,7 @@ void ListModel::performPaginatedSearch() .arg(currentSearchTerm) .arg(currentSort + 1); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); + netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response)); jobPtr = netJob; jobPtr->start(); QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished); @@ -202,11 +202,11 @@ void Flame::ListModel::searchRequestFinished() jobPtr.reset(); QJsonParseError parse_error; - QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from CurseForge at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << response; + qWarning() << *response; return; } diff --git a/launcher/ui/pages/modplatform/flame/FlameModel.h b/launcher/ui/pages/modplatform/flame/FlameModel.h index cab666cc..b3bc96b8 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModel.h +++ b/launcher/ui/pages/modplatform/flame/FlameModel.h @@ -3,46 +3,44 @@ #include #include -#include -#include #include -#include #include +#include +#include #include #include -#include +#include +#include -#include #include +#include #include namespace Flame { - typedef QMap LogoMap; typedef std::function LogoCallback; -class ListModel : public QAbstractListModel -{ +class ListModel : public QAbstractListModel { Q_OBJECT -public: - ListModel(QObject *parent); + public: + ListModel(QObject* parent); virtual ~ListModel(); - int rowCount(const QModelIndex &parent) const override; - int columnCount(const QModelIndex &parent) const override; - QVariant data(const QModelIndex &index, int role) const override; - bool setData(const QModelIndex &index, const QVariant &value, int role) override; - Qt::ItemFlags flags(const QModelIndex &index) const override; - bool canFetchMore(const QModelIndex & parent) const override; - void fetchMore(const QModelIndex & parent) override; + int rowCount(const QModelIndex& parent) const override; + int columnCount(const QModelIndex& parent) const override; + QVariant data(const QModelIndex& index, int role) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role) override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + bool canFetchMore(const QModelIndex& parent) const override; + void fetchMore(const QModelIndex& parent) override; - void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback); - void searchWithTerm(const QString & term, const int sort); + void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); + void searchWithTerm(const QString& term, const int sort); -private slots: + private slots: void performPaginatedSearch(); void logoFailed(QString logo); @@ -51,10 +49,10 @@ private slots: void searchRequestFinished(); void searchRequestFailed(QString reason); -private: + private: void requestLogo(QString file, QString url); -private: + private: QList modpacks; QStringList m_failedLogos; QStringList m_loadingLogos; @@ -64,14 +62,9 @@ private: QString currentSearchTerm; int currentSort = 0; int nextSearchOffset = 0; - enum SearchState { - None, - CanPossiblyFetchMore, - ResetRequested, - Finished - } searchState = None; + enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None; NetJob::Ptr jobPtr; - QByteArray response; + std::shared_ptr response = std::make_shared(); }; -} +} // namespace Flame diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp index f9ac4a78..cef26bb6 100644 --- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp @@ -130,7 +130,7 @@ void FlamePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) if (current.versionsLoaded == false) { qDebug() << "Loading flame modpack versions"; auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network()); - auto response = new QByteArray(); + auto response = std::make_shared(); int addonId = current.addonId; netJob->addNetAction(Net::Download::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response)); @@ -170,10 +170,7 @@ void FlamePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) } suggestCurrent(); }); - QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { - netJob->deleteLater(); - delete response; - }); + QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); }); netJob->start(); } else { for (auto version : current.versions) { diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp index 346a00b0..675589d0 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp @@ -129,27 +129,27 @@ void ModpackListModel::performPaginatedSearch() // TODO: Move to standalone API auto netJob = makeShared("Modrinth::SearchModpack", APPLICATION->network()); auto searchAllUrl = QString(BuildConfig.MODRINTH_PROD_URL + - "/search?" - "offset=%1&" - "limit=%2&" - "query=%3&" - "index=%4&" - "facets=[[\"project_type:modpack\"]]") + "/search?" + "offset=%1&" + "limit=%2&" + "query=%3&" + "index=%4&" + "facets=[[\"project_type:modpack\"]]") .arg(nextSearchOffset) .arg(m_modpacks_per_page) .arg(currentSearchTerm) .arg(currentSort); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchAllUrl), &m_all_response)); + netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchAllUrl), m_all_response)); QObject::connect(netJob.get(), &NetJob::succeeded, this, [this] { QJsonParseError parse_error_all{}; - QJsonDocument doc_all = QJsonDocument::fromJson(m_all_response, &parse_error_all); + QJsonDocument doc_all = QJsonDocument::fromJson(*m_all_response, &parse_error_all); if (parse_error_all.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from " << debugName() << " at " << parse_error_all.offset << " reason: " << parse_error_all.errorString(); - qWarning() << m_all_response; + qWarning() << *m_all_response; return; } diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h index 6e6be4b9..b9e9c3da 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthModel.h @@ -110,9 +110,9 @@ class ModpackListModel : public QAbstractListModel { NetJob::Ptr jobPtr; - QByteArray m_all_response; + std::shared_ptr m_all_response = std::make_shared(); QByteArray m_specific_response; int m_modpacks_per_page = 20; }; -} // namespace ModPlatform +} // namespace Modrinth diff --git a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp index 0bb11d83..c71dd903 100644 --- a/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp +++ b/launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp @@ -123,7 +123,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev) qDebug() << "Loading modrinth modpack information"; auto netJob = new NetJob(QString("Modrinth::PackInformation(%1)").arg(current.name), APPLICATION->network()); - auto response = new QByteArray(); + auto response = std::make_shared(); QString id = current.id; @@ -162,10 +162,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev) suggestCurrent(); }); - QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { - netJob->deleteLater(); - delete response; - }); + QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); }); netJob->start(); } else updateUI(); @@ -174,7 +171,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev) qDebug() << "Loading modrinth modpack versions"; auto netJob = new NetJob(QString("Modrinth::PackVersions(%1)").arg(current.name), APPLICATION->network()); - auto response = new QByteArray(); + auto response = std::make_shared(); QString id = current.id; @@ -217,10 +214,7 @@ void ModrinthPage::onSelectionChanged(QModelIndex curr, QModelIndex prev) suggestCurrent(); }); - QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { - netJob->deleteLater(); - delete response; - }); + QObject::connect(netJob, &NetJob::finished, this, [response, netJob] { netJob->deleteLater(); }); netJob->start(); } else { @@ -260,10 +254,8 @@ void ModrinthPage::updateUI() text += donates.join(", "); } - if (!current.extra.issuesUrl.isEmpty() - || !current.extra.sourceUrl.isEmpty() - || !current.extra.wikiUrl.isEmpty() - || !current.extra.discordUrl.isEmpty()) { + if (!current.extra.issuesUrl.isEmpty() || !current.extra.sourceUrl.isEmpty() || !current.extra.wikiUrl.isEmpty() || + !current.extra.discordUrl.isEmpty()) { text += "

" + tr("External links:") + "
"; } diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index 50f0c72d..7975fd58 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -134,7 +134,7 @@ void Technic::ListModel::performSearch() ).arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD, currentSearchTerm); searchMode = List; } - netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response)); + netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response)); jobPtr = netJob; jobPtr->start(); QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished); @@ -146,11 +146,11 @@ void Technic::ListModel::searchRequestFinished() jobPtr.reset(); QJsonParseError parse_error; - QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); - if(parse_error.error != QJsonParseError::NoError) - { - qWarning() << "Error while parsing JSON response from Technic at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << response; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from Technic at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response; return; } diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.h b/launcher/ui/pages/modplatform/technic/TechnicModel.h index 5eea124c..0f1a814e 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.h +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.h @@ -44,33 +44,32 @@ namespace Technic { typedef std::function LogoCallback; -class ListModel : public QAbstractListModel -{ +class ListModel : public QAbstractListModel { Q_OBJECT -public: - ListModel(QObject *parent); + public: + ListModel(QObject* parent); virtual ~ListModel(); virtual QVariant data(const QModelIndex& index, int role) const; virtual int columnCount(const QModelIndex& parent) const; virtual int rowCount(const QModelIndex& parent) const; - void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback); - void searchWithTerm(const QString & term); + void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback); + void searchWithTerm(const QString& term); -private slots: + private slots: void searchRequestFinished(); void searchRequestFailed(); void logoFailed(QString logo); void logoLoaded(QString logo, QString out); -private: + private: void performSearch(); void requestLogo(QString logo, QString url); -private: + private: QList modpacks; QStringList m_failedLogos; QStringList m_loadingLogos; @@ -78,17 +77,13 @@ private: QMap waitingCallbacks; QString currentSearchTerm; - enum SearchState { - None, - ResetRequested, - Finished - } searchState = None; + enum SearchState { None, ResetRequested, Finished } searchState = None; enum SearchMode { List, Single, } searchMode = List; NetJob::Ptr jobPtr; - QByteArray response; + std::shared_ptr response = std::make_shared(); }; -} +} // namespace Technic diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp index 859da97e..fc678fa2 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.cpp @@ -143,7 +143,7 @@ void TechnicPage::suggestCurrent() auto netJob = makeShared(QString("Technic::PackMeta(%1)").arg(current.name), APPLICATION->network()); QString slug = current.slug; - netJob->addNetAction(Net::Download::makeByteArray(QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), &response)); + netJob->addNetAction(Net::Download::makeByteArray(QString("%1modpack/%2?build=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, slug, BuildConfig.TECHNIC_API_BUILD), response)); QObject::connect(netJob.get(), &NetJob::succeeded, this, [this, slug] { jobPtr.reset(); @@ -154,7 +154,7 @@ void TechnicPage::suggestCurrent() } QJsonParseError parse_error {}; - QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); QJsonObject obj = doc.object(); if(parse_error.error != QJsonParseError::NoError) { @@ -249,7 +249,7 @@ void TechnicPage::metadataLoaded() auto netJob = makeShared(QString("Technic::SolderMeta(%1)").arg(current.name), APPLICATION->network()); auto url = QString("%1/modpack/%2").arg(current.url, current.slug); - netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), &response)); + netJob->addNetAction(Net::Download::makeByteArray(QUrl(url), response)); QObject::connect(netJob.get(), &NetJob::succeeded, this, &TechnicPage::onSolderLoaded); @@ -291,11 +291,11 @@ void TechnicPage::onSolderLoaded() { current.versions.clear(); - QJsonParseError parse_error {}; - auto doc = QJsonDocument::fromJson(response, &parse_error); + QJsonParseError parse_error{}; + auto doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from Solder at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << response; + qWarning() << *response; fallback(); return; } @@ -304,8 +304,7 @@ void TechnicPage::onSolderLoaded() { TechnicSolder::Pack pack; try { TechnicSolder::loadPack(pack, obj); - } - catch (const JSONValidationError& err) { + } catch (const JSONValidationError& err) { qCritical() << "Couldn't parse Solder pack metadata:" << err.cause(); fallback(); return; diff --git a/launcher/ui/pages/modplatform/technic/TechnicPage.h b/launcher/ui/pages/modplatform/technic/TechnicPage.h index f4a3b61d..753261b3 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicPage.h +++ b/launcher/ui/pages/modplatform/technic/TechnicPage.h @@ -104,5 +104,5 @@ private: QString selectedVersion; NetJob::Ptr jobPtr; - QByteArray response; + std::shared_ptr response = std::make_shared(); }; -- cgit From 0161520b332f485483f57acc305ad71a00d63fbc Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 18 Jun 2023 23:27:26 +0300 Subject: Fixed leaks Signed-off-by: Trial97 --- launcher/modplatform/EnsureMetadataTask.cpp | 9 +- .../modplatform/atlauncher/ATLPackInstallTask.h | 40 ++++---- launcher/modplatform/helpers/HashUtils.cpp | 14 +-- launcher/modplatform/helpers/HashUtils.h | 6 ++ .../modplatform/modrinth/ModrinthCheckUpdate.cpp | 5 +- launcher/ui/dialogs/NewsDialog.cpp | 2 +- .../pages/modplatform/atlauncher/AtlListModel.cpp | 91 +++++++---------- .../atlauncher/AtlUserInteractionSupportImpl.h | 8 +- .../ui/pages/modplatform/legacy_ftb/ListModel.cpp | 112 ++++++++------------- .../ui/pages/modplatform/technic/TechnicModel.cpp | 106 +++++++------------ 10 files changed, 164 insertions(+), 229 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp index 080dd580..a04a2534 100644 --- a/launcher/modplatform/EnsureMetadataTask.cpp +++ b/launcher/modplatform/EnsureMetadataTask.cpp @@ -10,6 +10,7 @@ #include "modplatform/flame/FlameAPI.h" #include "modplatform/flame/FlameModIndex.h" +#include "modplatform/helpers/HashUtils.h" #include "modplatform/modrinth/ModrinthAPI.h" #include "modplatform/modrinth/ModrinthPackIndex.h" @@ -24,8 +25,8 @@ EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::Resource auto hash_task = createNewHash(mod); if (!hash_task) return; - connect(hash_task.get(), &Task::succeeded, [this, hash_task, mod] { m_mods.insert(hash_task->getResult(), mod); }); - connect(hash_task.get(), &Task::failed, [this, hash_task, mod] { emitFail(mod, "", RemoveFromList::No); }); + connect(hash_task.get(), &Hashing::Hasher::getResults, [this, mod](QString hash) { m_mods.insert(hash, mod); }); + connect(hash_task.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); }); hash_task->start(); } @@ -37,8 +38,8 @@ EnsureMetadataTask::EnsureMetadataTask(QList& mods, QDir dir, ModPlatform: auto hash_task = createNewHash(mod); if (!hash_task) continue; - connect(hash_task.get(), &Task::succeeded, [this, hash_task, mod] { m_mods.insert(hash_task->getResult(), mod); }); - connect(hash_task.get(), &Task::failed, [this, hash_task, mod] { emitFail(mod, "", RemoveFromList::No); }); + connect(hash_task.get(), &Hashing::Hasher::getResults, [this, mod](QString hash) { m_mods.insert(hash, mod); }); + connect(hash_task.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); }); m_hashing_task->addTask(hash_task); } } diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.h b/launcher/modplatform/atlauncher/ATLPackInstallTask.h index bfe4d90a..b82f523f 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.h +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.h @@ -58,8 +58,7 @@ enum class InstallMode { }; class UserInteractionSupport { - -public: + public: /** * Requests a user interaction to select which optional mods should be installed. */ @@ -75,23 +74,27 @@ public: * Requests a user interaction to display a message. */ virtual void displayMessage(QString message) = 0; + + virtual ~UserInteractionSupport() = default; }; -class PackInstallTask : public InstanceTask -{ -Q_OBJECT +class PackInstallTask : public InstanceTask { + Q_OBJECT -public: - explicit PackInstallTask(UserInteractionSupport *support, QString packName, QString version, InstallMode installMode = InstallMode::Install); - virtual ~PackInstallTask(){} + public: + explicit PackInstallTask(UserInteractionSupport* support, + QString packName, + QString version, + InstallMode installMode = InstallMode::Install); + virtual ~PackInstallTask() { delete m_support; } bool canAbort() const override { return true; } bool abort() override; -protected: + protected: virtual void executeTask() override; -private slots: + private slots: void onDownloadSucceeded(); void onDownloadFailed(QString reason); void onDownloadAborted(); @@ -99,7 +102,7 @@ private slots: void onModsDownloaded(); void onModsExtracted(); -private: + private: QString getDirForModType(ModType type, QString raw); QString getVersionForLoader(QString uid); QString detectLibrary(VersionLibrary library); @@ -111,15 +114,13 @@ private: void installConfigs(); void extractConfigs(); void downloadMods(); - bool extractMods( - const QMap &toExtract, - const QMap &toDecomp, - const QMap &toCopy - ); + bool extractMods(const QMap& toExtract, + const QMap& toDecomp, + const QMap& toCopy); void install(); -private: - UserInteractionSupport *m_support; + private: + UserInteractionSupport* m_support; bool abortable = false; @@ -146,7 +147,6 @@ private: QFuture m_modExtractFuture; QFutureWatcher m_modExtractFutureWatcher; - }; -} +} // namespace ATLauncher diff --git a/launcher/modplatform/helpers/HashUtils.cpp b/launcher/modplatform/helpers/HashUtils.cpp index 81c94e1b..6df1eaf9 100644 --- a/launcher/modplatform/helpers/HashUtils.cpp +++ b/launcher/modplatform/helpers/HashUtils.cpp @@ -71,6 +71,7 @@ void ModrinthHasher::executeTask() emitFailed("Empty hash!"); } else { emitSucceeded(); + emit getResults(m_hash); } } @@ -91,10 +92,9 @@ void FlameHasher::executeTask() } } - -BlockedModHasher::BlockedModHasher(QString file_path, ModPlatform::ResourceProvider provider) - : Hasher(file_path), provider(provider) { - setObjectName(QString("BlockedModHasher: %1").arg(file_path)); +BlockedModHasher::BlockedModHasher(QString file_path, ModPlatform::ResourceProvider provider) : Hasher(file_path), provider(provider) +{ + setObjectName(QString("BlockedModHasher: %1").arg(file_path)); hash_type = ProviderCaps.hashType(provider).first(); } @@ -123,11 +123,13 @@ void BlockedModHasher::executeTask() } } -QStringList BlockedModHasher::getHashTypes() { +QStringList BlockedModHasher::getHashTypes() +{ return ProviderCaps.hashType(provider); } -bool BlockedModHasher::useHashType(QString type) { +bool BlockedModHasher::useHashType(QString type) +{ auto types = ProviderCaps.hashType(provider); if (types.contains(type)) { hash_type = type; diff --git a/launcher/modplatform/helpers/HashUtils.h b/launcher/modplatform/helpers/HashUtils.h index 91146a52..f3b9e030 100644 --- a/launcher/modplatform/helpers/HashUtils.h +++ b/launcher/modplatform/helpers/HashUtils.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "modplatform/ModIndex.h" @@ -8,6 +9,7 @@ namespace Hashing { class Hasher : public Task { + Q_OBJECT public: using Ptr = shared_qobject_ptr; @@ -21,6 +23,9 @@ class Hasher : public Task { QString getResult() const { return m_hash; }; QString getPath() const { return m_path; }; + signals: + void getResults(QString hash); + protected: QString m_hash; QString m_path; @@ -48,6 +53,7 @@ class BlockedModHasher : public Hasher { QStringList getHashTypes(); bool useHashType(QString type); + private: ModPlatform::ResourceProvider provider; QString hash_type; diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index 6a3f12f9..36002bad 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -53,12 +53,11 @@ void ModrinthCheckUpdate::executeTask() // (though it will rarely happen, if at all) if (mod->metadata()->hash_format != best_hash_type) { auto hash_task = Hashing::createModrinthHasher(mod->fileinfo().absoluteFilePath()); - connect(hash_task.get(), &Task::succeeded, [&] { - QString hash(hash_task->getResult()); + connect(hash_task.get(), &Hashing::Hasher::getResults, [&hashes, &mappings, mod](QString hash) { hashes.append(hash); mappings.insert(hash, mod); }); - connect(hash_task.get(), &Task::failed, [this, hash_task] { failed("Failed to generate hash"); }); + connect(hash_task.get(), &Task::failed, [this] { failed("Failed to generate hash"); }); hashing_task.addTask(hash_task); } else { hashes.append(hash); diff --git a/launcher/ui/dialogs/NewsDialog.cpp b/launcher/ui/dialogs/NewsDialog.cpp index e1b5dd74..b646e391 100644 --- a/launcher/ui/dialogs/NewsDialog.cpp +++ b/launcher/ui/dialogs/NewsDialog.cpp @@ -32,7 +32,7 @@ NewsDialog::~NewsDialog() void NewsDialog::selectedArticleChanged(const QString& new_title) { - auto const& article_entry = m_entries.constFind(new_title).value(); + auto article_entry = m_entries.constFind(new_title).value(); ui->articleTitleLabel->setText(QString("%2").arg(article_entry->link, new_title)); diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp index 2ab86529..c6b087d6 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp +++ b/launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp @@ -16,62 +16,49 @@ #include "AtlListModel.h" -#include #include +#include #include namespace Atl { -ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) -{ -} +ListModel::ListModel(QObject* parent) : QAbstractListModel(parent) {} -ListModel::~ListModel() -{ -} +ListModel::~ListModel() {} -int ListModel::rowCount(const QModelIndex &parent) const +int ListModel::rowCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : modpacks.size(); } -int ListModel::columnCount(const QModelIndex &parent) const +int ListModel::columnCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : 1; } -QVariant ListModel::data(const QModelIndex &index, int role) const +QVariant ListModel::data(const QModelIndex& index, int role) const { int pos = index.row(); - if(pos >= modpacks.size() || pos < 0 || !index.isValid()) - { + if (pos >= modpacks.size() || pos < 0 || !index.isValid()) { return QString("INVALID INDEX %1").arg(pos); } ATLauncher::IndexedPack pack = modpacks.at(pos); - if(role == Qt::DisplayRole) - { + if (role == Qt::DisplayRole) { return pack.name; - } - else if (role == Qt::ToolTipRole) - { + } else if (role == Qt::ToolTipRole) { return pack.name; - } - else if(role == Qt::DecorationRole) - { - if(m_logoMap.contains(pack.safeName)) - { + } else if (role == Qt::DecorationRole) { + if (m_logoMap.contains(pack.safeName)) { return (m_logoMap.value(pack.safeName)); } auto icon = APPLICATION->getThemedIcon("atlauncher-placeholder"); auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "launcher/images/%1.png").arg(pack.safeName.toLower()); - ((ListModel *)this)->requestLogo(pack.safeName, url); + ((ListModel*)this)->requestLogo(pack.safeName, url); return icon; - } - else if(role == Qt::UserRole) - { + } else if (role == Qt::UserRole) { QVariant v; v.setValue(pack); return v; @@ -102,7 +89,7 @@ void ListModel::requestFinished() QJsonParseError parse_error; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if(parse_error.error != QJsonParseError::NoError) { + if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from ATL at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << *response; return; @@ -111,26 +98,28 @@ void ListModel::requestFinished() QList newList; auto packs = doc.array(); - for(auto packRaw : packs) { + for (auto packRaw : packs) { auto packObj = packRaw.toObject(); ATLauncher::IndexedPack pack; try { ATLauncher::loadIndexedPack(pack, packObj); - } - catch (const JSONValidationError &e) { + } catch (const JSONValidationError& e) { qDebug() << QString::fromUtf8(*response); qWarning() << "Error while reading pack manifest from ATLauncher: " << e.cause(); return; } // ignore packs without a published version - if(pack.versions.length() == 0) continue; + if (pack.versions.length() == 0) + continue; // only display public packs (for now) - if(pack.type != ATLauncher::PackType::Public) continue; + if (pack.type != ATLauncher::PackType::Public) + continue; // ignore "system" packs (Vanilla, Vanilla with Forge, etc) - if(pack.system) continue; + if (pack.system) + continue; newList.append(pack); } @@ -145,14 +134,12 @@ void ListModel::requestFailed(QString reason) jobPtr.reset(); } -void ListModel::getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback) +void ListModel::getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback) { - if(m_logoMap.contains(logo)) - { - callback(APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath()); - } - else - { + if (m_logoMap.contains(logo)) { + callback( + APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath()); + } else { requestLogo(logo, logoUrl); } } @@ -168,36 +155,34 @@ void ListModel::logoLoaded(QString logo, QIcon out) m_loadingLogos.removeAll(logo); m_logoMap.insert(logo, out); - for(int i = 0; i < modpacks.size(); i++) { - if(modpacks[i].safeName == logo) { - emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole}); + for (int i = 0; i < modpacks.size(); i++) { + if (modpacks[i].safeName == logo) { + emit dataChanged(createIndex(i, 0), createIndex(i, 0), { Qt::DecorationRole }); } } } void ListModel::requestLogo(QString file, QString url) { - if(m_loadingLogos.contains(file) || m_failedLogos.contains(file)) - { + if (m_loadingLogos.contains(file) || m_failedLogos.contains(file)) { return; } MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", QString("logos/%1").arg(file.section(".", 0, 0))); - NetJob *job = new NetJob(QString("ATLauncher Icon Download %1").arg(file), APPLICATION->network()); + auto job = new NetJob(QString("ATLauncher Icon Download %1").arg(file), APPLICATION->network()); job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); - QObject::connect(job, &NetJob::succeeded, this, [this, file, fullPath] - { + QObject::connect(job, &NetJob::succeeded, this, [this, file, fullPath, job] { + job->deleteLater(); emit logoLoaded(file, QIcon(fullPath)); - if(waitingCallbacks.contains(file)) - { + if (waitingCallbacks.contains(file)) { waitingCallbacks.value(file)(fullPath); } }); - QObject::connect(job, &NetJob::failed, this, [this, file] - { + QObject::connect(job, &NetJob::failed, this, [this, file, job] { + job->deleteLater(); emit logoFailed(file); }); @@ -206,4 +191,4 @@ void ListModel::requestLogo(QString file, QString url) m_loadingLogos.append(file); } -} +} // namespace Atl diff --git a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h index 37010b3f..adeb53cb 100644 --- a/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h +++ b/launcher/ui/pages/modplatform/atlauncher/AtlUserInteractionSupportImpl.h @@ -42,15 +42,15 @@ class AtlUserInteractionSupportImpl : public QObject, public ATLauncher::UserInteractionSupport { Q_OBJECT -public: + public: AtlUserInteractionSupportImpl(QWidget* parent); + virtual ~AtlUserInteractionSupportImpl() = default; -private: + private: QString chooseVersion(Meta::VersionList::Ptr vlist, QString minecraftVersion) override; std::optional> chooseOptionalMods(ATLauncher::PackVersion version, QVector mods) override; void displayMessage(QString message) override; -private: + private: QWidget* m_parent; - }; diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp index 2343b79f..a3e29201 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp @@ -35,14 +35,15 @@ #include "ListModel.h" #include "Application.h" +#include "QObjectPtr.h" #include "net/HttpMetaCache.h" #include "net/NetJob.h" -#include "StringUtils.h" #include +#include "StringUtils.h" -#include #include +#include #include @@ -50,33 +51,33 @@ namespace LegacyFTB { -FilterModel::FilterModel(QObject *parent) : QSortFilterProxyModel(parent) +FilterModel::FilterModel(QObject* parent) : QSortFilterProxyModel(parent) { currentSorting = Sorting::ByGameVersion; sortings.insert(tr("Sort by Name"), Sorting::ByName); sortings.insert(tr("Sort by Game Version"), Sorting::ByGameVersion); } -bool FilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +bool FilterModel::lessThan(const QModelIndex& left, const QModelIndex& right) const { Modpack leftPack = sourceModel()->data(left, Qt::UserRole).value(); Modpack rightPack = sourceModel()->data(right, Qt::UserRole).value(); - if(currentSorting == Sorting::ByGameVersion) { + if (currentSorting == Sorting::ByGameVersion) { Version lv(leftPack.mcVersion); Version rv(rightPack.mcVersion); return lv < rv; - } else if(currentSorting == Sorting::ByName) { + } else if (currentSorting == Sorting::ByName) { return StringUtils::naturalCompare(leftPack.name, rightPack.name, Qt::CaseSensitive) >= 0; } - //UHM, some inavlid value set?! + // UHM, some inavlid value set?! qWarning() << "Invalid sorting set!"; return true; } -bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { return true; } @@ -102,18 +103,13 @@ FilterModel::Sorting FilterModel::getCurrentSorting() return currentSorting; } -ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) -{ -} +ListModel::ListModel(QObject* parent) : QAbstractListModel(parent) {} -ListModel::~ListModel() -{ -} +ListModel::~ListModel() {} QString ListModel::translatePackType(PackType type) const { - switch(type) - { + switch (type) { case PackType::Public: return tr("Public Modpack"); case PackType::ThirdParty: @@ -125,67 +121,51 @@ QString ListModel::translatePackType(PackType type) const return QString(); } -int ListModel::rowCount(const QModelIndex &parent) const +int ListModel::rowCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : modpacks.size(); } -int ListModel::columnCount(const QModelIndex &parent) const +int ListModel::columnCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : 1; } -QVariant ListModel::data(const QModelIndex &index, int role) const +QVariant ListModel::data(const QModelIndex& index, int role) const { int pos = index.row(); - if(pos >= modpacks.size() || pos < 0 || !index.isValid()) - { + if (pos >= modpacks.size() || pos < 0 || !index.isValid()) { return QString("INVALID INDEX %1").arg(pos); } Modpack pack = modpacks.at(pos); - if(role == Qt::DisplayRole) - { + if (role == Qt::DisplayRole) { return pack.name + "\n" + translatePackType(pack.type); - } - else if (role == Qt::ToolTipRole) - { - if(pack.description.length() > 100) - { - //some magic to prevent to long tooltips and replace html linebreaks + } else if (role == Qt::ToolTipRole) { + if (pack.description.length() > 100) { + // some magic to prevent to long tooltips and replace html linebreaks QString edit = pack.description.left(97); edit = edit.left(edit.lastIndexOf("
")).left(edit.lastIndexOf(" ")).append("..."); return edit; - } return pack.description; - } - else if(role == Qt::DecorationRole) - { - if(m_logoMap.contains(pack.logo)) - { + } else if (role == Qt::DecorationRole) { + if (m_logoMap.contains(pack.logo)) { return (m_logoMap.value(pack.logo)); } QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); - ((ListModel *)this)->requestLogo(pack.logo); + ((ListModel*)this)->requestLogo(pack.logo); return icon; - } - else if(role == Qt::ForegroundRole) - { - if(pack.broken) - { - //FIXME: Hardcoded color + } else if (role == Qt::ForegroundRole) { + if (pack.broken) { + // FIXME: Hardcoded color return QColor(255, 0, 50); - } - else if(pack.bugged) - { - //FIXME: Hardcoded color - //bugged pack, currently only indicates bugged xml + } else if (pack.bugged) { + // FIXME: Hardcoded color + // bugged pack, currently only indicates bugged xml return QColor(244, 229, 66); } - } - else if(role == Qt::UserRole) - { + } else if (role == Qt::UserRole) { QVariant v; v.setValue(pack); return v; @@ -222,8 +202,7 @@ Modpack ListModel::at(int row) void ListModel::remove(int row) { - if(row < 0 || row >= modpacks.size()) - { + if (row < 0 || row >= modpacks.size()) { qWarning() << "Attempt to remove FTB modpacks with invalid row" << row; return; } @@ -247,27 +226,25 @@ void ListModel::logoFailed(QString logo) void ListModel::requestLogo(QString file) { - if(m_loadingLogos.contains(file) || m_failedLogos.contains(file)) - { + if (m_loadingLogos.contains(file) || m_failedLogos.contains(file)) { return; } MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(file.section(".", 0, 0))); - NetJob *job = new NetJob(QString("FTB Icon Download for %1").arg(file), APPLICATION->network()); + NetJob* job = new NetJob(QString("FTB Icon Download for %1").arg(file), APPLICATION->network()); job->addNetAction(Net::Download::makeCached(QUrl(QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry)); auto fullPath = entry->getFullPath(); - QObject::connect(job, &NetJob::finished, this, [this, file, fullPath] - { + QObject::connect(job, &NetJob::finished, this, [this, file, fullPath, job] { + job->deleteLater(); emit logoLoaded(file, QIcon(fullPath)); - if(waitingCallbacks.contains(file)) - { + if (waitingCallbacks.contains(file)) { waitingCallbacks.value(file)(fullPath); } }); - QObject::connect(job, &NetJob::failed, this, [this, file] - { + QObject::connect(job, &NetJob::failed, this, [this, file, job] { + job->deleteLater(); emit logoFailed(file); }); @@ -276,21 +253,18 @@ void ListModel::requestLogo(QString file) m_loadingLogos.append(file); } -void ListModel::getLogo(const QString &logo, LogoCallback callback) +void ListModel::getLogo(const QString& logo, LogoCallback callback) { - if(m_logoMap.contains(logo)) - { + if (m_logoMap.contains(logo)) { callback(APPLICATION->metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath()); - } - else - { + } else { requestLogo(logo); } } -Qt::ItemFlags ListModel::flags(const QModelIndex &index) const +Qt::ItemFlags ListModel::flags(const QModelIndex& index) const { return QAbstractListModel::flags(index); } -} +} // namespace LegacyFTB diff --git a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp index 7975fd58..f08eb289 100644 --- a/launcher/ui/pages/modplatform/technic/TechnicModel.cpp +++ b/launcher/ui/pages/modplatform/technic/TechnicModel.cpp @@ -40,39 +40,28 @@ #include -Technic::ListModel::ListModel(QObject *parent) : QAbstractListModel(parent) -{ -} +Technic::ListModel::ListModel(QObject* parent) : QAbstractListModel(parent) {} -Technic::ListModel::~ListModel() -{ -} +Technic::ListModel::~ListModel() {} QVariant Technic::ListModel::data(const QModelIndex& index, int role) const { int pos = index.row(); - if(pos >= modpacks.size() || pos < 0 || !index.isValid()) - { + if (pos >= modpacks.size() || pos < 0 || !index.isValid()) { return QString("INVALID INDEX %1").arg(pos); } Modpack pack = modpacks.at(pos); - if(role == Qt::DisplayRole) - { + if (role == Qt::DisplayRole) { return pack.name; - } - else if(role == Qt::DecorationRole) - { - if(m_logoMap.contains(pack.logoName)) - { + } else if (role == Qt::DecorationRole) { + if (m_logoMap.contains(pack.logoName)) { return (m_logoMap.value(pack.logoName)); } QIcon icon = APPLICATION->getThemedIcon("screenshot-placeholder"); - ((ListModel *)this)->requestLogo(pack.logoName, pack.logoUrl); + ((ListModel*)this)->requestLogo(pack.logoName, pack.logoUrl); return icon; - } - else if(role == Qt::UserRole) - { + } else if (role == Qt::UserRole) { QVariant v; v.setValue(pack); return v; @@ -92,16 +81,15 @@ int Technic::ListModel::rowCount(const QModelIndex& parent) const void Technic::ListModel::searchWithTerm(const QString& term) { - if(currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull()) { + if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull()) { return; } currentSearchTerm = term; - if(jobPtr) { + if (jobPtr) { jobPtr->abort(); searchState = ResetRequested; return; - } - else { + } else { beginResetModel(); modpacks.clear(); endResetModel(); @@ -115,23 +103,17 @@ void Technic::ListModel::performSearch() auto netJob = makeShared("Technic::Search", APPLICATION->network()); QString searchUrl = ""; if (currentSearchTerm.isEmpty()) { - searchUrl = QString("%1trending?build=%2") - .arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD); + searchUrl = QString("%1trending?build=%2").arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD); searchMode = List; - } - else if (currentSearchTerm.startsWith("http://api.technicpack.net/modpack/")) { - searchUrl = QString("https://%1?build=%2") - .arg(currentSearchTerm.mid(7), BuildConfig.TECHNIC_API_BUILD); + } else if (currentSearchTerm.startsWith("http://api.technicpack.net/modpack/")) { + searchUrl = QString("https://%1?build=%2").arg(currentSearchTerm.mid(7), BuildConfig.TECHNIC_API_BUILD); searchMode = Single; - } - else if (currentSearchTerm.startsWith("https://api.technicpack.net/modpack/")) { + } else if (currentSearchTerm.startsWith("https://api.technicpack.net/modpack/")) { searchUrl = QString("%1?build=%2").arg(currentSearchTerm, BuildConfig.TECHNIC_API_BUILD); searchMode = Single; - } - else { - searchUrl = QString( - "%1search?build=%2&q=%3" - ).arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD, currentSearchTerm); + } else { + searchUrl = + QString("%1search?build=%2&q=%3").arg(BuildConfig.TECHNIC_API_BASE_URL, BuildConfig.TECHNIC_API_BUILD, currentSearchTerm); searchMode = List; } netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), response)); @@ -161,7 +143,7 @@ void Technic::ListModel::searchRequestFinished() switch (searchMode) { case List: { auto objs = Json::requireArray(root, "modpacks"); - for (auto technicPack: objs) { + for (auto technicPack : objs) { Modpack pack; auto technicPackObject = Json::requireObject(technicPack); pack.name = Json::requireString(technicPackObject, "name"); @@ -170,11 +152,10 @@ void Technic::ListModel::searchRequestFinished() continue; auto rawURL = Json::ensureString(technicPackObject, "iconUrl", "null"); - if(rawURL == "null") { + if (rawURL == "null") { pack.logoUrl = "null"; pack.logoName = "null"; - } - else { + } else { pack.logoUrl = rawURL; pack.logoName = rawURL.section(QLatin1Char('/'), -1).section(QLatin1Char('.'), 0, 0); } @@ -199,8 +180,7 @@ void Technic::ListModel::searchRequestFinished() pack.logoUrl = iconUrl; pack.logoName = iconUrl.section(QLatin1Char('/'), -1).section(QLatin1Char('.'), 0, 0); - } - else { + } else { pack.logoUrl = "null"; pack.logoName = "null"; } @@ -210,10 +190,8 @@ void Technic::ListModel::searchRequestFinished() break; } } - } - catch (const JSONValidationError &err) - { - qCritical() << "Couldn't parse technic search results:" << err.cause() ; + } catch (const JSONValidationError& err) { + qCritical() << "Couldn't parse technic search results:" << err.cause(); return; } searchState = Finished; @@ -229,12 +207,9 @@ void Technic::ListModel::searchRequestFinished() void Technic::ListModel::getLogo(const QString& logo, const QString& logoUrl, Technic::LogoCallback callback) { - if(m_logoMap.contains(logo)) - { + if (m_logoMap.contains(logo)) { callback(APPLICATION->metacache()->resolveEntry("TechnicPacks", QString("logos/%1").arg(logo))->getFullPath()); - } - else - { + } else { requestLogo(logo, logoUrl); } } @@ -243,30 +218,24 @@ void Technic::ListModel::searchRequestFailed() { jobPtr.reset(); - if(searchState == ResetRequested) - { + if (searchState == ResetRequested) { beginResetModel(); modpacks.clear(); endResetModel(); performSearch(); - } - else - { + } else { searchState = Finished; } } - void Technic::ListModel::logoLoaded(QString logo, QString out) { m_loadingLogos.removeAll(logo); m_logoMap.insert(logo, QIcon(out)); - for(int i = 0; i < modpacks.size(); i++) - { - if(modpacks[i].logoName == logo) - { - emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole}); + for (int i = 0; i < modpacks.size(); i++) { + if (modpacks[i].logoName == logo) { + emit dataChanged(createIndex(i, 0), createIndex(i, 0), { Qt::DecorationRole }); } } } @@ -279,24 +248,23 @@ void Technic::ListModel::logoFailed(QString logo) void Technic::ListModel::requestLogo(QString logo, QString url) { - if(m_loadingLogos.contains(logo) || m_failedLogos.contains(logo) || logo == "null") - { + if (m_loadingLogos.contains(logo) || m_failedLogos.contains(logo) || logo == "null") { return; } MetaEntryPtr entry = APPLICATION->metacache()->resolveEntry("TechnicPacks", QString("logos/%1").arg(logo)); - NetJob *job = new NetJob(QString("Technic Icon Download %1").arg(logo), APPLICATION->network()); + auto job = new NetJob(QString("Technic Icon Download %1").arg(logo), APPLICATION->network()); job->addNetAction(Net::Download::makeCached(QUrl(url), entry)); auto fullPath = entry->getFullPath(); - QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath] - { + QObject::connect(job, &NetJob::succeeded, this, [this, logo, fullPath, job] { + job->deleteLater(); logoLoaded(logo, fullPath); }); - QObject::connect(job, &NetJob::failed, this, [this, logo] - { + QObject::connect(job, &NetJob::failed, this, [this, logo, job] { + job->deleteLater(); logoFailed(logo); }); -- cgit From 4e66f55d8426559942d92e61556747528be03cdf Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 18 Jun 2023 23:32:17 +0300 Subject: Removed extra headers Signed-off-by: Trial97 --- launcher/modplatform/helpers/HashUtils.h | 1 - launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp | 1 - 2 files changed, 2 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/helpers/HashUtils.h b/launcher/modplatform/helpers/HashUtils.h index f3b9e030..a541ae8f 100644 --- a/launcher/modplatform/helpers/HashUtils.h +++ b/launcher/modplatform/helpers/HashUtils.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include "modplatform/ModIndex.h" diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp index a3e29201..330dd4fb 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp @@ -35,7 +35,6 @@ #include "ListModel.h" #include "Application.h" -#include "QObjectPtr.h" #include "net/HttpMetaCache.h" #include "net/NetJob.h" -- cgit From 1bdde1f947f57801f2fcb1a0f881f19bd8e1e29d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 19 Jun 2023 00:36:37 +0300 Subject: Small fixes Signed-off-by: Trial97 --- .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 61 ++++++++++++---------- .../minecraft/mod/tasks/GetModDependenciesTask.h | 2 +- launcher/modplatform/ModIndex.h | 2 +- launcher/modplatform/ResourceAPI.h | 8 --- launcher/modplatform/flame/FlameModIndex.cpp | 12 +++-- .../modplatform/modrinth/ModrinthPackIndex.cpp | 10 ++-- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 10 ++-- 7 files changed, 54 insertions(+), 51 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index bd80a661..54116e28 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -33,7 +33,7 @@ #include "ui/pages/modplatform/flame/FlameResourceModels.h" #include "ui/pages/modplatform/modrinth/ModrinthResourceModels.h" -static Version mcVersions(BaseInstance* inst) +static Version mcVersion(BaseInstance* inst) { return static_cast(inst)->getPackProfile()->getComponent("net.minecraft")->getVersion(); } @@ -53,7 +53,7 @@ GetModDependenciesTask::GetModDependenciesTask(QObject* parent, std::make_shared() } , m_modrinth_provider{ ModPlatform::ResourceProvider::MODRINTH, std::make_shared(*instance), std::make_shared() } - , m_version(mcVersions(instance)) + , m_version(mcVersion(instance)) , m_loaderType(mcLoaders(instance)) { for (auto mod : folder->allMods()) @@ -74,33 +74,38 @@ void GetModDependenciesTask::prepare() QList GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version, const ModPlatform::ResourceProvider providerName) { - auto c_dependencies = QList(); + QList c_dependencies; for (auto ver_dep : version.dependencies) { - if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) { - if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), - [&ver_dep](const ModPlatform::Dependency& i) { return i.addonId == ver_dep.addonId; }); - dep == c_dependencies.end()) { // check the current dependency list - if (auto dep = std::find_if(m_selected.begin(), m_selected.end(), - [&ver_dep, providerName](std::shared_ptr i) { - return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName; - }); - dep == m_selected.end()) { // check the selected versions - if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), - [&ver_dep, providerName](std::shared_ptr i) { - return i->project_id == ver_dep.addonId && i->provider == providerName; - }); - dep == m_mods.end()) { // check the existing mods - if (auto dep = std::find_if(m_pack_dependencies.begin(), m_pack_dependencies.end(), - [&ver_dep, providerName](std::shared_ptr i) { - return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName; - }); - dep == m_pack_dependencies.end()) { // check loaded dependencies - c_dependencies.append(ver_dep); - } - } - } - } - } + if (ver_dep.type != ModPlatform::DependencyType::REQUIRED) + continue; + + if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), + [&ver_dep](const ModPlatform::Dependency& i) { return i.addonId == ver_dep.addonId; }); + dep != c_dependencies.end()) + continue; // check the current dependency list + + if (auto dep = std::find_if(m_selected.begin(), m_selected.end(), + [&ver_dep, providerName](std::shared_ptr i) { + return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName; + }); + dep != m_selected.end()) + continue; // check the selected versions + + if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), + [&ver_dep, providerName](std::shared_ptr i) { + return i->project_id == ver_dep.addonId && i->provider == providerName; + }); + dep != m_mods.end()) + continue; // check the existing mods + + if (auto dep = std::find_if(m_pack_dependencies.begin(), m_pack_dependencies.end(), + [&ver_dep, providerName](std::shared_ptr i) { + return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName; + }); + dep != m_pack_dependencies.end()) // check loaded dependencies + continue; + + c_dependencies.append(ver_dep); } return c_dependencies; }; diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index 3824e781..99d5afb0 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -42,7 +42,7 @@ class GetModDependenciesTask : public SequentialTask { ModPlatform::Dependency dependency; ModPlatform::IndexedPack::Ptr pack; ModPlatform::IndexedVersion version; - PackDependency(){}; + PackDependency() = default; PackDependency(const ModPlatform::IndexedPack::Ptr p, const ModPlatform::IndexedVersion& v) { pack = p; diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 64b44055..7236e63e 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -34,7 +34,7 @@ enum class ResourceProvider { MODRINTH, FLAME }; enum class ResourceType { MOD, RESOURCE_PACK, SHADER_PACK }; -enum class DependencyType { REQUIRED, OPTIONAL, INCOMPATIBLE, EMBEDDED, TOOL, INCLUDE }; +enum class DependencyType { REQUIRED, OPTIONAL, INCOMPATIBLE, EMBEDDED, TOOL, INCLUDE, UNKNOWN }; class ProviderCapabilities { public: diff --git a/launcher/modplatform/ResourceAPI.h b/launcher/modplatform/ResourceAPI.h index c23444b3..63b917f1 100644 --- a/launcher/modplatform/ResourceAPI.h +++ b/launcher/modplatform/ResourceAPI.h @@ -115,14 +115,6 @@ class ResourceAPI { ModPlatform::Dependency dependency; Version mcVersion; ModLoaderTypes loader; - - DependencySearchArgs(DependencySearchArgs const&) = default; - void operator=(DependencySearchArgs other) - { - dependency = other.dependency; - mcVersion = other.mcVersion; - loader = other.loader; - } }; struct DependencySearchCallbacks { diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 120bfc91..9c8eb832 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -160,6 +160,10 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> case 6: // Include dependency.type = ModPlatform::DependencyType::INCLUDE; break; + default: + dependency.type = ModPlatform::DependencyType::UNKNOWN; + break; + } file.dependencies.append(dependency); } @@ -172,7 +176,7 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) { - QVector unsortedVersions; + QVector versions; for (auto versionIter : arr) { auto obj = versionIter.toObject(); @@ -181,13 +185,13 @@ ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform:: file.addonId = m.addonId; if (file.fileId.isValid()) // Heuristic to check if the returned value is valid - unsortedVersions.append(file); + versions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { // dates are in RFC 3339 format return a.date > b.date; }; - std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); - return unsortedVersions.front(); + std::sort(versions.begin(), versions.end(), orderSortPredicate); + return versions.front(); }; diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 879260a3..92b48e5f 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -156,6 +156,8 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t dependency.type = ModPlatform::DependencyType::INCOMPATIBLE; else if (depType == "embedded") dependency.type = ModPlatform::DependencyType::EMBEDDED; + else + dependency.type = ModPlatform::DependencyType::UNKNOWN; file.dependencies.append(dependency); } @@ -218,19 +220,19 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t auto Modrinth::loadDependencyVersions(const ModPlatform::Dependency& m, QJsonArray& arr) -> ModPlatform::IndexedVersion { - QVector unsortedVersions; + QVector versions; for (auto versionIter : arr) { auto obj = versionIter.toObject(); auto file = loadIndexedPackVersion(obj); if (file.fileId.isValid()) // Heuristic to check if the returned value is valid - unsortedVersions.append(file); + versions.append(file); } auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { // dates are in RFC 3339 format return a.date > b.date; }; - std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate); - return unsortedVersions.length() != 0 ? unsortedVersions.front() : ModPlatform::IndexedVersion(); + std::sort(versions.begin(), versions.end(), orderSortPredicate); + return versions.length() != 0 ? versions.front() : ModPlatform::IndexedVersion(); } \ No newline at end of file diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 819cf7de..c7d9da4e 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -125,7 +125,7 @@ void ResourceDownloadDialog::connectButtons() static ModPlatform::ProviderCapabilities ProviderCaps; -QStringList getReqiredBy(QList tasks, QVariant addonId) +QStringList getRequiredBy(QList tasks, QVariant addonId) { auto req = QStringList(); for (auto& task : tasks) { @@ -167,10 +167,10 @@ void ResourceDownloadDialog::confirm() if (ret == QDialog::DialogCode::Rejected) { QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection); return; - } else - for (auto dep : task->getDependecies()) { + } else { + for (auto dep : task->getDependecies()) addResource(dep->pack, dep->version); - } + } } auto selected = getTasks(); @@ -179,7 +179,7 @@ void ResourceDownloadDialog::confirm() }); for (auto& task : selected) { confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath(), - ProviderCaps.name(task->getProvider()), getReqiredBy(selected, task->getPack()->addonId) }); + ProviderCaps.name(task->getProvider()), getRequiredBy(selected, task->getPack()->addonId) }); } if (confirm_dialog->exec()) { -- cgit From 3ee0fec7298d467d5b8b48a5144794f58bc2ce28 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 19 Jun 2023 12:22:22 +0300 Subject: Removed mods from lambda Signed-off-by: Trial97 --- launcher/ui/pages/instance/ModFolderPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 1d090ef4..90e7d0d6 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -100,7 +100,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); connect(mods.get(), &ModFolderModel::updateFinished, this, - [this, check_allow_update, mods] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); + [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); connect(m_instance, &BaseInstance::runningStatusChanged, this, &ModFolderPage::runningStateChanged); ModFolderPage::runningStateChanged(m_instance && m_instance->isRunning()); -- cgit From d02858040ef0d1f691b3456bb0ac271c484a7c57 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 19 Jun 2023 13:09:37 +0300 Subject: Fixes #1212 Signed-off-by: Trial97 --- launcher/ui/pages/modplatform/ModPage.cpp | 16 ++++++------- launcher/ui/pages/modplatform/ResourcePage.cpp | 31 +++++++++++++++----------- 2 files changed, 25 insertions(+), 22 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 95064d16..60a43128 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -89,17 +89,13 @@ void ModPage::filterMods() void ModPage::triggerSearch() { - auto changed = m_filter_widget->changed(); m_filter = m_filter_widget->getFilter(); + m_ui->packView->clearSelection(); + m_ui->packDescription->clear(); + m_ui->versionSelectionBox->clear(); + updateSelectionButton(); - if (changed) { - m_ui->packView->clearSelection(); - m_ui->packDescription->clear(); - m_ui->versionSelectionBox->clear(); - updateSelectionButton(); - } - - static_cast(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt(), changed); + static_cast(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt(), m_filter_widget->changed()); m_fetch_progress.watch(m_model->activeSearchJob().get()); } @@ -122,6 +118,8 @@ void ModPage::updateVersionList() QString mcVersion = packProfile->getComponentVersion("net.minecraft"); auto current_pack = getCurrentPack(); + if (!current_pack) + return; for (int i = 0; i < current_pack->versions.size(); i++) { auto version = current_pack->versions[i]; bool valid = false; diff --git a/launcher/ui/pages/modplatform/ResourcePage.cpp b/launcher/ui/pages/modplatform/ResourcePage.cpp index 1d2509d8..aab2ee89 100644 --- a/launcher/ui/pages/modplatform/ResourcePage.cpp +++ b/launcher/ui/pages/modplatform/ResourcePage.cpp @@ -174,7 +174,11 @@ ModPlatform::IndexedPack::Ptr ResourcePage::getCurrentPack() const void ResourcePage::updateUi() { auto current_pack = getCurrentPack(); - + if (!current_pack) { + m_ui->packDescription->setHtml({}); + m_ui->packDescription->flush(); + return; + } QString text = ""; QString name = current_pack->name; @@ -240,8 +244,8 @@ void ResourcePage::updateSelectionButton() } m_ui->resourceSelectionButton->setEnabled(true); - if (getCurrentPack()) { - if (!getCurrentPack()->isVersionSelected(m_selected_version_index)) + if (auto current_pack = getCurrentPack(); current_pack) { + if (!current_pack->isVersionSelected(m_selected_version_index)) m_ui->resourceSelectionButton->setText(tr("Select %1 for download").arg(resourceString())); else m_ui->resourceSelectionButton->setText(tr("Deselect %1 for download").arg(resourceString())); @@ -258,13 +262,14 @@ void ResourcePage::updateVersionList() m_ui->versionSelectionBox->clear(); m_ui->versionSelectionBox->blockSignals(false); - for (int i = 0; i < current_pack->versions.size(); i++) { - auto& version = current_pack->versions[i]; - if (optedOut(version)) - continue; + if (current_pack) + for (int i = 0; i < current_pack->versions.size(); i++) { + auto& version = current_pack->versions[i]; + if (optedOut(version)) + continue; - m_ui->versionSelectionBox->addItem(current_pack->versions[i].version, QVariant(i)); - } + m_ui->versionSelectionBox->addItem(current_pack->versions[i].version, QVariant(i)); + } if (m_ui->versionSelectionBox->count() == 0) { m_ui->versionSelectionBox->addItem(tr("No valid version found."), QVariant(-1)); @@ -283,7 +288,7 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) auto current_pack = getCurrentPack(); bool request_load = false; - if (!current_pack->versionsLoaded) { + if (!current_pack || !current_pack->versionsLoaded) { m_ui->resourceSelectionButton->setText(tr("Loading versions...")); m_ui->resourceSelectionButton->setEnabled(false); @@ -292,7 +297,7 @@ void ResourcePage::onSelectionChanged(QModelIndex curr, QModelIndex prev) updateVersionList(); } - if (!current_pack->extraDataLoaded) + if (current_pack && !current_pack->extraDataLoaded) request_load = true; if (request_load) @@ -340,7 +345,7 @@ void ResourcePage::onResourceSelected() return; auto current_pack = getCurrentPack(); - if (!current_pack->versionsLoaded) + if (!current_pack || !current_pack->versionsLoaded) return; auto& version = current_pack->versions[m_selected_version_index]; @@ -386,7 +391,7 @@ void ResourcePage::openUrl(const QUrl& url) const QString slug = match.captured(1); // ensure the user isn't opening the same mod - if (slug != getCurrentPack()->slug) { + if (auto current_pack = getCurrentPack(); current_pack && slug != current_pack->slug) { m_parent_dialog->selectPage(page); auto newPage = m_parent_dialog->getSelectedPage(); -- cgit From 8ad9692daab303bba6f5337f6660d8437ec8f330 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 19 Jun 2023 14:10:29 +0300 Subject: Changed qWarning to qDebug for raw data Signed-off-by: Trial97 --- launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 54116e28..274ff3c9 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -132,7 +132,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response for mod info at " << parse_error.offset << " reason: " << parse_error.errorString(); - qWarning() << *responseInfo; + qDebug() << *responseInfo; return; } try { -- cgit From 6fd729e285f67c74633d27575717070f3577a132 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 19 Jun 2023 17:42:16 +0300 Subject: Fixed regresion regarding modrinth project_id in dependence array Signed-off-by: Trial97 --- .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 63 ++++++++++++++-------- .../minecraft/mod/tasks/GetModDependenciesTask.h | 1 + .../modplatform/modrinth/ModrinthPackIndex.cpp | 2 +- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 16 ++++-- 4 files changed, 55 insertions(+), 27 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 274ff3c9..02281a35 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -79,28 +79,34 @@ QList GetModDependenciesTask::getDependenciesForVersion if (ver_dep.type != ModPlatform::DependencyType::REQUIRED) continue; + auto isOnlyVersion = providerName == ModPlatform::ResourceProvider::MODRINTH && ver_dep.addonId.toString().isEmpty(); if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), - [&ver_dep](const ModPlatform::Dependency& i) { return i.addonId == ver_dep.addonId; }); + [&ver_dep, isOnlyVersion](const ModPlatform::Dependency& i) { + return isOnlyVersion ? i.version == ver_dep.version : i.addonId == ver_dep.addonId; + }); dep != c_dependencies.end()) continue; // check the current dependency list if (auto dep = std::find_if(m_selected.begin(), m_selected.end(), - [&ver_dep, providerName](std::shared_ptr i) { - return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName; + [&ver_dep, providerName, isOnlyVersion](std::shared_ptr i) { + return i->pack->provider == providerName && (isOnlyVersion ? i->version.version == ver_dep.version + : i->pack->addonId == ver_dep.addonId); }); dep != m_selected.end()) continue; // check the selected versions if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), - [&ver_dep, providerName](std::shared_ptr i) { - return i->project_id == ver_dep.addonId && i->provider == providerName; + [&ver_dep, providerName, isOnlyVersion](std::shared_ptr i) { + return i->provider == providerName && + (isOnlyVersion ? i->file_id == ver_dep.version : i->project_id == ver_dep.addonId); }); dep != m_mods.end()) continue; // check the existing mods if (auto dep = std::find_if(m_pack_dependencies.begin(), m_pack_dependencies.end(), - [&ver_dep, providerName](std::shared_ptr i) { - return i->pack->addonId == ver_dep.addonId && i->pack->provider == providerName; + [&ver_dep, providerName, isOnlyVersion](std::shared_ptr i) { + return i->pack->provider == providerName && (isOnlyVersion ? i->version.version == ver_dep.addonId + : i->pack->addonId == ver_dep.addonId); }); dep != m_pack_dependencies.end()) // check loaded dependencies continue; @@ -110,22 +116,11 @@ QList GetModDependenciesTask::getDependenciesForVersion return c_dependencies; }; -Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Dependency& dep, - const ModPlatform::ResourceProvider providerName, - int level) +Task::Ptr GetModDependenciesTask::getProjectInfoTask(std::shared_ptr pDep) { - auto pDep = std::make_shared(); - pDep->dependency = dep; - pDep->pack = std::make_shared(); - pDep->pack->addonId = dep.addonId; - pDep->pack->provider = providerName; - m_pack_dependencies.append(pDep); - auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider; - - auto tasks = makeShared(this, QString("DependencyInfo: %1").arg(dep.addonId.toString())); - + auto provider = pDep->pack->provider == m_flame_provider.name ? m_flame_provider : m_modrinth_provider; auto responseInfo = new QByteArray(); - auto info = provider.api->getProject(dep.addonId.toString(), responseInfo); + auto info = provider.api->getProject(pDep->pack->addonId.toString(), responseInfo); QObject::connect(info.get(), &NetJob::succeeded, [responseInfo, provider, pDep] { QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*responseInfo, &parse_error); @@ -144,7 +139,27 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen qWarning() << "Error while reading mod info: " << e.cause(); } }); - tasks->addTask(info); + return info; +} + +Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Dependency& dep, + const ModPlatform::ResourceProvider providerName, + int level) +{ + auto pDep = std::make_shared(); + pDep->dependency = dep; + pDep->pack = std::make_shared(); + pDep->pack->addonId = dep.addonId; + pDep->pack->provider = providerName; + m_pack_dependencies.append(pDep); + auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider; + + auto tasks = makeShared( + this, QString("DependencyInfo: %1").arg(dep.addonId.toString().isEmpty() ? dep.version : dep.addonId.toString())); + + if (!dep.addonId.toString().isEmpty()) { + tasks->addTask(getProjectInfoTask(pDep)); + } ResourceAPI::DependencySearchArgs args = { dep, m_version, m_loaderType }; ResourceAPI::DependencySearchCallbacks callbacks; @@ -176,6 +191,10 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen qWarning() << "Dependency cycle exeeded"; return; } + if (dep.addonId.toString().isEmpty() && !pDep->version.addonId.toString().isEmpty()) { + pDep->pack->addonId = pDep->version.addonId; + addTask(getProjectInfoTask(pDep)); + } for (auto dep : getDependenciesForVersion(pDep->version, provider.name)) { addTask(prepareDependencyTask(dep, provider.name, level - 1)); } diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index 99d5afb0..f1876c61 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -68,6 +68,7 @@ class GetModDependenciesTask : public SequentialTask { QList getDependenciesForVersion(const ModPlatform::IndexedVersion&, const ModPlatform::ResourceProvider providerName); void prepare(); + Task::Ptr getProjectInfoTask(std::shared_ptr pDep); private: QList> m_pack_dependencies; diff --git a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp index 92b48e5f..b4037349 100644 --- a/launcher/modplatform/modrinth/ModrinthPackIndex.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackIndex.cpp @@ -144,7 +144,7 @@ auto Modrinth::loadIndexedPackVersion(QJsonObject& obj, QString preferred_hash_t for (auto d : dependencies) { auto dep = Json::ensureObject(d); ModPlatform::Dependency dependency; - dependency.addonId = Json::requireString(dep, "project_id"); + dependency.addonId = Json::ensureString(dep, "project_id"); dependency.version = Json::ensureString(dep, "version_id"); auto depType = Json::requireString(dep, "dependency_type"); diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index c7d9da4e..4f59f560 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -125,14 +125,22 @@ void ResourceDownloadDialog::connectButtons() static ModPlatform::ProviderCapabilities ProviderCaps; -QStringList getRequiredBy(QList tasks, QVariant addonId) +QStringList getRequiredBy(QList tasks, ResourceDownloadDialog::DownloadTaskPtr pack) { + auto addonId = pack->getPack()->addonId; + auto provider = pack->getPack()->provider; + auto version = pack->getVersionID(); auto req = QStringList(); for (auto& task : tasks) { + if (provider != task->getPack()->provider) + continue; auto deps = task->getVersion().dependencies; if (auto dep = std::find_if(deps.begin(), deps.end(), - [addonId](const ModPlatform::Dependency& d) { - return d.addonId == addonId && d.type == ModPlatform::DependencyType::REQUIRED; + [addonId, provider, version](const ModPlatform::Dependency& d) { + return d.type == ModPlatform::DependencyType::REQUIRED && + (provider == ModPlatform::ResourceProvider::MODRINTH && d.addonId.toString().isEmpty() + ? version == d.version + : d.addonId == addonId); }); dep != deps.end()) { req.append(task->getName()); @@ -179,7 +187,7 @@ void ResourceDownloadDialog::confirm() }); for (auto& task : selected) { confirm_dialog->appendResource({ task->getName(), task->getFilename(), task->getCustomPath(), - ProviderCaps.name(task->getProvider()), getRequiredBy(selected, task->getPack()->addonId) }); + ProviderCaps.name(task->getProvider()), getRequiredBy(selected, task) }); } if (confirm_dialog->exec()) { -- cgit From c13a90540cf782debddd63f1d2da46e43ed48c7a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 19 Jun 2023 21:20:35 +0300 Subject: Added overide for Quilt/Fabric Signed-off-by: Trial97 --- .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 28 +++++++++++++++++-- .../minecraft/mod/tasks/GetModDependenciesTask.h | 1 + launcher/modplatform/ModIndex.h | 16 +++++++++++ launcher/modplatform/flame/FlameAPI.h | 32 +++++++++++++++++++--- 4 files changed, 71 insertions(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 02281a35..093304b3 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -25,11 +25,13 @@ #include "QObjectPtr.h" #include "minecraft/mod/MetadataHandler.h" #include "modplatform/ModIndex.h" +#include "modplatform/ResourceAPI.h" #include "modplatform/flame/FlameAPI.h" #include "modplatform/modrinth/ModrinthAPI.h" #include "tasks/ConcurrentTask.h" #include "tasks/SequentialTask.h" #include "ui/pages/modplatform/ModModel.h" +#include "ui/pages/modplatform/ResourceModel.h" #include "ui/pages/modplatform/flame/FlameResourceModels.h" #include "ui/pages/modplatform/modrinth/ModrinthResourceModels.h" @@ -71,6 +73,21 @@ void GetModDependenciesTask::prepare() } } +auto GetModDependenciesTask::getOverride(const ModPlatform::Dependency& dep, const ModPlatform::ResourceProvider providerName) + -> ModPlatform::Dependency +{ + if (auto isQuilt = m_loaderType & ResourceAPI::Quilt; isQuilt || m_loaderType & ResourceAPI::Fabric) { + auto overide = ModPlatform::getOverrideDeps(); + auto over = std::find_if(overide.cbegin(), overide.cend(), [dep, providerName, isQuilt](auto o) { + return o.provider == providerName && dep.addonId == (isQuilt ? o.fabric : o.quilt); + }); + if (over != overide.cend()) { + return { isQuilt ? over->quilt : over->fabric, dep.type }; + } + } + return dep; +} + QList GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version, const ModPlatform::ResourceProvider providerName) { @@ -111,7 +128,7 @@ QList GetModDependenciesTask::getDependenciesForVersion dep != m_pack_dependencies.end()) // check loaded dependencies continue; - c_dependencies.append(ver_dep); + c_dependencies.append(getOverride(ver_dep, providerName)); } return c_dependencies; }; @@ -151,6 +168,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen pDep->pack = std::make_shared(); pDep->pack->addonId = dep.addonId; pDep->pack->provider = providerName; + m_pack_dependencies.append(pDep); auto provider = providerName == m_flame_provider.name ? m_flame_provider : m_modrinth_provider; @@ -193,7 +211,13 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen } if (dep.addonId.toString().isEmpty() && !pDep->version.addonId.toString().isEmpty()) { pDep->pack->addonId = pDep->version.addonId; - addTask(getProjectInfoTask(pDep)); + auto dep = getOverride({ pDep->version.addonId, pDep->dependency.type }, provider.name); + if (dep.addonId != pDep->version.addonId) { + auto toRemoveID = pDep->version.addonId; + m_pack_dependencies.removeIf([toRemoveID](auto v) { return v->pack->addonId == toRemoveID; }); + addTask(prepareDependencyTask(dep, provider.name, level)); + } else + addTask(getProjectInfoTask(pDep)); } for (auto dep : getDependenciesForVersion(pDep->version, provider.name)) { addTask(prepareDependencyTask(dep, provider.name, level - 1)); diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index f1876c61..7a4990f7 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -69,6 +69,7 @@ class GetModDependenciesTask : public SequentialTask { const ModPlatform::ResourceProvider providerName); void prepare(); Task::Ptr getProjectInfoTask(std::shared_ptr pDep); + auto getOverride(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider providerName) -> ModPlatform::Dependency; private: QList> m_pack_dependencies; diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 7236e63e..3b0a03a1 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -129,6 +129,22 @@ struct IndexedPack { } }; +struct OverrideDep { + QString quilt; + QString fabric; + QString slug; + ModPlatform::ResourceProvider provider; +}; + +inline auto getOverrideDeps() -> QList +{ + return { { "634179", "306612", "API", ModPlatform::ResourceProvider::FLAME }, + { "720410", "308769", "KotlinLibraries", ModPlatform::ResourceProvider::FLAME }, + + { "qvIfYCYJ", "P7dR8mSH", "API", ModPlatform::ResourceProvider::MODRINTH }, + { "lwVhp9o5", "Ha28R6CL", "KotlinLibraries", ModPlatform::ResourceProvider::MODRINTH } }; +}; + } // namespace ModPlatform Q_DECLARE_METATYPE(ModPlatform::IndexedPack) diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 4ffc36d2..89561a89 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -4,7 +4,9 @@ #pragma once +#include #include "modplatform/ModIndex.h" +#include "modplatform/ResourceAPI.h" #include "modplatform/helpers/NetworkResourceAPI.h" class FlameAPI : public NetworkResourceAPI { @@ -74,22 +76,44 @@ class FlameAPI : public NetworkResourceAPI { [[nodiscard]] std::optional getVersionsURL(VersionSearchArgs const& args) const override { - QString url{ QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(args.pack.addonId.toString()) }; + auto mappedModLoader = getMappedModLoader(args.loaders.value()); + auto addonId = args.pack.addonId.toString(); + if (args.loaders.value() & Quilt) { + auto overide = ModPlatform::getOverrideDeps(); + auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) { + return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt; + }); + if (over != overide.cend()) { + mappedModLoader = 5; + } + } + QString url{ QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(addonId) }; QStringList get_parameters; if (args.mcVersions.has_value()) get_parameters.append(QString("gameVersion=%1").arg(args.mcVersions.value().front().toString())); if (args.loaders.has_value()) - get_parameters.append(QString("modLoaderType=%1").arg(getMappedModLoader(args.loaders.value()))); + get_parameters.append(QString("modLoaderType=%1").arg(mappedModLoader)); return url + get_parameters.join('&'); }; [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override { + auto mappedModLoader = getMappedModLoader(args.loader); + auto addonId = args.dependency.addonId.toString(); + if (args.loader & Quilt) { + auto overide = ModPlatform::getOverrideDeps(); + auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) { + return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt; + }); + if (over != overide.cend()) { + mappedModLoader = 5; + } + } return QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&gameVersion=%2&modLoaderType=%3") - .arg(args.dependency.addonId.toString()) + .arg(addonId) .arg(args.mcVersion.toString()) - .arg(getMappedModLoader(args.loader)); + .arg(mappedModLoader); }; }; -- cgit From f6f0fbbd9f16afad16b8a401f87d741eba4be677 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 19 Jun 2023 21:23:48 +0300 Subject: Fixed removeIf Signed-off-by: Trial97 --- launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 093304b3..93c7f259 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -214,7 +214,17 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen auto dep = getOverride({ pDep->version.addonId, pDep->dependency.type }, provider.name); if (dep.addonId != pDep->version.addonId) { auto toRemoveID = pDep->version.addonId; - m_pack_dependencies.removeIf([toRemoveID](auto v) { return v->pack->addonId == toRemoveID; }); + + auto pred = [toRemoveID](auto v) { return v->pack->addonId == toRemoveID; }; +#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) + m_pack_dependencies.removeIf(pred); +#else + for (auto it = m_pack_dependencies.begin(); it != m_pack_dependencies.end();) + if (pred(*it)) + it = m_pack_dependencies.erase(it); + else + ++it; +#endif addTask(prepareDependencyTask(dep, provider.name, level)); } else addTask(getProjectInfoTask(pDep)); -- cgit From b62e4c0cc79d9d3074b37d879bb00df68c2973bc Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 19 Jun 2023 21:32:19 +0300 Subject: Fixed build Signed-off-by: Trial97 --- launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 6 +++--- launcher/minecraft/mod/tasks/GetModDependenciesTask.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 93c7f259..00611f32 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -73,8 +73,8 @@ void GetModDependenciesTask::prepare() } } -auto GetModDependenciesTask::getOverride(const ModPlatform::Dependency& dep, const ModPlatform::ResourceProvider providerName) - -> ModPlatform::Dependency +ModPlatform::Dependency GetModDependenciesTask::getOverride(const ModPlatform::Dependency& dep, + const ModPlatform::ResourceProvider providerName) { if (auto isQuilt = m_loaderType & ResourceAPI::Quilt; isQuilt || m_loaderType & ResourceAPI::Fabric) { auto overide = ModPlatform::getOverrideDeps(); @@ -215,7 +215,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen if (dep.addonId != pDep->version.addonId) { auto toRemoveID = pDep->version.addonId; - auto pred = [toRemoveID](auto v) { return v->pack->addonId == toRemoveID; }; + auto pred = [toRemoveID](const std::shared_ptr& v) { return v->pack->addonId == toRemoveID; }; #if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) m_pack_dependencies.removeIf(pred); #else diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index 7a4990f7..e2ad4825 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -69,7 +69,7 @@ class GetModDependenciesTask : public SequentialTask { const ModPlatform::ResourceProvider providerName); void prepare(); Task::Ptr getProjectInfoTask(std::shared_ptr pDep); - auto getOverride(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider providerName) -> ModPlatform::Dependency; + ModPlatform::Dependency getOverride(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider providerName); private: QList> m_pack_dependencies; -- cgit From d9b24f770561e3bb139955854ac7f3ca4d92a122 Mon Sep 17 00:00:00 2001 From: James Beddek Date: Tue, 20 Jun 2023 16:52:57 +1200 Subject: Screenshots: remove path from watcher if it no longer exists Signed-off-by: James Beddek --- launcher/ui/pages/instance/ScreenshotsPage.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp index ca368d3b..8f134efd 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.cpp +++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp @@ -145,7 +145,6 @@ public: m_thumbnailCache = std::make_shared(); m_thumbnailCache->add("placeholder", APPLICATION->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 @@ -214,10 +213,12 @@ private slots: void fileChanged(QString filepath) { m_thumbnailCache->setStale(filepath); - thumbnailImage(filepath); // reinsert the path... watcher.removePath(filepath); - watcher.addPath(filepath); + if (QFile::exists(filepath)) { + watcher.addPath(filepath); + thumbnailImage(filepath); + } } private: -- cgit From f2471f0f68e436d25d27ccc750e6668c07a29070 Mon Sep 17 00:00:00 2001 From: James Beddek Date: Tue, 20 Jun 2023 16:54:15 +1200 Subject: Screenshots: clear the thumbnailing pool on page delete Removes pending QThreadPool jobs which linger after page delete. May help with #1201 by allowing the pool to finish earlier. Signed-off-by: James Beddek --- launcher/ui/pages/instance/ScreenshotsPage.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp index 8f134efd..9d1f8421 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.cpp +++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp @@ -146,7 +146,11 @@ public: m_thumbnailCache->add("placeholder", APPLICATION->getThemedIcon("screenshot-placeholder")); connect(&watcher, SIGNAL(fileChanged(QString)), SLOT(fileChanged(QString))); } - virtual ~FilterModel() { m_thumbnailingPool.waitForDone(500); } + virtual ~FilterModel() { + m_thumbnailingPool.clear(); + if (!m_thumbnailingPool.waitForDone(500)) + qDebug() << "Thumbnail pool took longer than 500ms to finish"; + } virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const { auto model = sourceModel(); -- cgit From 75bd626f33a5182facff2ef1f9938f60553c3352 Mon Sep 17 00:00:00 2001 From: James Beddek Date: Tue, 20 Jun 2023 16:59:59 +1200 Subject: Screenshots: do not retry image thumbnailing on null result This causes the thumbnailing thread pool to spend a lot of time attempting to retry an image that failed. A null result is common where the image is too large to be allocated (>128MiB alloc). The repeated retries continue after page delete, causing hangs if a user tries to exit the application. Fixes: #1201 Signed-off-by: James Beddek --- launcher/ui/pages/instance/ScreenshotsPage.cpp | 51 +++++++++++--------------- 1 file changed, 22 insertions(+), 29 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp index 9d1f8421..75bb48b2 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.cpp +++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp @@ -96,37 +96,30 @@ public: 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); + if (!m_cache->stale(m_path)) + return; + QImage image(m_path); + if (image.isNull()) { + m_resultEmitter.emitResultsFailed(m_path); + qDebug() << "Error loading screenshot: " + m_path + ". Perhaps too large?"; return; } - m_resultEmitter.emitResultsFailed(m_path); + 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); } QString m_path; SharedIconCachePtr m_cache; -- cgit From f769b0b4c63888ac95416a4cc834aad2395f9b74 Mon Sep 17 00:00:00 2001 From: Alfio Date: Tue, 20 Jun 2023 10:25:11 +0200 Subject: Remove inconsistent/unneeded question marks in UI Signed-off-by: P2 --- launcher/minecraft/auth/AccountList.cpp | 6 +++--- launcher/ui/pages/global/LauncherPage.ui | 8 ++++---- launcher/ui/pages/global/MinecraftPage.ui | 2 +- launcher/ui/pages/instance/InstanceSettingsPage.ui | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp index 9e2fd111..c2794147 100644 --- a/launcher/minecraft/auth/AccountList.cpp +++ b/launcher/minecraft/auth/AccountList.cpp @@ -333,13 +333,13 @@ QVariant AccountList::data(const QModelIndex &index, int role) const case MigrationColumn: { if(account->isMSA() || account->isOffline()) { - return tr("N/A", "Can Migrate?"); + return tr("N/A", "Can Migrate"); } if (account->canMigrate()) { - return tr("Yes", "Can Migrate?"); + return tr("Yes", "Can Migrate"); } else { - return tr("No", "Can Migrate?"); + return tr("No", "Can Migrate"); } } diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index 55bd3eea..d9116bfc 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -172,7 +172,7 @@ Disable using metadata provided by mod providers (like Modrinth or Curseforge) for mods. - Disable using metadata for mods? + Disable using metadata for mods @@ -307,21 +307,21 @@ - Show console while the game is &running? + Show console while the game is &running - &Automatically close console when the game quits? + &Automatically close console when the game quits - Show console when the game &crashes? + Show console when the game &crashes diff --git a/launcher/ui/pages/global/MinecraftPage.ui b/launcher/ui/pages/global/MinecraftPage.ui index 103881b5..8f5de725 100644 --- a/launcher/ui/pages/global/MinecraftPage.ui +++ b/launcher/ui/pages/global/MinecraftPage.ui @@ -51,7 +51,7 @@ - Start Minecraft &maximized? + Start Minecraft &maximized diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.ui b/launcher/ui/pages/instance/InstanceSettingsPage.ui index 19d6dc02..8427965d 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.ui +++ b/launcher/ui/pages/instance/InstanceSettingsPage.ui @@ -269,7 +269,7 @@ - Start Minecraft maximized? + Start Minecraft maximized @@ -341,21 +341,21 @@ - Show console while the game is running? + Show console while the game is running - Automatically close console when the game quits? + Automatically close console when the game quits - Show console when the game crashes? + Show console when the game crashes -- cgit From 3e3be9ae6f902cc292ee26e4d330b078ddbb2a46 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 20 Jun 2023 13:28:57 +0300 Subject: Added fallback for quilt if the API or Kotilin is not present Signed-off-by: Trial97 --- .../minecraft/mod/tasks/GetModDependenciesTask.cpp | 38 ++++++++++++++-------- .../minecraft/mod/tasks/GetModDependenciesTask.h | 1 + 2 files changed, 26 insertions(+), 13 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index 00611f32..ebc9cf40 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -31,7 +31,6 @@ #include "tasks/ConcurrentTask.h" #include "tasks/SequentialTask.h" #include "ui/pages/modplatform/ModModel.h" -#include "ui/pages/modplatform/ResourceModel.h" #include "ui/pages/modplatform/flame/FlameResourceModels.h" #include "ui/pages/modplatform/modrinth/ModrinthResourceModels.h" @@ -192,6 +191,16 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen } pDep->version = provider.mod->loadDependencyVersions(dep, arr); if (!pDep->version.addonId.isValid()) { + if (m_loaderType & ResourceAPI::Quilt) { // falback for quilt + auto overide = ModPlatform::getOverrideDeps(); + auto over = std::find_if(overide.cbegin(), overide.cend(), + [dep, provider](auto o) { return o.provider == provider.name && dep.addonId == o.quilt; }); + if (over != overide.cend()) { + removePack(dep.addonId); + addTask(prepareDependencyTask({ over->fabric, dep.type }, provider.name, level)); + return; + } + } qWarning() << "Error while reading mod version empty "; qDebug() << doc; return; @@ -213,18 +222,7 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen pDep->pack->addonId = pDep->version.addonId; auto dep = getOverride({ pDep->version.addonId, pDep->dependency.type }, provider.name); if (dep.addonId != pDep->version.addonId) { - auto toRemoveID = pDep->version.addonId; - - auto pred = [toRemoveID](const std::shared_ptr& v) { return v->pack->addonId == toRemoveID; }; -#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) - m_pack_dependencies.removeIf(pred); -#else - for (auto it = m_pack_dependencies.begin(); it != m_pack_dependencies.end();) - if (pred(*it)) - it = m_pack_dependencies.erase(it); - else - ++it; -#endif + removePack(pDep->version.addonId); addTask(prepareDependencyTask(dep, provider.name, level)); } else addTask(getProjectInfoTask(pDep)); @@ -238,3 +236,17 @@ Task::Ptr GetModDependenciesTask::prepareDependencyTask(const ModPlatform::Depen tasks->addTask(version); return tasks; }; + +void GetModDependenciesTask::removePack(const QVariant addonId) +{ + auto pred = [addonId](const std::shared_ptr& v) { return v->pack->addonId == addonId; }; +#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) + m_pack_dependencies.removeIf(pred); +#else + for (auto it = m_pack_dependencies.begin(); it != m_pack_dependencies.end();) + if (pred(*it)) + it = m_pack_dependencies.erase(it); + else + ++it; +#endif +} diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h index e2ad4825..50eba6af 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.h +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.h @@ -70,6 +70,7 @@ class GetModDependenciesTask : public SequentialTask { void prepare(); Task::Ptr getProjectInfoTask(std::shared_ptr pDep); ModPlatform::Dependency getOverride(const ModPlatform::Dependency&, const ModPlatform::ResourceProvider providerName); + void removePack(const QVariant addonId); private: QList> m_pack_dependencies; -- cgit From a32a3e25adbb20e31749828cca84a3ff3878f094 Mon Sep 17 00:00:00 2001 From: Jakub Wroński Date: Tue, 20 Jun 2023 12:11:28 +0200 Subject: Fix compiling on FreeBSD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jakub Wroński --- launcher/FileSystem.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index d98526df..835ad925 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -102,7 +102,7 @@ namespace fs = ghc::filesystem; #include #include #include -#elif defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) +#elif defined(Q_OS_MACOS) || defined(Q_OS_OPENBSD) #include #include #elif defined(Q_OS_WIN) @@ -1151,7 +1151,7 @@ bool clone_file(const QString& src, const QString& dst, std::error_code& ec) return false; } -#elif defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) +#elif defined(Q_OS_MACOS) || defined(Q_OS_OPENBSD) if (!macos_bsd_clonefile(src_path, dst_path, ec)) { qDebug() << "failed macos_bsd_clonefile:"; @@ -1380,7 +1380,7 @@ bool linux_ficlone(const std::string& src_path, const std::string& dst_path, std return true; } -#elif defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) +#elif defined(Q_OS_MACOS) || defined(Q_OS_OPENBSD) bool macos_bsd_clonefile(const std::string& src_path, const std::string& dst_path, std::error_code& ec) { -- cgit From 009623823d6036ea22b34b21812758666fb8f7ba Mon Sep 17 00:00:00 2001 From: James Beddek Date: Tue, 20 Jun 2023 23:00:13 +1200 Subject: Modrinth: use default icon for non-managed packs Fixes: #317 Signed-off-by: James Beddek --- launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp index bb8227aa..76f07277 100644 --- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp @@ -214,7 +214,7 @@ bool ModrinthCreationTask::createInstance() if (m_instIcon != "default") { instance.setIconKey(m_instIcon); - } else { + } else if (!m_managed_id.isEmpty()) { instance.setIconKey("modrinth"); } -- cgit From f2692e60f3b7f1281750c4e97268830b9db30e95 Mon Sep 17 00:00:00 2001 From: Chris Lane Date: Tue, 20 Jun 2023 12:44:44 +0100 Subject: Add missing space in java checker debug message Signed-off-by: Chris Lane --- launcher/java/JavaChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp index b4c55b3d..916a010c 100644 --- a/launcher/java/JavaChecker.cpp +++ b/launcher/java/JavaChecker.cpp @@ -85,7 +85,7 @@ void JavaChecker::performCheck() process->setProgram(m_path); process->setProcessChannelMode(QProcess::SeparateChannels); process->setProcessEnvironment(CleanEnviroment()); - qDebug() << "Running java checker: " + m_path + args.join(" ");; + qDebug() << "Running java checker: " + m_path + " " + args.join(" ");; connect(process.get(), QOverload::of(&QProcess::finished), this, &JavaChecker::finished); connect(process.get(), &QProcess::errorOccurred, this, &JavaChecker::error); -- cgit From 07f3d27fb89e1e5a32ca25e7111c98a29ab12e8c Mon Sep 17 00:00:00 2001 From: Chris Lane Date: Tue, 20 Jun 2023 15:36:25 +0100 Subject: Clean up 'Running java checker' debug msg code Signed-off-by: Chris Lane --- launcher/java/JavaChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp index 916a010c..755e34c6 100644 --- a/launcher/java/JavaChecker.cpp +++ b/launcher/java/JavaChecker.cpp @@ -85,7 +85,7 @@ void JavaChecker::performCheck() process->setProgram(m_path); process->setProcessChannelMode(QProcess::SeparateChannels); process->setProcessEnvironment(CleanEnviroment()); - qDebug() << "Running java checker: " + m_path + " " + args.join(" ");; + qDebug() << "Running java checker:" << m_path << args.join(" "); connect(process.get(), QOverload::of(&QProcess::finished), this, &JavaChecker::finished); connect(process.get(), &QProcess::errorOccurred, this, &JavaChecker::error); -- cgit From 9ad29e8d85d66b9008892bd3298cc7d709c2ad17 Mon Sep 17 00:00:00 2001 From: Chris Lane Date: Tue, 20 Jun 2023 15:51:31 +0100 Subject: Remove extra spaces in one more Java checker debug Signed-off-by: Chris Lane --- launcher/java/JavaChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp index 755e34c6..e4a686c2 100644 --- a/launcher/java/JavaChecker.cpp +++ b/launcher/java/JavaChecker.cpp @@ -128,7 +128,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) result.outLog = m_stdout; qDebug() << "STDOUT" << m_stdout; qWarning() << "STDERR" << m_stderr; - qDebug() << "Java checker finished with status " << status << " exit code " << exitcode; + qDebug() << "Java checker finished with status" << status << "exit code" << exitcode; if (status == QProcess::CrashExit || exitcode == 1) { -- cgit From 470518eb3a3e0e43d67b7a15823c060755ad3284 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Wed, 21 Jun 2023 02:31:40 -0700 Subject: fix: resize columns on hide ^& uniform heights Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/minecraft/mod/ModFolderModel.cpp | 2 +- launcher/minecraft/mod/ResourceFolderModel.cpp | 4 ++++ launcher/minecraft/mod/ResourceFolderModel.h | 2 +- launcher/ui/pages/instance/ExternalResourcesPage.ui | 3 +++ 4 files changed, 9 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index e745f954..af98d834 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -60,7 +60,7 @@ ModFolderModel::ModFolderModel(const QString& dir, BaseInstance* instance, bool m_column_names = QStringList({ "Enable", "Image", "Name", "Version", "Last Modified", "Provider" }); m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Version"), tr("Last Modified"), tr("Provider") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME , SortType::VERSION, SortType::DATE, SortType::PROVIDER}; - m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents}; + m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents}; } QVariant ModFolderModel::data(const QModelIndex &index, int role) const diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index b60f8182..7700fd36 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -558,6 +558,10 @@ QMenu* ResourceFolderModel::createHeaderContextMenu(QTreeView* tree) connect(act, &QAction::toggled, tree, [this, col, tree](bool toggled){ tree->setColumnHidden(col, !toggled); + for(int c = 0; c < columnCount(); ++c) { + if (m_column_resize_modes.at(c) == QHeaderView::ResizeToContents) + tree->resizeColumnToContents(c); + } saveHiddenColumn(col, !toggled); }); diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 3c9c4d89..eb1d7c4f 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -201,7 +201,7 @@ class ResourceFolderModel : public QAbstractListModel { QList m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE }; QStringList m_column_names = {"Enable", "Name", "Last Modified"}; QStringList m_column_names_translated = {tr("Enable"), tr("Name"), tr("Last Modified")}; - QList m_column_resize_modes = { QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents }; + QList m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents }; bool m_can_interact = true; diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 33a03336..f676361c 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -62,6 +62,9 @@ QAbstractItemView::DropOnly + + true + -- cgit From 480faca5598b503eb130566061f06348e4a42b8f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 21 Jun 2023 21:17:17 +0300 Subject: Removed unused variable Signed-off-by: Trial97 --- launcher/ui/pages/instance/ExternalResourcesPage.cpp | 15 --------------- launcher/ui/pages/instance/ExternalResourcesPage.h | 2 -- launcher/ui/pages/instance/ModFolderPage.cpp | 4 +--- launcher/ui/pages/instance/ResourcePackPage.cpp | 2 -- launcher/ui/pages/instance/ShaderPackPage.cpp | 3 --- launcher/ui/pages/instance/TexturePackPage.cpp | 2 -- 6 files changed, 1 insertion(+), 27 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index e50fa635..e77e4572 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -135,9 +135,6 @@ void ExternalResourcesPage::retranslate() void ExternalResourcesPage::itemActivated(const QModelIndex&) { - if (!m_controlsEnabled) - return; - auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); m_model->setResourceEnabled(selection.indexes(), EnableAction::TOGGLE); } @@ -182,9 +179,6 @@ bool ExternalResourcesPage::eventFilter(QObject* obj, QEvent* ev) void ExternalResourcesPage::addItem() { - if (!m_controlsEnabled) - return; - auto list = GuiUtil::BrowseForFiles( helpPage(), tr("Select %1", "Select whatever type of files the page contains. Example: 'Loader Mods'").arg(displayName()), m_fileSelectionFilter.arg(displayName()), APPLICATION->settings()->get("CentralModsDir").toString(), this->parentWidget()); @@ -198,9 +192,6 @@ void ExternalResourcesPage::addItem() void ExternalResourcesPage::removeItem() { - if (!m_controlsEnabled) - return; - auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); int count = 0; @@ -249,18 +240,12 @@ void ExternalResourcesPage::removeItems(const QItemSelection& selection) void ExternalResourcesPage::enableItem() { - if (!m_controlsEnabled) - return; - auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); m_model->setResourceEnabled(selection.indexes(), EnableAction::ENABLE); } void ExternalResourcesPage::disableItem() { - if (!m_controlsEnabled) - return; - auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); m_model->setResourceEnabled(selection.indexes(), EnableAction::DISABLE); } diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.h b/launcher/ui/pages/instance/ExternalResourcesPage.h index fd200193..acea81b5 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.h +++ b/launcher/ui/pages/instance/ExternalResourcesPage.h @@ -72,7 +72,5 @@ class ExternalResourcesPage : public QMainWindow, public BasePage { QString m_fileSelectionFilter; QString m_viewFilter; - bool m_controlsEnabled = true; - std::shared_ptr m_wide_bar_setting = nullptr; }; diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 90e7d0d6..ef7b1f2b 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -133,15 +133,13 @@ bool ModFolderPage::onSelectionChanged(const QModelIndex& current, const QModelI return true; } -void ModFolderPage::removeItems(const QItemSelection &selection) +void ModFolderPage::removeItems(const QItemSelection& selection) { m_model->deleteMods(selection.indexes()); } void ModFolderPage::installMods() { - if (!m_controlsEnabled) - return; if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance diff --git a/launcher/ui/pages/instance/ResourcePackPage.cpp b/launcher/ui/pages/instance/ResourcePackPage.cpp index 24bfb38d..12b371df 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.cpp +++ b/launcher/ui/pages/instance/ResourcePackPage.cpp @@ -67,8 +67,6 @@ bool ResourcePackPage::onSelectionChanged(const QModelIndex& current, const QMod void ResourcePackPage::downloadRPs() { - if (!m_controlsEnabled) - return; if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance diff --git a/launcher/ui/pages/instance/ShaderPackPage.cpp b/launcher/ui/pages/instance/ShaderPackPage.cpp index 2d0c10aa..dc8b0a05 100644 --- a/launcher/ui/pages/instance/ShaderPackPage.cpp +++ b/launcher/ui/pages/instance/ShaderPackPage.cpp @@ -46,7 +46,6 @@ #include "ui/dialogs/ProgressDialog.h" #include "ui/dialogs/ResourceDownloadDialog.h" - ShaderPackPage::ShaderPackPage(MinecraftInstance* instance, std::shared_ptr model, QWidget* parent) : ExternalResourcesPage(instance, model, parent) { @@ -61,8 +60,6 @@ ShaderPackPage::ShaderPackPage(MinecraftInstance* instance, std::shared_ptrtypeName() != "Minecraft") return; // this is a null instance or a legacy instance diff --git a/launcher/ui/pages/instance/TexturePackPage.cpp b/launcher/ui/pages/instance/TexturePackPage.cpp index 427aba11..e477ceda 100644 --- a/launcher/ui/pages/instance/TexturePackPage.cpp +++ b/launcher/ui/pages/instance/TexturePackPage.cpp @@ -69,8 +69,6 @@ bool TexturePackPage::onSelectionChanged(const QModelIndex& current, const QMode void TexturePackPage::downloadTPs() { - if (!m_controlsEnabled) - return; if (m_instance->typeName() != "Minecraft") return; // this is a null instance or a legacy instance -- cgit From 0d2105dec44bb1b5234e18ce6a8de5b2d26eb93a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 21 Jun 2023 21:34:40 +0300 Subject: Made buttons on ModsFolderPage enabled all the time Signed-off-by: Trial97 --- launcher/minecraft/MinecraftInstance.cpp | 15 ++---- launcher/minecraft/mod/ModFolderModel.cpp | 11 ++-- launcher/minecraft/mod/ResourceFolderModel.cpp | 69 +++++++++----------------- launcher/minecraft/mod/ResourceFolderModel.h | 14 +++--- launcher/ui/pages/instance/ModFolderPage.cpp | 20 +------- launcher/ui/pages/instance/ModFolderPage.h | 3 +- 6 files changed, 39 insertions(+), 93 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index f8ed5214..e896799a 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -1112,36 +1112,27 @@ JavaVersion MinecraftInstance::getJavaVersion() std::shared_ptr MinecraftInstance::loaderModList() { - if (!m_loader_mod_list) - { + if (!m_loader_mod_list) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_loader_mod_list.reset(new ModFolderModel(modsRoot(), this, is_indexed)); - m_loader_mod_list->disableInteraction(isRunning()); - connect(this, &BaseInstance::runningStatusChanged, m_loader_mod_list.get(), &ModFolderModel::disableInteraction); } return m_loader_mod_list; } std::shared_ptr MinecraftInstance::coreModList() { - if (!m_core_mod_list) - { + if (!m_core_mod_list) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_core_mod_list.reset(new ModFolderModel(coreModsDir(), this, is_indexed)); - m_core_mod_list->disableInteraction(isRunning()); - connect(this, &BaseInstance::runningStatusChanged, m_core_mod_list.get(), &ModFolderModel::disableInteraction); } return m_core_mod_list; } std::shared_ptr MinecraftInstance::nilModList() { - if (!m_nil_mod_list) - { + if (!m_nil_mod_list) { bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); m_nil_mod_list.reset(new ModFolderModel(nilModsDir(), this, is_indexed, false)); - m_nil_mod_list->disableInteraction(isRunning()); - connect(this, &BaseInstance::runningStatusChanged, m_nil_mod_list.get(), &ModFolderModel::disableInteraction); } return m_nil_mod_list; } diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 5e3b31e0..0089cd8b 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -213,16 +213,11 @@ bool ModFolderModel::uninstallMod(const QString& filename, bool preserve_metadat bool ModFolderModel::deleteMods(const QModelIndexList& indexes) { - if(!m_can_interact) { - return false; - } - - if(indexes.isEmpty()) + if (indexes.isEmpty()) return true; - for (auto i: indexes) - { - if(i.column() != 0) { + for (auto i : indexes) { + if (i.column() != 0) { continue; } auto m = at(i.row()); diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index d2d875e4..c38e97d9 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -74,10 +74,6 @@ bool ResourceFolderModel::stopWatching(const QStringList paths) bool ResourceFolderModel::installResource(QString original_path) { - if (!m_can_interact) { - return false; - } - // NOTE: fix for GH-1178: remove trailing slash to avoid issues with using the empty result of QFileInfo::fileName original_path = FS::NormalizePath(original_path); QFileInfo file_info(original_path); @@ -168,9 +164,6 @@ bool ResourceFolderModel::uninstallResource(QString file_name) bool ResourceFolderModel::deleteResources(const QModelIndexList& indexes) { - if (!m_can_interact) - return false; - if (indexes.isEmpty()) return true; @@ -189,11 +182,8 @@ bool ResourceFolderModel::deleteResources(const QModelIndexList& indexes) return true; } -bool ResourceFolderModel::setResourceEnabled(const QModelIndexList &indexes, EnableAction action) +bool ResourceFolderModel::setResourceEnabled(const QModelIndexList& indexes, EnableAction action) { - if (!m_can_interact) - return false; - if (indexes.isEmpty()) return true; @@ -246,15 +236,18 @@ bool ResourceFolderModel::update() connect(m_current_update_task.get(), &Task::succeeded, this, &ResourceFolderModel::onUpdateSucceeded, Qt::ConnectionType::QueuedConnection); connect(m_current_update_task.get(), &Task::failed, this, &ResourceFolderModel::onUpdateFailed, Qt::ConnectionType::QueuedConnection); - connect(m_current_update_task.get(), &Task::finished, this, [=] { - m_current_update_task.reset(); - if (m_scheduled_update) { - m_scheduled_update = false; - update(); - } else { - emit updateFinished(); - } - }, Qt::ConnectionType::QueuedConnection); + connect( + m_current_update_task.get(), &Task::finished, this, + [=] { + m_current_update_task.reset(); + if (m_scheduled_update) { + m_scheduled_update = false; + update(); + } else { + emit updateFinished(); + } + }, + Qt::ConnectionType::QueuedConnection); QThreadPool::globalInstance()->start(m_current_update_task.get()); @@ -344,15 +337,9 @@ Qt::DropActions ResourceFolderModel::supportedDropActions() const Qt::ItemFlags ResourceFolderModel::flags(const QModelIndex& index) const { Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index); - auto flags = defaultFlags; - if (!m_can_interact) { - flags &= ~Qt::ItemIsDropEnabled; - } else { - flags |= Qt::ItemIsDropEnabled; - if (index.isValid()) { - flags |= Qt::ItemIsUserCheckable; - } - } + auto flags = defaultFlags | Qt::ItemIsDropEnabled; + if (index.isValid()) + flags |= Qt::ItemIsUserCheckable; return flags; } @@ -425,16 +412,17 @@ QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const if (column == NAME_COLUMN) { if (at(row).isSymLinkUnder(instDirPath())) { return m_resources[row]->internal_id() + - tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." - "\nCanonical Path: %1") - .arg(at(row).fileinfo().canonicalFilePath());; + tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original." + "\nCanonical Path: %1") + .arg(at(row).fileinfo().canonicalFilePath()); + ; } if (at(row).isMoreThanOneHardLink()) { return m_resources[row]->internal_id() + - tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original."); + tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original."); } } - + return m_resources[row]->internal_id(); case Qt::DecorationRole: { if (column == NAME_COLUMN && (at(row).isSymLinkUnder(instDirPath()) || at(row).isMoreThanOneHardLink())) @@ -511,16 +499,6 @@ SortType ResourceFolderModel::columnToSortKey(size_t column) const return m_column_sort_keys.at(column); } -void ResourceFolderModel::enableInteraction(bool enabled) -{ - if (m_can_interact == enabled) - return; - - m_can_interact = enabled; - if (size()) - emit dataChanged(index(0), index(size() - 1)); -} - /* Standard Proxy Model for createFilterProxyModel */ [[nodiscard]] bool ResourceFolderModel::ProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const { @@ -556,6 +534,7 @@ void ResourceFolderModel::enableInteraction(bool enabled) return (compare_result.first > 0); } -QString ResourceFolderModel::instDirPath() const { +QString ResourceFolderModel::instDirPath() const +{ return QFileInfo(m_instance->instanceRoot()).absoluteFilePath(); } diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 0a35e1bc..d5ca08e8 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -11,8 +11,8 @@ #include "BaseInstance.h" -#include "tasks/Task.h" #include "tasks/ConcurrentTask.h" +#include "tasks/Task.h" class QSortFilterProxyModel; @@ -129,10 +129,6 @@ class ResourceFolderModel : public QAbstractListModel { QString instDirPath() const; - public slots: - void enableInteraction(bool enabled); - void disableInteraction(bool disabled) { enableInteraction(!disabled); } - signals: void updateFinished(); @@ -181,15 +177,17 @@ class ResourceFolderModel : public QAbstractListModel { * if the resource is complex and has more stuff to parse. */ virtual void onParseSucceeded(int ticket, QString resource_id); - virtual void onParseFailed(int ticket, QString resource_id) { Q_UNUSED(ticket); Q_UNUSED(resource_id); } + virtual void onParseFailed(int ticket, QString resource_id) + { + Q_UNUSED(ticket); + Q_UNUSED(resource_id); + } protected: // Represents the relationship between a column's index (represented by the list index), and it's sorting key. // As such, the order in with they appear is very important! QList m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE }; - bool m_can_interact = true; - QDir m_dir; BaseInstance* m_instance; QFileSystemWatcher m_watcher; diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index ef7b1f2b..9812bbe9 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -86,9 +86,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionsToolbar->insertActionAfter(ui->actionAddItem, ui->actionUpdateItem); connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods); - auto check_allow_update = [this] { - return (!m_instance || !m_instance->isRunning()) && (ui->treeView->selectionModel()->hasSelection() || !m_model->empty()); - }; + auto check_allow_update = [this] { return ui->treeView->selectionModel()->hasSelection() || !m_model->empty(); }; connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); @@ -101,22 +99,9 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr connect(mods.get(), &ModFolderModel::updateFinished, this, [this, check_allow_update] { ui->actionUpdateItem->setEnabled(check_allow_update()); }); - - connect(m_instance, &BaseInstance::runningStatusChanged, this, &ModFolderPage::runningStateChanged); - ModFolderPage::runningStateChanged(m_instance && m_instance->isRunning()); } } -void ModFolderPage::runningStateChanged(bool running) -{ - ui->actionDownloadItem->setEnabled(!running); - ui->actionUpdateItem->setEnabled(!running); - ui->actionAddItem->setEnabled(!running); - ui->actionEnableItem->setEnabled(!running); - ui->actionDisableItem->setEnabled(!running); - ui->actionRemoveItem->setEnabled(!running); -} - bool ModFolderPage::shouldDisplay() const { return true; @@ -205,8 +190,7 @@ void ModFolderPage::updateMods() message = tr("All selected mods are up-to-date! :)"); } } - CustomMessageBox::selectable(this, tr("Update checker"), message) - ->exec(); + CustomMessageBox::selectable(this, tr("Update checker"), message)->exec(); return; } diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h index 2fc7b574..b5984195 100644 --- a/launcher/ui/pages/instance/ModFolderPage.h +++ b/launcher/ui/pages/instance/ModFolderPage.h @@ -59,8 +59,7 @@ class ModFolderPage : public ExternalResourcesPage { bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override; private slots: - void runningStateChanged(bool running); - void removeItems(const QItemSelection &selection) override; + void removeItems(const QItemSelection& selection) override; void installMods(); void updateMods(); -- cgit From 820892d7cc7864315bd73dcd877cb0a1beb2b106 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 21 Jun 2023 22:42:08 +0300 Subject: Made settings editable when instance is running Signed-off-by: Trial97 --- launcher/ui/pages/instance/InstanceSettingsPage.cpp | 13 ++----------- launcher/ui/pages/instance/InstanceSettingsPage.h | 3 +-- 2 files changed, 3 insertions(+), 13 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 08977841..1108d264 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -60,17 +60,13 @@ InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) m_settings = inst->settings(); ui->setupUi(this); - // As the signal will (probably) not be triggered once we click edit, let's update it manually instead. - updateRunningStatus(m_instance->isRunning()); - - connect(m_instance, &BaseInstance::runningStatusChanged, this, &InstanceSettingsPage::updateRunningStatus); connect(ui->openGlobalJavaSettingsButton, &QCommandLinkButton::clicked, this, &InstanceSettingsPage::globalSettingsButtonClicked); connect(APPLICATION, &Application::globalSettingsAboutToOpen, this, &InstanceSettingsPage::applySettings); connect(APPLICATION, &Application::globalSettingsClosed, this, &InstanceSettingsPage::loadSettings); - connect(ui->instanceAccountSelector, QOverload::of(&QComboBox::currentIndexChanged), this, &InstanceSettingsPage::changeInstanceAccount); + connect(ui->instanceAccountSelector, QOverload::of(&QComboBox::currentIndexChanged), this, + &InstanceSettingsPage::changeInstanceAccount); loadSettings(); - updateThresholds(); } @@ -523,8 +519,3 @@ void InstanceSettingsPage::updateThresholds() ui->labelMaxMemIcon->setPixmap(pix); } } - -void InstanceSettingsPage::updateRunningStatus(bool running) -{ - setEnabled(!running); -} diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.h b/launcher/ui/pages/instance/InstanceSettingsPage.h index 0438fe3b..036b4181 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.h +++ b/launcher/ui/pages/instance/InstanceSettingsPage.h @@ -79,8 +79,7 @@ public: void updateThresholds(); -private slots: - void updateRunningStatus(bool running); + private slots: void on_javaDetectBtn_clicked(); void on_javaTestBtn_clicked(); void on_javaBrowseBtn_clicked(); -- cgit From 2e82c1d40cd43aef4745726d51dd6a9df2d8f78b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 21 Jun 2023 23:22:25 +0300 Subject: Added regex expresion to exclude .DS_Store files Signed-off-by: Trial97 --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 239873f6..561b92e4 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -53,6 +53,7 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) const QDir root(instance->gameRoot()); proxy = new FileIgnoreProxy(instance->gameRoot(), this); proxy->setSourceModel(model); + proxy->setFilterRegularExpression("^(?!\\.DS_Store).+$"); const QDir::Filters filter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); -- cgit From 9ad356d66f4c7bf1ccbbe251df800ebb1c4b67d4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 16:00:45 +0300 Subject: Added ExportModsToStringTask Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 3 + .../modplatform/helpers/ExportModsToStringTask.cpp | 114 +++++++++++++++++++++ .../modplatform/helpers/ExportModsToStringTask.h | 33 ++++++ 3 files changed, 150 insertions(+) create mode 100644 launcher/modplatform/helpers/ExportModsToStringTask.cpp create mode 100644 launcher/modplatform/helpers/ExportModsToStringTask.h (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ce2771a4..c7efdad8 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -487,6 +487,9 @@ set(API_SOURCES modplatform/helpers/HashUtils.cpp modplatform/helpers/OverrideUtils.h modplatform/helpers/OverrideUtils.cpp + + modplatform/helpers/ExportModsToStringTask.h + modplatform/helpers/ExportModsToStringTask.cpp ) set(FTB_SOURCES diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp new file mode 100644 index 00000000..a105fc35 --- /dev/null +++ b/launcher/modplatform/helpers/ExportModsToStringTask.cpp @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * 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 . + */ +#include "ExportModsToStringTask.h" +#include "modplatform/ModIndex.h" + +namespace ExportToString { +QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData) +{ + switch (format) { + case HTML: { + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + if (extraData & Url) { + auto url = mod->homeurl(); + if (meta != nullptr) { + url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" + : "https://modrinth.com/mod/") + + meta->project_id.toString(); + } + if (!url.isEmpty()) + modName = QString("%2").arg(url, modName); + } + auto line = modName; + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + line += QString("[%1]").arg(ver); + } + if (extraData & Authors && !mod->authors().isEmpty()) + line += " by " + mod->authors().join(", "); + lines.append(QString("
    %1
").arg(line)); + } + return QString("\n\t%1\n").arg(lines.join("\n\t")); + } + case MARKDOWN: { + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + if (extraData & Url) { + auto url = mod->homeurl(); + if (meta != nullptr) { + url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" + : "https://modrinth.com/mod/") + + meta->project_id.toString(); + } + if (!url.isEmpty()) + modName = QString("[%1](%2)").arg(modName, url); + } + auto line = modName; + if (extraData & Version) { + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + if (!ver.isEmpty()) + line += QString("[%1]").arg(ver); + } + if (extraData & Authors && !mod->authors().isEmpty()) + line += " by " + mod->authors().join(", "); + lines << line; + } + return lines.join("\n"); + } + default: { + return QString("unknown format:%1").arg(format); + } + } +} + +QString ExportModsToStringTask(QList mods, QString lineTemplate) +{ + QStringList lines; + for (auto mod : mods) { + auto meta = mod->metadata(); + auto modName = mod->name(); + + auto url = mod->homeurl(); + if (meta != nullptr) { + url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" + : "https://modrinth.com/mod/") + + meta->project_id.toString(); + } + auto ver = mod->version(); + if (ver.isEmpty() && meta != nullptr) + ver = meta->version().toString(); + auto authors = mod->authors().join(", "); + lines << QString(lineTemplate) + .replace("{name}", modName) + .replace("{url}", url) + .replace("{version}", ver) + .replace("{authors}", authors); + } + return lines.join("\n"); +} +} // namespace ExportToString \ No newline at end of file diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.h b/launcher/modplatform/helpers/ExportModsToStringTask.h new file mode 100644 index 00000000..756c69f7 --- /dev/null +++ b/launcher/modplatform/helpers/ExportModsToStringTask.h @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * 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 . + */ +#pragma once +#include +#include +#include "minecraft/mod/Mod.h" + +namespace ExportToString { + +enum Formats { HTML, MARKDOWN }; +enum OptionalData { + Authors = 1 << 0, + Url = 1 << 1, + Version = 1 << 2, +}; +QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData); +QString ExportModsToStringTask(QList mods, QString lineTemplate); +} // namespace ExportToString -- cgit From 4e07f9574af10943577726f795fc8fad249e90e4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 18:11:03 +0300 Subject: Use slug for url Signed-off-by: Trial97 --- launcher/modplatform/helpers/ExportModsToStringTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp index a105fc35..c10560c1 100644 --- a/launcher/modplatform/helpers/ExportModsToStringTask.cpp +++ b/launcher/modplatform/helpers/ExportModsToStringTask.cpp @@ -32,7 +32,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex if (meta != nullptr) { url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" : "https://modrinth.com/mod/") + - meta->project_id.toString(); + meta->slug.remove(".pw.toml"); } if (!url.isEmpty()) modName = QString("%2").arg(url, modName); @@ -61,7 +61,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex if (meta != nullptr) { url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" : "https://modrinth.com/mod/") + - meta->project_id.toString(); + meta->slug.remove(".pw.toml"); } if (!url.isEmpty()) modName = QString("[%1](%2)").arg(modName, url); -- cgit From 58321f34915bd22ab8a2c195b64af3006d962be9 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 20:03:44 +0300 Subject: Added curseforge export Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 2 + launcher/modplatform/flame/FlamePackExportTask.cpp | 223 +++++++++++++++++++++ launcher/modplatform/flame/FlamePackExportTask.h | 74 +++++++ launcher/ui/MainWindow.cpp | 9 + launcher/ui/MainWindow.h | 1 + launcher/ui/MainWindow.ui | 8 + launcher/ui/dialogs/ExportMrPackDialog.cpp | 30 ++- launcher/ui/dialogs/ExportMrPackDialog.h | 6 +- 8 files changed, 342 insertions(+), 11 deletions(-) create mode 100644 launcher/modplatform/flame/FlamePackExportTask.cpp create mode 100644 launcher/modplatform/flame/FlamePackExportTask.h (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index c7efdad8..df6c9012 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -517,6 +517,8 @@ set(FLAME_SOURCES modplatform/flame/FlameCheckUpdate.h modplatform/flame/FlameInstanceCreationTask.h modplatform/flame/FlameInstanceCreationTask.cpp + modplatform/flame/FlamePackExportTask.h + modplatform/flame/FlamePackExportTask.cpp ) set(MODRINTH_SOURCES diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp new file mode 100644 index 00000000..1ae13f72 --- /dev/null +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * 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 . + */ + +#include "FlamePackExportTask.h" +#include +#include + +#include +#include +#include +#include +#include "Json.h" +#include "MMCZip.h" +#include "minecraft/PackProfile.h" +#include "minecraft/mod/ModFolderModel.h" +#include "modplatform/helpers/ExportModsToStringTask.h" + +const QStringList FlamePackExportTask::PREFIXES({ "mods/", "coremods/", "resourcepacks/", "texturepacks/", "shaderpacks/" }); +const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "litemod", "zip" }); +const QString FlamePackExportTask::TEMPLATE = "
  • {name}({authors})
  • "; + +FlamePackExportTask::FlamePackExportTask(const QString& name, + const QString& version, + const QVariant& projectID, + InstancePtr instance, + const QString& output, + MMCZip::FilterFunction filter) + : name(name) + , version(version) + , projectID(projectID) + , instance(instance) + , mcInstance(dynamic_cast(instance.get())) + , gameRoot(instance->gameRoot()) + , output(output) + , filter(filter) +{} + +void FlamePackExportTask::executeTask() +{ + setStatus(tr("Searching for files...")); + setProgress(0, 0); + collectFiles(); +} + +bool FlamePackExportTask::abort() +{ + if (task != nullptr) { + task->abort(); + task = nullptr; + emitAborted(); + return true; + } + + if (buildZipFuture.isRunning()) { + buildZipFuture.cancel(); + // NOTE: Here we don't do `emitAborted()` because it will be done when `buildZipFuture` actually cancels, which may not occur + // immediately. + return true; + } + + return false; +} + +void FlamePackExportTask::collectFiles() +{ + setAbortable(false); + QCoreApplication::processEvents(); + + files.clear(); + if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) { + emitFailed(tr("Could not search for files")); + return; + } + + resolvedFiles.clear(); + + mcInstance->loaderModList()->update(); + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, [this]() { + mods = mcInstance->loaderModList()->allMods(); + buildZip(); + }); +} + +void FlamePackExportTask::buildZip() +{ + setStatus(tr("Adding files...")); + + buildZipFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { + QuaZip zip(output); + if (!zip.open(QuaZip::mdCreate)) { + QFile::remove(output); + return BuildZipResult(tr("Could not create file")); + } + + if (buildZipFuture.isCanceled()) + return BuildZipResult(); + + QuaZipFile indexFile(&zip); + if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("manifest.json"))) { + QFile::remove(output); + return BuildZipResult(tr("Could not create index")); + } + indexFile.write(generateIndex()); + + QuaZipFile modlist(&zip); + if (!modlist.open(QIODevice::WriteOnly, QuaZipNewInfo("modlist.html"))) { + QFile::remove(output); + return BuildZipResult(tr("Could not create index")); + } + QString content = ExportToString::ExportModsToStringTask(mods, TEMPLATE); + content = "
      " + content + "
    "; + modlist.write(content.toUtf8()); + + size_t progress = 0; + for (const QFileInfo& file : files) { + if (buildZipFuture.isCanceled()) { + QFile::remove(output); + return BuildZipResult(); + } + + setProgress(progress, files.length()); + const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); + if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) { + QFile::remove(output); + return BuildZipResult(tr("Could not read and compress %1").arg(relative)); + } + progress++; + } + + zip.close(); + + if (zip.getZipError() != 0) { + QFile::remove(output); + return BuildZipResult(tr("A zip error occurred")); + } + + return BuildZipResult(); + }); + connect(&buildZipWatcher, &QFutureWatcher::finished, this, &FlamePackExportTask::finish); + buildZipWatcher.setFuture(buildZipFuture); +} + +void FlamePackExportTask::finish() +{ + if (buildZipFuture.isCanceled()) + emitAborted(); + else { + const BuildZipResult result = buildZipFuture.result(); + if (result.has_value()) + emitFailed(result.value()); + else + emitSucceeded(); + } +} + +QByteArray FlamePackExportTask::generateIndex() +{ + QJsonObject obj; + obj["manifestType"] = "minecraftModpack"; + obj["manifestVersion"] = 1; + obj["name"] = name; + obj["version"] = version; + obj["author"] = author; + obj["projectID"] = projectID.toInt(); + obj["overrides"] = "overrides"; + if (mcInstance) { + QJsonObject version; + auto profile = mcInstance->getPackProfile(); + // collect all supported components + const ComponentPtr minecraft = profile->getComponent("net.minecraft"); + const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader"); + const ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader"); + const ComponentPtr forge = profile->getComponent("net.minecraftforge"); + + // convert all available components to mrpack dependencies + if (minecraft != nullptr) + version["version"] = minecraft->m_version; + + QJsonObject loader; + if (quilt != nullptr) + loader["id"] = quilt->getName(); + else if (fabric != nullptr) + loader["id"] = fabric->getName(); + else if (forge != nullptr) + loader["id"] = forge->getName(); + loader["primary"] = true; + + version["modLoaders"] = QJsonArray({ loader }); + obj["minecraft"] = version; + } + + QJsonArray files; + QMapIterator iterator(resolvedFiles); + while (iterator.hasNext()) { + iterator.next(); + + const ResolvedFile& value = iterator.value(); + + QJsonObject file; + file["projectID"] = value.projectID.toInt(); + file["fileID"] = value.fileID.toInt(); + file["required"] = value.required; + files << file; + } + obj["files"] = files; + + return QJsonDocument(obj).toJson(QJsonDocument::Compact); +} diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h new file mode 100644 index 00000000..83927099 --- /dev/null +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2023 Trial97 + * + * 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 . + */ + +#pragma once + +#include +#include +#include "BaseInstance.h" +#include "MMCZip.h" +#include "minecraft/MinecraftInstance.h" +#include "tasks/Task.h" + +class FlamePackExportTask : public Task { + public: + FlamePackExportTask(const QString& name, + const QString& version, + const QVariant& projectID, + InstancePtr instance, + const QString& output, + MMCZip::FilterFunction filter); + + protected: + void executeTask() override; + bool abort() override; + + private: + struct ResolvedFile { + QVariant projectID, fileID; + bool required; + }; + + static const QStringList PREFIXES; + static const QStringList FILE_EXTENSIONS; + static const QString TEMPLATE; + + // inputs + const QString name, version, author; + const QVariant projectID; + const InstancePtr instance; + MinecraftInstance* mcInstance; + const QDir gameRoot; + const QString output; + const MMCZip::FilterFunction filter; + + typedef std::optional BuildZipResult; + + QFileInfoList files; + QMap resolvedFiles; + Task::Ptr task; + QFuture buildZipFuture; + QFutureWatcher buildZipWatcher; + QList mods; + + void collectFiles(); + void buildZip(); + void finish(); + + QByteArray generateIndex(); +}; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index e04011ca..0027d180 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -205,6 +205,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi auto exportInstanceMenu = new QMenu(this); exportInstanceMenu->addAction(ui->actionExportInstanceZip); exportInstanceMenu->addAction(ui->actionExportInstanceMrPack); + exportInstanceMenu->addAction(ui->actionExportInstanceFlamePack); ui->actionExportInstance->setMenu(exportInstanceMenu); } @@ -1416,6 +1417,14 @@ void MainWindow::on_actionExportInstanceMrPack_triggered() } } +void MainWindow::on_actionExportInstanceFlamePack_triggered() +{ + if (m_selectedInstance) { + ExportMrPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME); + dlg.exec(); + } +} + void MainWindow::on_actionRenameInstance_triggered() { if (m_selectedInstance) diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 3bb20c4a..5f74b501 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -157,6 +157,7 @@ private slots: inline void on_actionExportInstance_triggered() { on_actionExportInstanceZip_triggered(); } void on_actionExportInstanceZip_triggered(); void on_actionExportInstanceMrPack_triggered(); + void on_actionExportInstanceFlamePack_triggered(); void on_actionRenameInstance_triggered(); diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index f67fb185..f7e93f48 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -479,6 +479,14 @@ Modrinth (mrpack)
    + + + + + + Curseforge (zip) + + diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 561b92e4..16ef526a 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -18,6 +18,8 @@ #include "ExportMrPackDialog.h" #include "minecraft/mod/ModFolderModel.h" +#include "modplatform/ModIndex.h" +#include "modplatform/flame/FlamePackExportTask.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" #include "ui_ExportMrPackDialog.h" @@ -32,12 +34,15 @@ #include "MMCZip.h" #include "modplatform/modrinth/ModrinthPackExportTask.h" -ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) - : QDialog(parent), instance(instance), ui(new Ui::ExportMrPackDialog) +ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, ModPlatform::ResourceProvider provider) + : QDialog(parent), instance(instance), ui(new Ui::ExportMrPackDialog), m_provider(provider) { ui->setupUi(this); ui->name->setText(instance->name()); - ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) + ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); + else + ui->summaryLabel->setText("ProjectID"); // ensure a valid pack is generated // the name and version fields mustn't be empty @@ -97,20 +102,25 @@ void ExportMrPackDialog::done(int result) if (output.isEmpty()) return; - - ModrinthPackExportTask task(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, - [this](const QString& path) { return proxy->blockedPaths().covers(path); }); - - connect(&task, &Task::failed, + Task* task; + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) + task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, + [this](const QString& path) { return proxy->blockedPaths().covers(path); }); + else + task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, + [this](const QString& path) { return proxy->blockedPaths().covers(path); }); + + connect(task, &Task::failed, [this](const QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); - connect(&task, &Task::aborted, [this] { + connect(task, &Task::aborted, [this] { CustomMessageBox::selectable(this, tr("Task aborted"), tr("The task has been aborted by the user."), QMessageBox::Information) ->show(); }); + connect(task, &Task::finished, [task] { task->deleteLater(); }); ProgressDialog progress(this); progress.setSkipButton(true, tr("Abort")); - if (progress.execWithTask(&task) != QDialog::Accepted) + if (progress.execWithTask(task) != QDialog::Accepted) return; } diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportMrPackDialog.h index 1c70c4ae..858a31bf 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.h +++ b/launcher/ui/dialogs/ExportMrPackDialog.h @@ -22,6 +22,7 @@ #include "BaseInstance.h" #include "FastFileIconProvider.h" #include "FileIgnoreProxy.h" +#include "modplatform/ModIndex.h" namespace Ui { class ExportMrPackDialog; @@ -31,7 +32,9 @@ class ExportMrPackDialog : public QDialog { Q_OBJECT public: - explicit ExportMrPackDialog(InstancePtr instance, QWidget* parent = nullptr); + explicit ExportMrPackDialog(InstancePtr instance, + QWidget* parent = nullptr, + ModPlatform::ResourceProvider provider = ModPlatform::ResourceProvider::MODRINTH); ~ExportMrPackDialog(); void done(int result) override; @@ -42,4 +45,5 @@ class ExportMrPackDialog : public QDialog { Ui::ExportMrPackDialog* ui; FileIgnoreProxy* proxy; FastFileIconProvider icons; + const ModPlatform::ResourceProvider m_provider; }; -- cgit From 377f27b16fbd8adb21d4907101d195ef6f3a9e88 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 20:04:06 +0300 Subject: Updated slug for url Signed-off-by: Trial97 --- launcher/modplatform/helpers/ExportModsToStringTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp index c10560c1..e7be5ce1 100644 --- a/launcher/modplatform/helpers/ExportModsToStringTask.cpp +++ b/launcher/modplatform/helpers/ExportModsToStringTask.cpp @@ -97,7 +97,7 @@ QString ExportModsToStringTask(QList mods, QString lineTemplate) if (meta != nullptr) { url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" : "https://modrinth.com/mod/") + - meta->project_id.toString(); + meta->slug.remove(".pw.toml"); } auto ver = mod->version(); if (ver.isEmpty() && meta != nullptr) -- cgit From 049b02cee46358a3d1dd13769e2c6f4ba27bc55e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 21:06:01 +0300 Subject: finished up the curesforge export Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 28 +++++++++++----------- launcher/modplatform/flame/FlamePackExportTask.h | 10 ++------ launcher/ui/dialogs/ExportMrPackDialog.cpp | 20 +++++++++++----- launcher/ui/dialogs/ExportMrPackDialog.ui | 14 +++++++++-- 4 files changed, 42 insertions(+), 30 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 1ae13f72..4ac2c8ab 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -28,20 +28,21 @@ #include "MMCZip.h" #include "minecraft/PackProfile.h" #include "minecraft/mod/ModFolderModel.h" +#include "modplatform/ModIndex.h" #include "modplatform/helpers/ExportModsToStringTask.h" -const QStringList FlamePackExportTask::PREFIXES({ "mods/", "coremods/", "resourcepacks/", "texturepacks/", "shaderpacks/" }); -const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "litemod", "zip" }); const QString FlamePackExportTask::TEMPLATE = "
  • {name}({authors})
  • "; FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, + const QString& author, const QVariant& projectID, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter) : name(name) , version(version) + , author(author) , projectID(projectID) , instance(instance) , mcInstance(dynamic_cast(instance.get())) @@ -193,28 +194,27 @@ QByteArray FlamePackExportTask::generateIndex() QJsonObject loader; if (quilt != nullptr) - loader["id"] = quilt->getName(); + loader["id"] = "quilt-" + quilt->getVersion(); else if (fabric != nullptr) - loader["id"] = fabric->getName(); + loader["id"] = "fabric-" + fabric->getVersion(); else if (forge != nullptr) - loader["id"] = forge->getName(); + loader["id"] = "forge-" + forge->getVersion(); loader["primary"] = true; - version["modLoaders"] = QJsonArray({ loader }); obj["minecraft"] = version; } QJsonArray files; - QMapIterator iterator(resolvedFiles); - while (iterator.hasNext()) { - iterator.next(); - - const ResolvedFile& value = iterator.value(); + for (auto mod : mods) { + auto meta = mod->metadata(); + if (meta == nullptr || meta->provider != ModPlatform::ResourceProvider::FLAME) + continue; + resolvedFiles[gameRoot.relativeFilePath(mod->fileinfo().absoluteFilePath())] = {}; QJsonObject file; - file["projectID"] = value.projectID.toInt(); - file["fileID"] = value.fileID.toInt(); - file["required"] = value.required; + file["projectID"] = meta->project_id.toInt(); + file["fileID"] = meta->file_id.toInt(); + file["required"] = true; files << file; } obj["files"] = files; diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 83927099..c3cda926 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -29,6 +29,7 @@ class FlamePackExportTask : public Task { public: FlamePackExportTask(const QString& name, const QString& version, + const QString& author, const QVariant& projectID, InstancePtr instance, const QString& output, @@ -39,13 +40,6 @@ class FlamePackExportTask : public Task { bool abort() override; private: - struct ResolvedFile { - QVariant projectID, fileID; - bool required; - }; - - static const QStringList PREFIXES; - static const QStringList FILE_EXTENSIONS; static const QString TEMPLATE; // inputs @@ -60,7 +54,7 @@ class FlamePackExportTask : public Task { typedef std::optional BuildZipResult; QFileInfoList files; - QMap resolvedFiles; + QMap resolvedFiles; Task::Ptr task; QFuture buildZipFuture; QFutureWatcher buildZipWatcher; diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 16ef526a..aaa528aa 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -39,10 +39,13 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, Mo { ui->setupUi(this); ui->name->setText(instance->name()); - if (m_provider == ModPlatform::ResourceProvider::MODRINTH) + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); - else + ui->author->hide(); + ui->authorLabel->hide(); + } else { ui->summaryLabel->setText("ProjectID"); + } // ensure a valid pack is generated // the name and version fields mustn't be empty @@ -96,9 +99,14 @@ void ExportMrPackDialog::done(int result) { if (result == Accepted) { const QString filename = FS::RemoveInvalidFilenameChars(ui->name->text()); - const QString output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), - FS::PathCombine(QDir::homePath(), filename + ".mrpack"), - "Modrinth pack (*.mrpack *.zip)", nullptr); + QString output; + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) + output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), + FS::PathCombine(QDir::homePath(), filename + ".mrpack"), "Modrinth pack (*.mrpack *.zip)", + nullptr); + else + output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), + FS::PathCombine(QDir::homePath(), filename + ".zip"), "Curseforge pack (*.zip)", nullptr); if (output.isEmpty()) return; @@ -107,7 +115,7 @@ void ExportMrPackDialog::done(int result) task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); else - task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, + task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); connect(task, &Task::failed, diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportMrPackDialog.ui index 9a789737..59ecb17c 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.ui +++ b/launcher/ui/dialogs/ExportMrPackDialog.ui @@ -24,7 +24,7 @@
    - + Summary @@ -41,7 +41,7 @@ - + Version @@ -57,6 +57,16 @@ + + + + Author + + + + + + -- cgit From 85495c794de2b7c9ae64bbf43156b3e4e6ecfed0 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 22 Jun 2023 21:12:02 +0300 Subject: changed map tipe Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- launcher/modplatform/flame/FlamePackExportTask.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 4ac2c8ab..6114f1b1 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -209,7 +209,7 @@ QByteArray FlamePackExportTask::generateIndex() auto meta = mod->metadata(); if (meta == nullptr || meta->provider != ModPlatform::ResourceProvider::FLAME) continue; - resolvedFiles[gameRoot.relativeFilePath(mod->fileinfo().absoluteFilePath())] = {}; + resolvedFiles[gameRoot.relativeFilePath(mod->fileinfo().absoluteFilePath())] = true; QJsonObject file; file["projectID"] = meta->project_id.toInt(); diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index c3cda926..370cd67e 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -54,7 +54,7 @@ class FlamePackExportTask : public Task { typedef std::optional BuildZipResult; QFileInfoList files; - QMap resolvedFiles; + QMap resolvedFiles; Task::Ptr task; QFuture buildZipFuture; QFutureWatcher buildZipWatcher; -- cgit From 03361e51efb20802c419e15228e8dc086c4d273b Mon Sep 17 00:00:00 2001 From: seth Date: Thu, 22 Jun 2023 15:58:53 -0400 Subject: chore: add 'suggest a feature' message in help Signed-off-by: seth --- launcher/ui/MainWindow.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index f67fb185..113dfc1e 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -577,7 +577,7 @@ .. - Report a &Bug... + Report a Bug or Suggest a Feature Open the bug tracker to report a bug with %1. -- cgit From a4521ac0bbd0472c0f8bbf184d1b2f5b54ed8e0b Mon Sep 17 00:00:00 2001 From: seth Date: Thu, 22 Jun 2023 16:15:03 -0400 Subject: chore: avoid confusion in file/url import dialog Signed-off-by: seth --- launcher/ui/pages/modplatform/ImportPage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/pages/modplatform/ImportPage.h b/launcher/ui/pages/modplatform/ImportPage.h index 8d13ac10..c2acb92d 100644 --- a/launcher/ui/pages/modplatform/ImportPage.h +++ b/launcher/ui/pages/modplatform/ImportPage.h @@ -57,7 +57,7 @@ public: virtual ~ImportPage(); virtual QString displayName() const override { - return tr("Import from zip"); + return tr("Import"); } virtual QIcon icon() const override { -- cgit From 763b3c323613473a1d9678e15f92a712884ab7c3 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 23 Jun 2023 10:38:26 +0300 Subject: Added Thumbs.db to excluded files in MrPackExport Signed-off-by: Trial97 --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 561b92e4..60ecefd5 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -53,7 +53,7 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) const QDir root(instance->gameRoot()); proxy = new FileIgnoreProxy(instance->gameRoot(), this); proxy->setSourceModel(model); - proxy->setFilterRegularExpression("^(?!\\.DS_Store).+$"); + proxy->setFilterRegularExpression("^(?!(\\.DS_Store)|([tT]humbs\\.db)).+$"); const QDir::Filters filter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); -- cgit From 67db141203864123f65d93723e7eed43328b8d97 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 23 Jun 2023 14:38:23 +0300 Subject: Renamed getResults to resultsReady Signed-off-by: Trial97 --- launcher/modplatform/EnsureMetadataTask.cpp | 4 ++-- launcher/modplatform/atlauncher/ATLPackInstallTask.cpp | 2 +- launcher/modplatform/helpers/HashUtils.cpp | 2 +- launcher/modplatform/helpers/HashUtils.h | 2 +- launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp index a04a2534..93b5ce76 100644 --- a/launcher/modplatform/EnsureMetadataTask.cpp +++ b/launcher/modplatform/EnsureMetadataTask.cpp @@ -25,7 +25,7 @@ EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::Resource auto hash_task = createNewHash(mod); if (!hash_task) return; - connect(hash_task.get(), &Hashing::Hasher::getResults, [this, mod](QString hash) { m_mods.insert(hash, mod); }); + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { m_mods.insert(hash, mod); }); connect(hash_task.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); }); hash_task->start(); } @@ -38,7 +38,7 @@ EnsureMetadataTask::EnsureMetadataTask(QList& mods, QDir dir, ModPlatform: auto hash_task = createNewHash(mod); if (!hash_task) continue; - connect(hash_task.get(), &Hashing::Hasher::getResults, [this, mod](QString hash) { m_mods.insert(hash, mod); }); + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { m_mods.insert(hash, mod); }); connect(hash_task.get(), &Task::failed, [this, mod] { emitFail(mod, "", RemoveFromList::No); }); m_hashing_task->addTask(hash_task); } diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp index 2522020d..22ea02da 100644 --- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp +++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp @@ -100,7 +100,7 @@ void PackInstallTask::onDownloadSucceeded() jobPtr.reset(); QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response.get(), &parse_error); + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { qWarning() << "Error while parsing JSON response from ATLauncher at " << parse_error.offset << " reason: " << parse_error.errorString(); diff --git a/launcher/modplatform/helpers/HashUtils.cpp b/launcher/modplatform/helpers/HashUtils.cpp index 6df1eaf9..7d188a2f 100644 --- a/launcher/modplatform/helpers/HashUtils.cpp +++ b/launcher/modplatform/helpers/HashUtils.cpp @@ -71,7 +71,7 @@ void ModrinthHasher::executeTask() emitFailed("Empty hash!"); } else { emitSucceeded(); - emit getResults(m_hash); + emit resultsReady(m_hash); } } diff --git a/launcher/modplatform/helpers/HashUtils.h b/launcher/modplatform/helpers/HashUtils.h index a541ae8f..73a2435a 100644 --- a/launcher/modplatform/helpers/HashUtils.h +++ b/launcher/modplatform/helpers/HashUtils.h @@ -23,7 +23,7 @@ class Hasher : public Task { QString getPath() const { return m_path; }; signals: - void getResults(QString hash); + void resultsReady(QString hash); protected: QString m_hash; diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index 36002bad..a7c22832 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -53,7 +53,7 @@ void ModrinthCheckUpdate::executeTask() // (though it will rarely happen, if at all) if (mod->metadata()->hash_format != best_hash_type) { auto hash_task = Hashing::createModrinthHasher(mod->fileinfo().absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::getResults, [&hashes, &mappings, mod](QString hash) { + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [&hashes, &mappings, mod](QString hash) { hashes.append(hash); mappings.insert(hash, mod); }); -- cgit From 0a566318315c4e1566cb4ef7c99321a025e998a2 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 23 Jun 2023 19:35:41 +0300 Subject: Added curseforge search Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 130 ++++++++++++++++++--- launcher/modplatform/flame/FlamePackExportTask.h | 13 ++- launcher/ui/dialogs/ExportMrPackDialog.cpp | 5 +- 3 files changed, 133 insertions(+), 15 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 6114f1b1..7130b502 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -24,12 +24,15 @@ #include #include #include +#include #include "Json.h" #include "MMCZip.h" #include "minecraft/PackProfile.h" +#include "minecraft/mod/ModDetails.h" #include "minecraft/mod/ModFolderModel.h" #include "modplatform/ModIndex.h" #include "modplatform/helpers/ExportModsToStringTask.h" +#include "modplatform/helpers/HashUtils.h" const QString FlamePackExportTask::TEMPLATE = "
  • {name}({authors})
  • "; @@ -88,13 +91,118 @@ void FlamePackExportTask::collectFiles() return; } + pendingHashes.clear(); resolvedFiles.clear(); - mcInstance->loaderModList()->update(); - connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, [this]() { - mods = mcInstance->loaderModList()->allMods(); + if (mcInstance) { + mcInstance->loaderModList()->update(); + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, [this]() { + mods = mcInstance->loaderModList()->allMods(); + collectHashes(); + }); + } else + collectHashes(); +} + +void FlamePackExportTask::collectHashes() +{ + ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); + for (auto* mod : mods) { + if (!mod || !mod->valid() || mod->type() == ResourceType::FOLDER) + continue; + if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { + resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), + { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled() }); + continue; + } + + auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); + connect(hash_task.get(), &Task::succeeded, [this, hash_task, mod] { pendingHashes.insert(hash_task->getResult(), mod); }); + connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + connect(hash_task.get(), &Task::finished, [hash_task] { hash_task->deleteLater(); }); + hashing_task->addTask(hash_task); + } + connect(hashing_task.get(), &Task::succeeded, this, &FlamePackExportTask::makeApiRequest); + connect(hashing_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + connect(hashing_task.get(), &Task::finished, [hashing_task] { hashing_task->deleteLater(); }); + hashing_task->start(); +} + +void FlamePackExportTask::makeApiRequest() +{ + setAbortable(true); + if (pendingHashes.isEmpty()) { + buildZip(); + return; + } + + auto response = std::make_shared(); + + QList fingerprints; + for (auto& murmur : pendingHashes.keys()) { + fingerprints.push_back(murmur.toUInt()); + } + + auto task = api.matchFingerprints(fingerprints, response.get()); + + connect(task.get(), &Task::succeeded, this, [this, response] { + QJsonParseError parse_error{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from Modrinth::CurrentVersions at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response; + + failed(parse_error.errorString()); + return; + } + + try { + auto doc_obj = Json::requireObject(doc); + auto data_obj = Json::requireObject(doc_obj, "data"); + auto data_arr = Json::requireArray(data_obj, "exactMatches"); + + if (data_arr.isEmpty()) { + qWarning() << "No matches found for fingerprint search!"; + + return; + } + + for (auto match : data_arr) { + auto match_obj = Json::ensureObject(match, {}); + auto file_obj = Json::ensureObject(match_obj, "file", {}); + + if (match_obj.isEmpty() || file_obj.isEmpty()) { + qWarning() << "Fingerprint match is empty!"; + + return; + } + + auto fingerprint = QString::number(Json::ensureVariant(file_obj, "fileFingerprint").toUInt()); + auto mod = pendingHashes.find(fingerprint); + if (mod == pendingHashes.end()) { + qWarning() << "Invalid fingerprint from the API response."; + continue; + } + + setStatus(tr("Parsing API response from CurseForge for '%1'...").arg((*mod)->name())); + + resolvedFiles.insert( + mod.value()->fileinfo().absoluteFilePath(), + { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "modId"), mod.value()->enabled() }); + } + + } catch (Json::JsonException& e) { + qDebug() << e.cause(); + qDebug() << doc; + } + pendingHashes.clear(); buildZip(); }); + + connect(task.get(), &NetJob::finished, [task]() { task->deleteLater(); }); + connect(task.get(), &NetJob::failed, this, &FlamePackExportTask::emitFailed); + task->start(); } void FlamePackExportTask::buildZip() @@ -177,7 +285,8 @@ QByteArray FlamePackExportTask::generateIndex() obj["name"] = name; obj["version"] = version; obj["author"] = author; - obj["projectID"] = projectID.toInt(); + if (projectID.toInt() != 0) + obj["projectID"] = projectID.toInt(); obj["overrides"] = "overrides"; if (mcInstance) { QJsonObject version; @@ -205,16 +314,11 @@ QByteArray FlamePackExportTask::generateIndex() } QJsonArray files; - for (auto mod : mods) { - auto meta = mod->metadata(); - if (meta == nullptr || meta->provider != ModPlatform::ResourceProvider::FLAME) - continue; - resolvedFiles[gameRoot.relativeFilePath(mod->fileinfo().absoluteFilePath())] = true; - + for (auto mod : resolvedFiles) { QJsonObject file; - file["projectID"] = meta->project_id.toInt(); - file["fileID"] = meta->file_id.toInt(); - file["required"] = true; + file["projectID"] = mod.addonId; + file["fileID"] = mod.version; + file["required"] = mod.enabled; files << file; } obj["files"] = files; diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 370cd67e..58f66cc5 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -23,6 +23,7 @@ #include "BaseInstance.h" #include "MMCZip.h" #include "minecraft/MinecraftInstance.h" +#include "modplatform/flame/FlameAPI.h" #include "tasks/Task.h" class FlamePackExportTask : public Task { @@ -52,15 +53,25 @@ class FlamePackExportTask : public Task { const MMCZip::FilterFunction filter; typedef std::optional BuildZipResult; + struct ResolvedFile { + int addonId; + int version; + bool enabled; + }; + + FlameAPI api; QFileInfoList files; - QMap resolvedFiles; + QMap pendingHashes; + QMap resolvedFiles; Task::Ptr task; QFuture buildZipFuture; QFutureWatcher buildZipWatcher; QList mods; void collectFiles(); + void collectHashes(); + void makeApiRequest(); void buildZip(); void finish(); diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index aaa528aa..3711bb8f 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -44,6 +44,8 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, Mo ui->author->hide(); ui->authorLabel->hide(); } else { + setWindowTitle("Export CurseForge Pack"); + ui->version->setText(""); ui->summaryLabel->setText("ProjectID"); } @@ -137,6 +139,7 @@ void ExportMrPackDialog::done(int result) void ExportMrPackDialog::validate() { - const bool invalid = ui->name->text().isEmpty() || ui->version->text().isEmpty(); + const bool invalid = + ui->name->text().isEmpty() || ((m_provider == ModPlatform::ResourceProvider::MODRINTH) && ui->version->text().isEmpty()); ui->buttonBox->button(QDialogButtonBox::Ok)->setDisabled(invalid); } -- cgit From 222a10891c103d1357448d6aaff5da8d94e576af Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 23 Jun 2023 19:41:55 +0300 Subject: Fixed merge Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 7130b502..28c62f53 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -143,7 +143,7 @@ void FlamePackExportTask::makeApiRequest() fingerprints.push_back(murmur.toUInt()); } - auto task = api.matchFingerprints(fingerprints, response.get()); + auto task = api.matchFingerprints(fingerprints, response); connect(task.get(), &Task::succeeded, this, [this, response] { QJsonParseError parse_error{}; -- cgit From 28de461067b0fec69ebcb9bdcd213d02244b39bb Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 23 Jun 2023 21:38:41 +0300 Subject: Fixed hashers Signed-off-by: Trial97 --- launcher/modplatform/helpers/HashUtils.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'launcher') diff --git a/launcher/modplatform/helpers/HashUtils.cpp b/launcher/modplatform/helpers/HashUtils.cpp index 7d188a2f..6ff1d171 100644 --- a/launcher/modplatform/helpers/HashUtils.cpp +++ b/launcher/modplatform/helpers/HashUtils.cpp @@ -89,6 +89,7 @@ void FlameHasher::executeTask() emitFailed("Empty hash!"); } else { emitSucceeded(); + emit resultsReady(m_hash); } } @@ -120,6 +121,7 @@ void BlockedModHasher::executeTask() emitFailed("Empty hash!"); } else { emitSucceeded(); + emit resultsReady(m_hash); } } -- cgit From 823cd3862d15f8e9d47cdc5fc8662a20f774567a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 23 Jun 2023 22:41:01 +0300 Subject: Fixed hash checking Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 41 +++++++++++++--------- launcher/modplatform/flame/FlamePackExportTask.h | 5 ++- launcher/modplatform/helpers/HashUtils.cpp | 2 ++ 3 files changed, 29 insertions(+), 19 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 28c62f53..880d4324 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -28,11 +28,11 @@ #include "Json.h" #include "MMCZip.h" #include "minecraft/PackProfile.h" -#include "minecraft/mod/ModDetails.h" #include "minecraft/mod/ModFolderModel.h" #include "modplatform/ModIndex.h" #include "modplatform/helpers/ExportModsToStringTask.h" #include "modplatform/helpers/HashUtils.h" +#include "tasks/Task.h" const QString FlamePackExportTask::TEMPLATE = "
  • {name}({authors})
  • "; @@ -94,43 +94,51 @@ void FlamePackExportTask::collectFiles() pendingHashes.clear(); resolvedFiles.clear(); - if (mcInstance) { + if (mcInstance != nullptr) { + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, &FlamePackExportTask::collectHashes); mcInstance->loaderModList()->update(); - connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, [this]() { - mods = mcInstance->loaderModList()->allMods(); - collectHashes(); - }); } else collectHashes(); } void FlamePackExportTask::collectHashes() { + setAbortable(true); + setStatus(tr("Find file hashes...")); + auto mods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); + task.reset(hashing_task); + setProgress(0, mods.count()); for (auto* mod : mods) { - if (!mod || !mod->valid() || mod->type() == ResourceType::FOLDER) + if (!mod || mod->type() == ResourceType::FOLDER) { + setProgress(m_progress + 1, mods.count()); continue; + } if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled() }); + setProgress(m_progress + 1, mods.count()); continue; } auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); - connect(hash_task.get(), &Task::succeeded, [this, hash_task, mod] { pendingHashes.insert(hash_task->getResult(), mod); }); + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, mods](QString hash) { + if (m_state == Task::State::Running) { + setProgress(m_progress + 1, mods.count()); + pendingHashes.insert(hash, mod); + } + }); connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); - connect(hash_task.get(), &Task::finished, [hash_task] { hash_task->deleteLater(); }); hashing_task->addTask(hash_task); } connect(hashing_task.get(), &Task::succeeded, this, &FlamePackExportTask::makeApiRequest); connect(hashing_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); - connect(hashing_task.get(), &Task::finished, [hashing_task] { hashing_task->deleteLater(); }); hashing_task->start(); } void FlamePackExportTask::makeApiRequest() { - setAbortable(true); + setStatus(tr("Find versions for hashes...")); if (pendingHashes.isEmpty()) { buildZip(); return; @@ -143,7 +151,7 @@ void FlamePackExportTask::makeApiRequest() fingerprints.push_back(murmur.toUInt()); } - auto task = api.matchFingerprints(fingerprints, response); + task.reset(api.matchFingerprints(fingerprints, response)); connect(task.get(), &Task::succeeded, this, [this, response] { QJsonParseError parse_error{}; @@ -167,8 +175,9 @@ void FlamePackExportTask::makeApiRequest() return; } - + size_t progress = 0; for (auto match : data_arr) { + setProgress(progress++, data_arr.count()); auto match_obj = Json::ensureObject(match, {}); auto file_obj = Json::ensureObject(match_obj, "file", {}); @@ -200,7 +209,6 @@ void FlamePackExportTask::makeApiRequest() buildZip(); }); - connect(task.get(), &NetJob::finished, [task]() { task->deleteLater(); }); connect(task.get(), &NetJob::failed, this, &FlamePackExportTask::emitFailed); task->start(); } @@ -231,7 +239,7 @@ void FlamePackExportTask::buildZip() QFile::remove(output); return BuildZipResult(tr("Could not create index")); } - QString content = ExportToString::ExportModsToStringTask(mods, TEMPLATE); + QString content = ExportToString::ExportModsToStringTask(mcInstance->loaderModList()->allMods(), TEMPLATE); content = "
      " + content + "
    "; modlist.write(content.toUtf8()); @@ -244,7 +252,8 @@ void FlamePackExportTask::buildZip() setProgress(progress, files.length()); const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); - if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) { + if (!resolvedFiles.contains(file.absoluteFilePath()) && + !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) { QFile::remove(output); return BuildZipResult(tr("Could not read and compress %1").arg(relative)); } diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 58f66cc5..f0069678 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -62,12 +62,11 @@ class FlamePackExportTask : public Task { FlameAPI api; QFileInfoList files; - QMap pendingHashes; - QMap resolvedFiles; + QMap pendingHashes{}; + QMap resolvedFiles{}; Task::Ptr task; QFuture buildZipFuture; QFutureWatcher buildZipWatcher; - QList mods; void collectFiles(); void collectHashes(); diff --git a/launcher/modplatform/helpers/HashUtils.cpp b/launcher/modplatform/helpers/HashUtils.cpp index 7d188a2f..6ff1d171 100644 --- a/launcher/modplatform/helpers/HashUtils.cpp +++ b/launcher/modplatform/helpers/HashUtils.cpp @@ -89,6 +89,7 @@ void FlameHasher::executeTask() emitFailed("Empty hash!"); } else { emitSucceeded(); + emit resultsReady(m_hash); } } @@ -120,6 +121,7 @@ void BlockedModHasher::executeTask() emitFailed("Empty hash!"); } else { emitSucceeded(); + emit resultsReady(m_hash); } } -- cgit From 750209b8bbeaf75b93a6ae6e55d9192c38fd6f7d Mon Sep 17 00:00:00 2001 From: leo78913 Date: Fri, 23 Jun 2023 16:55:51 -0300 Subject: fix: fix crash when hiding columns on resource packs page Signed-off-by: leo78913 --- launcher/minecraft/mod/ResourcePackFolderModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp index 14a28b47..41455599 100644 --- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp +++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp @@ -53,7 +53,7 @@ ResourcePackFolderModel::ResourcePackFolderModel(const QString& dir, BaseInstanc m_column_names = QStringList({ "Enable", "Image", "Name", "Pack Format", "Last Modified" }); m_column_names_translated = QStringList({ tr("Enable"), tr("Image"), tr("Name"), tr("Pack Format"), tr("Last Modified") }); m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::NAME, SortType::PACK_FORMAT, SortType::DATE}; - m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents}; + m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Interactive, QHeaderView::Stretch, QHeaderView::ResizeToContents, QHeaderView::ResizeToContents }; } -- cgit From d74a23d5b217195e71cce47a07e2141b0eaa9fc3 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 23 Jun 2023 21:00:55 +0100 Subject: Update developers Signed-off-by: TheKodeToad --- launcher/ui/dialogs/AboutDialog.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/AboutDialog.cpp b/launcher/ui/dialogs/AboutDialog.cpp index 76e3d8ed..88739463 100644 --- a/launcher/ui/dialogs/AboutDialog.cpp +++ b/launcher/ui/dialogs/AboutDialog.cpp @@ -71,13 +71,18 @@ QString getCreditsHtml() //: %1 is the name of the launcher, determined at build time, e.g. "Prism Launcher Developers" stream << "

    " << QObject::tr("%1 Developers", "About Credits").arg(BuildConfig.LAUNCHER_DISPLAYNAME) << "

    \n"; stream << QString("

    Sefa Eyeoglu (Scrumplex) %1

    \n") .arg(getWebsite("https://scrumplex.net")); - stream << QString("

    dada513 %1

    \n") .arg(getGitHub("dada513")); + stream << QString("

    d-513 %1

    \n") .arg(getGitHub("d-513")); stream << QString("

    txtsd %1

    \n") .arg(getWebsite("https://ihavea.quest")); stream << QString("

    timoreo %1

    \n") .arg(getGitHub("timoreo22")); stream << QString("

    Ezekiel Smith (ZekeSmith) %1

    \n") .arg(getGitHub("ZekeSmith")); stream << QString("

    cozyGalvinism %1

    \n") .arg(getGitHub("cozyGalvinism")); - stream << QString("

    DioEgizio %1

    \n") .arg(getGitHub("DioEgizio")); - stream << QString("

    flowln %1

    \n") .arg(getGitHub("flowln")); + stream << QString("

    DioEgizio %1

    \n") .arg(getGitHub("DioEgizio")); + stream << QString("

    flowln %1

    \n") .arg(getGitHub("flowln")); + stream << QString("

    ViRb3 %1

    \n") .arg(getGitHub("ViRb3")); + stream << QString("

    Rachel Powers (Ryex) %1

    \n") .arg(getGitHub("Ryex")); + stream << QString("

    TayouVR %1

    \n") .arg(getGitHub("TayouVR")); + stream << QString("

    TheKodeToad %1

    \n") .arg(getGitHub("TheKodeToad")); + stream << QString("

    getchoo %1

    \n") .arg(getGitHub("getchoo")); stream << "
    \n"; // TODO: possibly retrieve from git history at build time? -- cgit From cf94adb363c1ae791ebd6f0149899f63c78bfb1b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 01:05:49 +0300 Subject: Added some warnings Signed-off-by: Trial97 --- launcher/minecraft/mod/Mod.cpp | 7 ++ launcher/minecraft/mod/Mod.h | 1 + launcher/modplatform/ModIndex.cpp | 9 +- launcher/modplatform/ModIndex.h | 1 + launcher/modplatform/flame/FlamePackExportTask.cpp | 124 ++++++++++++++++++--- launcher/modplatform/flame/FlamePackExportTask.h | 7 ++ .../modplatform/helpers/ExportModsToStringTask.cpp | 22 +--- launcher/ui/MainWindow.cpp | 13 ++- launcher/ui/dialogs/ExportMrPackDialog.cpp | 4 +- launcher/ui/dialogs/ExportMrPackDialog.ui | 7 ++ 10 files changed, 158 insertions(+), 37 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index e613ddeb..e93ff8bc 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -166,6 +166,13 @@ auto Mod::homeurl() const -> QString return details().homeurl; } +auto Mod::metaurl() const -> QString +{ + if (metadata() == nullptr) + return homeurl(); + return ModPlatform::getMetaURL(metadata()->provider, metadata()->slug); +} + auto Mod::description() const -> QString { return details().description; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index d4e419f4..d6272f4d 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -70,6 +70,7 @@ public: auto provider() const -> std::optional; auto licenses() const -> const QList&; auto issueTracker() const -> QString; + auto metaurl() const -> QString; /** Get the intneral path to the mod's icon file*/ QString iconPath() const { return m_local_details.icon_file; }; diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 6a507caf..c68333c5 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -70,11 +70,18 @@ auto ProviderCapabilities::hash(ResourceProvider p, QIODevice* device, QString t } QCryptographicHash hash(algo); - if(!hash.addData(device)) + if (!hash.addData(device)) qCritical() << "Failed to read JAR to create hash!"; Q_ASSERT(hash.result().length() == hash.hashLength(algo)); return { hash.result().toHex() }; } +QString getMetaURL(ResourceProvider provider, QString slug) +{ + return ((provider == ModPlatform::ResourceProvider::FLAME) ? "https://www.curseforge.com/minecraft/mc-mods/" + : "https://modrinth.com/mod/") + + slug.remove(".pw.toml"); +} + } // namespace ModPlatform diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 82da2ab2..7d8199b3 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -118,6 +118,7 @@ struct IndexedPack { return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); } }; +QString getMetaURL(ResourceProvider provider, QString slug); } // namespace ModPlatform diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 880d4324..2f1201e1 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -24,13 +24,14 @@ #include #include #include +#include #include #include "Json.h" #include "MMCZip.h" #include "minecraft/PackProfile.h" #include "minecraft/mod/ModFolderModel.h" #include "modplatform/ModIndex.h" -#include "modplatform/helpers/ExportModsToStringTask.h" +#include "modplatform/flame/FlameModIndex.h" #include "modplatform/helpers/HashUtils.h" #include "tasks/Task.h" @@ -40,6 +41,7 @@ FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, const QString& author, const QVariant& projectID, + const bool generateModList, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter) @@ -52,6 +54,7 @@ FlamePackExportTask::FlamePackExportTask(const QString& name, , gameRoot(instance->gameRoot()) , output(output) , filter(filter) + , generateModList(generateModList) {} void FlamePackExportTask::executeTask() @@ -116,7 +119,8 @@ void FlamePackExportTask::collectHashes() } if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), - { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled() }); + { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), + mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") }); setProgress(m_progress + 1, mods.count()); continue; } @@ -195,10 +199,10 @@ void FlamePackExportTask::makeApiRequest() } setStatus(tr("Parsing API response from CurseForge for '%1'...").arg((*mod)->name())); - - resolvedFiles.insert( - mod.value()->fileinfo().absoluteFilePath(), - { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "modId"), mod.value()->enabled() }); + if (Json::ensureBoolean(file_obj, "isAvailable", false)) + resolvedFiles.insert( + mod.value()->fileinfo().absoluteFilePath(), + { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), mod.value()->enabled() }); } } catch (Json::JsonException& e) { @@ -206,13 +210,94 @@ void FlamePackExportTask::makeApiRequest() qDebug() << doc; } pendingHashes.clear(); - buildZip(); }); - + connect(task.get(), &Task::finished, this, &FlamePackExportTask::getProjectsInfo); connect(task.get(), &NetJob::failed, this, &FlamePackExportTask::emitFailed); task->start(); } +void FlamePackExportTask::getProjectsInfo() +{ + if (!generateModList) { + buildZip(); + return; + } + setStatus(tr("Find project info from curseforge...")); + QList addonIds; + for (auto resolved : resolvedFiles) { + if (resolved.slug.isEmpty()) { + addonIds << QString::number(resolved.addonId); + } + } + + auto response = std::make_shared(); + Task::Ptr proj_task; + + if (addonIds.isEmpty()) { + buildZip(); + return; + } else if (addonIds.size() == 1) { + proj_task = api.getProject(*addonIds.begin(), response); + } else { + proj_task = api.getProjects(addonIds, response); + } + + connect(proj_task.get(), &Task::succeeded, this, [this, response, addonIds] { + QJsonParseError parse_error{}; + auto doc = QJsonDocument::fromJson(*response, &parse_error); + if (parse_error.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from Modrinth projects task at " << parse_error.offset + << " reason: " << parse_error.errorString(); + qWarning() << *response; + return; + } + + try { + QJsonArray entries; + if (addonIds.size() == 1) + entries = { Json::requireObject(Json::requireObject(doc), "data") }; + else + entries = Json::requireArray(Json::requireObject(doc), "data"); + + size_t progress = 0; + for (auto entry : entries) { + setProgress(progress++, entries.count()); + auto entry_obj = Json::requireObject(entry); + + try { + setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(Json::requireString(entry_obj, "name"))); + + ModPlatform::IndexedPack pack; + FlameMod::loadIndexedPack(pack, entry_obj); + for (auto key : resolvedFiles.keys()) { + auto val = resolvedFiles.value(key); + if (val.addonId == pack.addonId) { + val.name = pack.name; + val.slug = pack.slug; + QStringList authors; + for (auto author : pack.authors) + authors << author.name; + + val.authors = authors.join(", "); + resolvedFiles[key] = val; + } + } + + } catch (Json::JsonException& e) { + qDebug() << e.cause(); + qDebug() << entries; + } + } + } catch (Json::JsonException& e) { + qDebug() << e.cause(); + qDebug() << doc; + } + buildZip(); + }); + task.reset(proj_task); + task->start(); +} + void FlamePackExportTask::buildZip() { setStatus(tr("Adding files...")); @@ -234,14 +319,23 @@ void FlamePackExportTask::buildZip() } indexFile.write(generateIndex()); - QuaZipFile modlist(&zip); - if (!modlist.open(QIODevice::WriteOnly, QuaZipNewInfo("modlist.html"))) { - QFile::remove(output); - return BuildZipResult(tr("Could not create index")); + if (generateModList) { + QuaZipFile modlist(&zip); + if (!modlist.open(QIODevice::WriteOnly, QuaZipNewInfo("modlist.html"))) { + QFile::remove(output); + return BuildZipResult(tr("Could not create index")); + } + QString content = ""; + for (auto mod : resolvedFiles) { + content += QString(TEMPLATE) + .replace("{name}", mod.name) + .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)) + .replace("{authors}", mod.authors) + + "\n"; + } + content = "
      " + content + "
    "; + modlist.write(content.toUtf8()); } - QString content = ExportToString::ExportModsToStringTask(mcInstance->loaderModList()->allMods(), TEMPLATE); - content = "
      " + content + "
    "; - modlist.write(content.toUtf8()); size_t progress = 0; for (const QFileInfo& file : files) { diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index f0069678..7f27e0d0 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -32,6 +32,7 @@ class FlamePackExportTask : public Task { const QString& version, const QString& author, const QVariant& projectID, + const bool generateModList, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter); @@ -51,12 +52,17 @@ class FlamePackExportTask : public Task { const QDir gameRoot; const QString output; const MMCZip::FilterFunction filter; + const bool generateModList; typedef std::optional BuildZipResult; struct ResolvedFile { int addonId; int version; bool enabled; + + QString name; + QString slug; + QString authors; }; FlameAPI api; @@ -71,6 +77,7 @@ class FlamePackExportTask : public Task { void collectFiles(); void collectHashes(); void makeApiRequest(); + void getProjectsInfo(); void buildZip(); void finish(); diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp index e7be5ce1..03e1f4ba 100644 --- a/launcher/modplatform/helpers/ExportModsToStringTask.cpp +++ b/launcher/modplatform/helpers/ExportModsToStringTask.cpp @@ -19,6 +19,7 @@ #include "modplatform/ModIndex.h" namespace ExportToString { + QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData) { switch (format) { @@ -28,12 +29,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex auto meta = mod->metadata(); auto modName = mod->name(); if (extraData & Url) { - auto url = mod->homeurl(); - if (meta != nullptr) { - url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" - : "https://modrinth.com/mod/") + - meta->slug.remove(".pw.toml"); - } + auto url = mod->metaurl(); if (!url.isEmpty()) modName = QString("%2").arg(url, modName); } @@ -57,12 +53,7 @@ QString ExportModsToStringTask(QList mods, Formats format, OptionalData ex auto meta = mod->metadata(); auto modName = mod->name(); if (extraData & Url) { - auto url = mod->homeurl(); - if (meta != nullptr) { - url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" - : "https://modrinth.com/mod/") + - meta->slug.remove(".pw.toml"); - } + auto url = mod->metaurl(); if (!url.isEmpty()) modName = QString("[%1](%2)").arg(modName, url); } @@ -93,12 +84,7 @@ QString ExportModsToStringTask(QList mods, QString lineTemplate) auto meta = mod->metadata(); auto modName = mod->name(); - auto url = mod->homeurl(); - if (meta != nullptr) { - url = (meta->provider == ModPlatform::ResourceProvider::FLAME ? "https://www.curseforge.com/minecraft/mc-mods/" - : "https://modrinth.com/mod/") + - meta->slug.remove(".pw.toml"); - } + auto url = mod->metaurl(); auto ver = mod->version(); if (ver.isEmpty() && meta != nullptr) ver = meta->version().toString(); diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 0027d180..eb09efbc 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1420,8 +1420,17 @@ void MainWindow::on_actionExportInstanceMrPack_triggered() void MainWindow::on_actionExportInstanceFlamePack_triggered() { if (m_selectedInstance) { - ExportMrPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME); - dlg.exec(); + auto instance = dynamic_cast(m_selectedInstance.get()); + if (instance) { + if (instance->getPackProfile()->getComponent("org.quiltmc.quilt-loader")) { + QMessageBox msgBox; + msgBox.setText(tr("Quilt is not yet supported by curseforge.")); + msgBox.exec(); + return; + } + ExportMrPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME); + dlg.exec(); + } } } diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 3711bb8f..edd2148a 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -43,6 +43,7 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, Mo ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); ui->author->hide(); ui->authorLabel->hide(); + ui->gnerateModlist->hide(); } else { setWindowTitle("Export CurseForge Pack"); ui->version->setText(""); @@ -117,7 +118,8 @@ void ExportMrPackDialog::done(int result) task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); else - task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), instance, output, + task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), + ui->gnerateModlist->isChecked(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); connect(task, &Task::failed, diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportMrPackDialog.ui index 59ecb17c..1b137eb4 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.ui +++ b/launcher/ui/dialogs/ExportMrPackDialog.ui @@ -67,6 +67,13 @@ + + + + Generate modlist + + + -- cgit From 20ba6e5fb50177d5145459951a69edc7b3302e95 Mon Sep 17 00:00:00 2001 From: James Beddek Date: Sat, 24 Jun 2023 15:42:58 +1200 Subject: modrinth: use encoded url when exporting pack Ensures that necessary url components such as spaces are encoded. Prevents an error when submitting the resulting file to modrinth. See https://discord.com/channels/734077874708938864/1120070731242410024 Fixes: #1226 Signed-off-by: James Beddek --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index c607bb89..4cd88aa6 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -134,8 +134,8 @@ void ModrinthPackExportTask::collectHashes() QCryptographicHash sha1(QCryptographicHash::Algorithm::Sha1); sha1.addData(data); - ResolvedFile file{ sha1.result().toHex(), sha512.result().toHex(), url.toString(), openFile.size() }; - resolvedFiles[relative] = file; + ResolvedFile resolvedFile{ sha1.result().toHex(), sha512.result().toHex(), url.toEncoded(), openFile.size() }; + resolvedFiles[relative] = resolvedFile; // nice! we've managed to resolve based on local metadata! // no need to enqueue it -- cgit From 42bc04a0d2af26e97829e6b1afd87d550b9b44da Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sat, 24 Jun 2023 11:01:23 +0300 Subject: Update launcher/ui/MainWindow.cpp Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/ui/MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index eb09efbc..89c78539 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1424,7 +1424,7 @@ void MainWindow::on_actionExportInstanceFlamePack_triggered() if (instance) { if (instance->getPackProfile()->getComponent("org.quiltmc.quilt-loader")) { QMessageBox msgBox; - msgBox.setText(tr("Quilt is not yet supported by curseforge.")); + msgBox.setText(tr("Quilt is currently not supported by CurseForge modpacks.")); msgBox.exec(); return; } -- cgit From cd1e8dc8cc87acf905ab3140efc48ef482973c7e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 11:12:23 +0300 Subject: Removed modlist checkbox Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 36 +++++++++------------- launcher/modplatform/flame/FlamePackExportTask.h | 2 -- launcher/ui/dialogs/ExportMrPackDialog.cpp | 4 +-- launcher/ui/dialogs/ExportMrPackDialog.ui | 7 ----- 4 files changed, 15 insertions(+), 34 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 2f1201e1..927b2e46 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -41,7 +41,6 @@ FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, const QString& author, const QVariant& projectID, - const bool generateModList, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter) @@ -54,7 +53,6 @@ FlamePackExportTask::FlamePackExportTask(const QString& name, , gameRoot(instance->gameRoot()) , output(output) , filter(filter) - , generateModList(generateModList) {} void FlamePackExportTask::executeTask() @@ -218,10 +216,6 @@ void FlamePackExportTask::makeApiRequest() void FlamePackExportTask::getProjectsInfo() { - if (!generateModList) { - buildZip(); - return; - } setStatus(tr("Find project info from curseforge...")); QList addonIds; for (auto resolved : resolvedFiles) { @@ -319,23 +313,21 @@ void FlamePackExportTask::buildZip() } indexFile.write(generateIndex()); - if (generateModList) { - QuaZipFile modlist(&zip); - if (!modlist.open(QIODevice::WriteOnly, QuaZipNewInfo("modlist.html"))) { - QFile::remove(output); - return BuildZipResult(tr("Could not create index")); - } - QString content = ""; - for (auto mod : resolvedFiles) { - content += QString(TEMPLATE) - .replace("{name}", mod.name) - .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)) - .replace("{authors}", mod.authors) + - "\n"; - } - content = "
      " + content + "
    "; - modlist.write(content.toUtf8()); + QuaZipFile modlist(&zip); + if (!modlist.open(QIODevice::WriteOnly, QuaZipNewInfo("modlist.html"))) { + QFile::remove(output); + return BuildZipResult(tr("Could not create index")); + } + QString content = ""; + for (auto mod : resolvedFiles) { + content += QString(TEMPLATE) + .replace("{name}", mod.name) + .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)) + .replace("{authors}", mod.authors) + + "\n"; } + content = "
      " + content + "
    "; + modlist.write(content.toUtf8()); size_t progress = 0; for (const QFileInfo& file : files) { diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 7f27e0d0..9ec9a230 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -32,7 +32,6 @@ class FlamePackExportTask : public Task { const QString& version, const QString& author, const QVariant& projectID, - const bool generateModList, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter); @@ -52,7 +51,6 @@ class FlamePackExportTask : public Task { const QDir gameRoot; const QString output; const MMCZip::FilterFunction filter; - const bool generateModList; typedef std::optional BuildZipResult; struct ResolvedFile { diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 3c593d20..8a95997b 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -43,7 +43,6 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, Mo ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); ui->author->hide(); ui->authorLabel->hide(); - ui->gnerateModlist->hide(); } else { setWindowTitle("Export CurseForge Pack"); ui->version->setText(""); @@ -118,8 +117,7 @@ void ExportMrPackDialog::done(int result) task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); else - task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), - ui->gnerateModlist->isChecked(), instance, output, + task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); connect(task, &Task::failed, diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportMrPackDialog.ui index 1b137eb4..59ecb17c 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.ui +++ b/launcher/ui/dialogs/ExportMrPackDialog.ui @@ -67,13 +67,6 @@ - - - - Generate modlist - - - -- cgit From a325d814e242ee450141088513d9cd282d79141f Mon Sep 17 00:00:00 2001 From: Alexandru Ionut Tripon Date: Sat, 24 Jun 2023 11:13:08 +0300 Subject: Update launcher/modplatform/flame/FlamePackExportTask.cpp Co-authored-by: DioEgizio <83089242+DioEgizio@users.noreply.github.com> Signed-off-by: Alexandru Ionut Tripon --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 927b2e46..cd242491 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -35,7 +35,7 @@ #include "modplatform/helpers/HashUtils.h" #include "tasks/Task.h" -const QString FlamePackExportTask::TEMPLATE = "
  • {name}({authors})
  • "; +const QString FlamePackExportTask::TEMPLATE = "
  • {name} (by {authors})
  • "; FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, -- cgit From 8939096db659d1df5c75b938fc011a24af36e488 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 13:24:40 +0300 Subject: Fixed windows build Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 927b2e46..2920cb86 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -197,7 +197,7 @@ void FlamePackExportTask::makeApiRequest() } setStatus(tr("Parsing API response from CurseForge for '%1'...").arg((*mod)->name())); - if (Json::ensureBoolean(file_obj, "isAvailable", false)) + if (Json::ensureBoolean(file_obj, "isAvailable", false, "isAvailable")) resolvedFiles.insert( mod.value()->fileinfo().absoluteFilePath(), { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), mod.value()->enabled() }); -- cgit From 9804996db652eb719a0eb40c41157d0813372eb2 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 14:37:02 +0300 Subject: Added resource packs to export Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 36 ++++++++++++++++------ launcher/modplatform/flame/FlamePackExportTask.h | 7 ++++- 2 files changed, 32 insertions(+), 11 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 0d7abc9f..45fc2e63 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -109,25 +109,42 @@ void FlamePackExportTask::collectHashes() auto mods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); task.reset(hashing_task); - setProgress(0, mods.count()); + int totalProgres = mods.count(); + setProgress(0, totalProgres); for (auto* mod : mods) { if (!mod || mod->type() == ResourceType::FOLDER) { - setProgress(m_progress + 1, mods.count()); + setProgress(m_progress + 1, totalProgres); continue; } if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") }); - setProgress(m_progress + 1, mods.count()); + setProgress(m_progress + 1, totalProgres); continue; } auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, mods](QString hash) { + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, totalProgres](QString hash) { if (m_state == Task::State::Running) { - setProgress(m_progress + 1, mods.count()); - pendingHashes.insert(hash, mod); + setProgress(m_progress + 1, totalProgres); + pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled() }); + } + }); + connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + hashing_task->addTask(hash_task); + } + + for (const QFileInfo& file : files) { + const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); + if (!relative.endsWith(".zip") || !relative.startsWith("resourcepacks/")) + continue; + totalProgres++; + auto hash_task = Hashing::createFlameHasher(file.absoluteFilePath()); + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, relative, file, totalProgres](QString hash) { + if (m_state == Task::State::Running) { + setProgress(m_progress + 1, totalProgres); + pendingHashes.insert(hash, { relative, file.absoluteFilePath(), true }); } }); connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); @@ -196,11 +213,10 @@ void FlamePackExportTask::makeApiRequest() continue; } - setStatus(tr("Parsing API response from CurseForge for '%1'...").arg((*mod)->name())); + setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(mod->name)); if (Json::ensureBoolean(file_obj, "isAvailable", false, "isAvailable")) - resolvedFiles.insert( - mod.value()->fileinfo().absoluteFilePath(), - { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), mod.value()->enabled() }); + resolvedFiles.insert(mod->path, + { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), mod->enabled }); } } catch (Json::JsonException& e) { diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 9ec9a230..629493d8 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -62,11 +62,16 @@ class FlamePackExportTask : public Task { QString slug; QString authors; }; + struct HashInfo { + QString name; + QString path; + bool enabled; + }; FlameAPI api; QFileInfoList files; - QMap pendingHashes{}; + QMap pendingHashes{}; QMap resolvedFiles{}; Task::Ptr task; QFuture buildZipFuture; -- cgit From 30ef5475c75514c08a4d1b2c8e4c6ec5abba41ea Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 14:50:05 +0300 Subject: Made sure CurseForge string is corect Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- launcher/ui/MainWindow.ui | 2 +- launcher/ui/dialogs/ExportMrPackDialog.cpp | 2 +- launcher/ui/pages/global/LauncherPage.ui | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 45fc2e63..fb5bcc0b 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -232,7 +232,7 @@ void FlamePackExportTask::makeApiRequest() void FlamePackExportTask::getProjectsInfo() { - setStatus(tr("Find project info from curseforge...")); + setStatus(tr("Find project info from CurseForge...")); QList addonIds; for (auto resolved : resolvedFiles) { if (resolved.slug.isEmpty()) { diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index 1cfb59cd..190219b9 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -484,7 +484,7 @@
    - Curseforge (zip) + CurseForge (zip)
    diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 8a95997b..94987c7e 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -108,7 +108,7 @@ void ExportMrPackDialog::done(int result) nullptr); else output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), - FS::PathCombine(QDir::homePath(), filename + ".zip"), "Curseforge pack (*.zip)", nullptr); + FS::PathCombine(QDir::homePath(), filename + ".zip"), "CurseForge pack (*.zip)", nullptr); if (output.isEmpty()) return; diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index d9116bfc..26408f44 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -169,7 +169,7 @@ - Disable using metadata provided by mod providers (like Modrinth or Curseforge) for mods. + Disable using metadata provided by mod providers (like Modrinth or CurseForge) for mods. Disable using metadata for mods -- cgit From 59e1e5190310626109018d5aeed4782b347176ec Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 14:51:12 +0300 Subject: Removed unused files Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 3 - .../modplatform/helpers/ExportModsToStringTask.cpp | 100 --------------------- .../modplatform/helpers/ExportModsToStringTask.h | 33 ------- 3 files changed, 136 deletions(-) delete mode 100644 launcher/modplatform/helpers/ExportModsToStringTask.cpp delete mode 100644 launcher/modplatform/helpers/ExportModsToStringTask.h (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index df6c9012..8de616a6 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -487,9 +487,6 @@ set(API_SOURCES modplatform/helpers/HashUtils.cpp modplatform/helpers/OverrideUtils.h modplatform/helpers/OverrideUtils.cpp - - modplatform/helpers/ExportModsToStringTask.h - modplatform/helpers/ExportModsToStringTask.cpp ) set(FTB_SOURCES diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.cpp b/launcher/modplatform/helpers/ExportModsToStringTask.cpp deleted file mode 100644 index 03e1f4ba..00000000 --- a/launcher/modplatform/helpers/ExportModsToStringTask.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 - * - * 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 . - */ -#include "ExportModsToStringTask.h" -#include "modplatform/ModIndex.h" - -namespace ExportToString { - -QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData) -{ - switch (format) { - case HTML: { - QStringList lines; - for (auto mod : mods) { - auto meta = mod->metadata(); - auto modName = mod->name(); - if (extraData & Url) { - auto url = mod->metaurl(); - if (!url.isEmpty()) - modName = QString("%2").arg(url, modName); - } - auto line = modName; - if (extraData & Version) { - auto ver = mod->version(); - if (ver.isEmpty() && meta != nullptr) - ver = meta->version().toString(); - if (!ver.isEmpty()) - line += QString("[%1]").arg(ver); - } - if (extraData & Authors && !mod->authors().isEmpty()) - line += " by " + mod->authors().join(", "); - lines.append(QString("
      %1
    ").arg(line)); - } - return QString("\n\t%1\n").arg(lines.join("\n\t")); - } - case MARKDOWN: { - QStringList lines; - for (auto mod : mods) { - auto meta = mod->metadata(); - auto modName = mod->name(); - if (extraData & Url) { - auto url = mod->metaurl(); - if (!url.isEmpty()) - modName = QString("[%1](%2)").arg(modName, url); - } - auto line = modName; - if (extraData & Version) { - auto ver = mod->version(); - if (ver.isEmpty() && meta != nullptr) - ver = meta->version().toString(); - if (!ver.isEmpty()) - line += QString("[%1]").arg(ver); - } - if (extraData & Authors && !mod->authors().isEmpty()) - line += " by " + mod->authors().join(", "); - lines << line; - } - return lines.join("\n"); - } - default: { - return QString("unknown format:%1").arg(format); - } - } -} - -QString ExportModsToStringTask(QList mods, QString lineTemplate) -{ - QStringList lines; - for (auto mod : mods) { - auto meta = mod->metadata(); - auto modName = mod->name(); - - auto url = mod->metaurl(); - auto ver = mod->version(); - if (ver.isEmpty() && meta != nullptr) - ver = meta->version().toString(); - auto authors = mod->authors().join(", "); - lines << QString(lineTemplate) - .replace("{name}", modName) - .replace("{url}", url) - .replace("{version}", ver) - .replace("{authors}", authors); - } - return lines.join("\n"); -} -} // namespace ExportToString \ No newline at end of file diff --git a/launcher/modplatform/helpers/ExportModsToStringTask.h b/launcher/modplatform/helpers/ExportModsToStringTask.h deleted file mode 100644 index 756c69f7..00000000 --- a/launcher/modplatform/helpers/ExportModsToStringTask.h +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (c) 2023 Trial97 - * - * 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 . - */ -#pragma once -#include -#include -#include "minecraft/mod/Mod.h" - -namespace ExportToString { - -enum Formats { HTML, MARKDOWN }; -enum OptionalData { - Authors = 1 << 0, - Url = 1 << 1, - Version = 1 << 2, -}; -QString ExportModsToStringTask(QList mods, Formats format, OptionalData extraData); -QString ExportModsToStringTask(QList mods, QString lineTemplate); -} // namespace ExportToString -- cgit From 25579fbedcfac6b36c6b30ad2447d702b601e1d6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 14:54:39 +0300 Subject: Renamed ExportMrPackDialog to ExportPackDialog Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 6 +- launcher/ui/MainWindow.cpp | 6 +- launcher/ui/dialogs/ExportMrPackDialog.cpp | 145 ---------------------------- launcher/ui/dialogs/ExportMrPackDialog.h | 49 ---------- launcher/ui/dialogs/ExportMrPackDialog.ui | 146 ----------------------------- launcher/ui/dialogs/ExportPackDialog.cpp | 145 ++++++++++++++++++++++++++++ launcher/ui/dialogs/ExportPackDialog.h | 49 ++++++++++ launcher/ui/dialogs/ExportPackDialog.ui | 146 +++++++++++++++++++++++++++++ 8 files changed, 346 insertions(+), 346 deletions(-) delete mode 100644 launcher/ui/dialogs/ExportMrPackDialog.cpp delete mode 100644 launcher/ui/dialogs/ExportMrPackDialog.h delete mode 100644 launcher/ui/dialogs/ExportMrPackDialog.ui create mode 100644 launcher/ui/dialogs/ExportPackDialog.cpp create mode 100644 launcher/ui/dialogs/ExportPackDialog.h create mode 100644 launcher/ui/dialogs/ExportPackDialog.ui (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 8de616a6..0dc2b80a 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -908,8 +908,8 @@ SET(LAUNCHER_SOURCES ui/dialogs/EditAccountDialog.h ui/dialogs/ExportInstanceDialog.cpp ui/dialogs/ExportInstanceDialog.h - ui/dialogs/ExportMrPackDialog.cpp - ui/dialogs/ExportMrPackDialog.h + ui/dialogs/ExportPackDialog.cpp + ui/dialogs/ExportPackDialog.h ui/dialogs/IconPickerDialog.cpp ui/dialogs/IconPickerDialog.h ui/dialogs/ImportResourceDialog.cpp @@ -1056,7 +1056,7 @@ qt_wrap_ui(LAUNCHER_UI ui/dialogs/ProfileSelectDialog.ui ui/dialogs/SkinUploadDialog.ui ui/dialogs/ExportInstanceDialog.ui - ui/dialogs/ExportMrPackDialog.ui + ui/dialogs/ExportPackDialog.ui ui/dialogs/IconPickerDialog.ui ui/dialogs/ImportResourceDialog.ui ui/dialogs/MSALoginDialog.ui diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 89c78539..91809c7b 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -107,7 +107,7 @@ #include "ui/dialogs/CopyInstanceDialog.h" #include "ui/dialogs/EditAccountDialog.h" #include "ui/dialogs/ExportInstanceDialog.h" -#include "ui/dialogs/ExportMrPackDialog.h" +#include "ui/dialogs/ExportPackDialog.h" #include "ui/dialogs/ImportResourceDialog.h" #include "ui/themes/ITheme.h" #include "ui/themes/ThemeManager.h" @@ -1412,7 +1412,7 @@ void MainWindow::on_actionExportInstanceMrPack_triggered() { if (m_selectedInstance) { - ExportMrPackDialog dlg(m_selectedInstance, this); + ExportPackDialog dlg(m_selectedInstance, this); dlg.exec(); } } @@ -1428,7 +1428,7 @@ void MainWindow::on_actionExportInstanceFlamePack_triggered() msgBox.exec(); return; } - ExportMrPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME); + ExportPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME); dlg.exec(); } } diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp deleted file mode 100644 index 94987c7e..00000000 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (C) 2023 TheKodeToad - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "ExportMrPackDialog.h" -#include "minecraft/mod/ModFolderModel.h" -#include "modplatform/ModIndex.h" -#include "modplatform/flame/FlamePackExportTask.h" -#include "ui/dialogs/CustomMessageBox.h" -#include "ui/dialogs/ProgressDialog.h" -#include "ui_ExportMrPackDialog.h" - -#include -#include -#include -#include -#include -#include "FastFileIconProvider.h" -#include "FileSystem.h" -#include "MMCZip.h" -#include "modplatform/modrinth/ModrinthPackExportTask.h" - -ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent, ModPlatform::ResourceProvider provider) - : QDialog(parent), instance(instance), ui(new Ui::ExportMrPackDialog), m_provider(provider) -{ - ui->setupUi(this); - ui->name->setText(instance->name()); - if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { - ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); - ui->author->hide(); - ui->authorLabel->hide(); - } else { - setWindowTitle("Export CurseForge Pack"); - ui->version->setText(""); - ui->summaryLabel->setText("ProjectID"); - } - - // ensure a valid pack is generated - // the name and version fields mustn't be empty - connect(ui->name, &QLineEdit::textEdited, this, &ExportMrPackDialog::validate); - connect(ui->version, &QLineEdit::textEdited, this, &ExportMrPackDialog::validate); - // the instance name can technically be empty - validate(); - - QFileSystemModel* model = new QFileSystemModel(this); - model->setIconProvider(&icons); - - // use the game root - everything outside cannot be exported - const QDir root(instance->gameRoot()); - proxy = new FileIgnoreProxy(instance->gameRoot(), this); - proxy->setSourceModel(model); - proxy->setFilterRegularExpression("^(?!(\\.DS_Store)|([tT]humbs\\.db)).+$"); - - const QDir::Filters filter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); - - for (const QString& file : root.entryList(filter)) { - if (!(file == "mods" || file == "coremods" || file == "datapacks" || file == "config" || file == "options.txt" || - file == "servers.dat")) - proxy->blockedPaths().insert(file); - } - - MinecraftInstance* mcInstance = dynamic_cast(instance.get()); - if (mcInstance) { - const QDir index = mcInstance->loaderModList()->indexDir(); - if (index.exists()) - proxy->blockedPaths().insert(root.relativeFilePath(index.absolutePath())); - } - - ui->treeView->setModel(proxy); - ui->treeView->setRootIndex(proxy->mapFromSource(model->index(instance->gameRoot()))); - ui->treeView->sortByColumn(0, Qt::AscendingOrder); - - model->setFilter(filter); - model->setRootPath(instance->gameRoot()); - - QHeaderView* headerView = ui->treeView->header(); - headerView->setSectionResizeMode(QHeaderView::ResizeToContents); - headerView->setSectionResizeMode(0, QHeaderView::Stretch); -} - -ExportMrPackDialog::~ExportMrPackDialog() -{ - delete ui; -} - -void ExportMrPackDialog::done(int result) -{ - if (result == Accepted) { - const QString filename = FS::RemoveInvalidFilenameChars(ui->name->text()); - QString output; - if (m_provider == ModPlatform::ResourceProvider::MODRINTH) - output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), - FS::PathCombine(QDir::homePath(), filename + ".mrpack"), "Modrinth pack (*.mrpack *.zip)", - nullptr); - else - output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), - FS::PathCombine(QDir::homePath(), filename + ".zip"), "CurseForge pack (*.zip)", nullptr); - - if (output.isEmpty()) - return; - Task* task; - if (m_provider == ModPlatform::ResourceProvider::MODRINTH) - task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, - [this](const QString& path) { return proxy->blockedPaths().covers(path); }); - else - task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), instance, output, - [this](const QString& path) { return proxy->blockedPaths().covers(path); }); - - connect(task, &Task::failed, - [this](const QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); - connect(task, &Task::aborted, [this] { - CustomMessageBox::selectable(this, tr("Task aborted"), tr("The task has been aborted by the user."), QMessageBox::Information) - ->show(); - }); - connect(task, &Task::finished, [task] { task->deleteLater(); }); - - ProgressDialog progress(this); - progress.setSkipButton(true, tr("Abort")); - if (progress.execWithTask(task) != QDialog::Accepted) - return; - } - - QDialog::done(result); -} - -void ExportMrPackDialog::validate() -{ - const bool invalid = - ui->name->text().isEmpty() || ((m_provider == ModPlatform::ResourceProvider::MODRINTH) && ui->version->text().isEmpty()); - ui->buttonBox->button(QDialogButtonBox::Ok)->setDisabled(invalid); -} diff --git a/launcher/ui/dialogs/ExportMrPackDialog.h b/launcher/ui/dialogs/ExportMrPackDialog.h deleted file mode 100644 index 858a31bf..00000000 --- a/launcher/ui/dialogs/ExportMrPackDialog.h +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * Prism Launcher - Minecraft Launcher - * Copyright (C) 2023 TheKodeToad - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include -#include "BaseInstance.h" -#include "FastFileIconProvider.h" -#include "FileIgnoreProxy.h" -#include "modplatform/ModIndex.h" - -namespace Ui { -class ExportMrPackDialog; -} - -class ExportMrPackDialog : public QDialog { - Q_OBJECT - - public: - explicit ExportMrPackDialog(InstancePtr instance, - QWidget* parent = nullptr, - ModPlatform::ResourceProvider provider = ModPlatform::ResourceProvider::MODRINTH); - ~ExportMrPackDialog(); - - void done(int result) override; - void validate(); - - private: - const InstancePtr instance; - Ui::ExportMrPackDialog* ui; - FileIgnoreProxy* proxy; - FastFileIconProvider icons; - const ModPlatform::ResourceProvider m_provider; -}; diff --git a/launcher/ui/dialogs/ExportMrPackDialog.ui b/launcher/ui/dialogs/ExportMrPackDialog.ui deleted file mode 100644 index 59ecb17c..00000000 --- a/launcher/ui/dialogs/ExportMrPackDialog.ui +++ /dev/null @@ -1,146 +0,0 @@ - - - ExportMrPackDialog - - - - 0 - 0 - 650 - 413 - - - - Export Modrinth Pack - - - true - - - - - - Information - - - - - - Summary - - - - - - - - - - Name - - - - - - - Version - - - - - - - - - - 1.0.0 - - - - - - - Author - - - - - - - - - - - - - Files - - - - - - - true - - - QAbstractItemView::ExtendedSelection - - - true - - - false - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - name - version - summary - treeView - - - - - buttonBox - accepted() - ExportMrPackDialog - accept() - - - 324 - 390 - - - 324 - 206 - - - - - buttonBox - rejected() - ExportMrPackDialog - reject() - - - 324 - 390 - - - 324 - 206 - - - - - diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp new file mode 100644 index 00000000..8e921f89 --- /dev/null +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ExportPackDialog.h" +#include "minecraft/mod/ModFolderModel.h" +#include "modplatform/ModIndex.h" +#include "modplatform/flame/FlamePackExportTask.h" +#include "ui/dialogs/CustomMessageBox.h" +#include "ui/dialogs/ProgressDialog.h" +#include "ui_ExportMrPackDialog.h" + +#include +#include +#include +#include +#include +#include "FastFileIconProvider.h" +#include "FileSystem.h" +#include "MMCZip.h" +#include "modplatform/modrinth/ModrinthPackExportTask.h" + +ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPlatform::ResourceProvider provider) + : QDialog(parent), instance(instance), ui(new Ui::ExportPackDialog), m_provider(provider) +{ + ui->setupUi(this); + ui->name->setText(instance->name()); + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { + ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); + ui->author->hide(); + ui->authorLabel->hide(); + } else { + setWindowTitle("Export CurseForge Pack"); + ui->version->setText(""); + ui->summaryLabel->setText("ProjectID"); + } + + // ensure a valid pack is generated + // the name and version fields mustn't be empty + connect(ui->name, &QLineEdit::textEdited, this, &ExportPackDialog::validate); + connect(ui->version, &QLineEdit::textEdited, this, &ExportPackDialog::validate); + // the instance name can technically be empty + validate(); + + QFileSystemModel* model = new QFileSystemModel(this); + model->setIconProvider(&icons); + + // use the game root - everything outside cannot be exported + const QDir root(instance->gameRoot()); + proxy = new FileIgnoreProxy(instance->gameRoot(), this); + proxy->setSourceModel(model); + proxy->setFilterRegularExpression("^(?!(\\.DS_Store)|([tT]humbs\\.db)).+$"); + + const QDir::Filters filter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); + + for (const QString& file : root.entryList(filter)) { + if (!(file == "mods" || file == "coremods" || file == "datapacks" || file == "config" || file == "options.txt" || + file == "servers.dat")) + proxy->blockedPaths().insert(file); + } + + MinecraftInstance* mcInstance = dynamic_cast(instance.get()); + if (mcInstance) { + const QDir index = mcInstance->loaderModList()->indexDir(); + if (index.exists()) + proxy->blockedPaths().insert(root.relativeFilePath(index.absolutePath())); + } + + ui->treeView->setModel(proxy); + ui->treeView->setRootIndex(proxy->mapFromSource(model->index(instance->gameRoot()))); + ui->treeView->sortByColumn(0, Qt::AscendingOrder); + + model->setFilter(filter); + model->setRootPath(instance->gameRoot()); + + QHeaderView* headerView = ui->treeView->header(); + headerView->setSectionResizeMode(QHeaderView::ResizeToContents); + headerView->setSectionResizeMode(0, QHeaderView::Stretch); +} + +ExportPackDialog::~ExportPackDialog() +{ + delete ui; +} + +void ExportPackDialog::done(int result) +{ + if (result == Accepted) { + const QString filename = FS::RemoveInvalidFilenameChars(ui->name->text()); + QString output; + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) + output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), + FS::PathCombine(QDir::homePath(), filename + ".mrpack"), "Modrinth pack (*.mrpack *.zip)", + nullptr); + else + output = QFileDialog::getSaveFileName(this, tr("Export %1").arg(ui->name->text()), + FS::PathCombine(QDir::homePath(), filename + ".zip"), "CurseForge pack (*.zip)", nullptr); + + if (output.isEmpty()) + return; + Task* task; + if (m_provider == ModPlatform::ResourceProvider::MODRINTH) + task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, + [this](const QString& path) { return proxy->blockedPaths().covers(path); }); + else + task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), instance, output, + [this](const QString& path) { return proxy->blockedPaths().covers(path); }); + + connect(task, &Task::failed, + [this](const QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); + connect(task, &Task::aborted, [this] { + CustomMessageBox::selectable(this, tr("Task aborted"), tr("The task has been aborted by the user."), QMessageBox::Information) + ->show(); + }); + connect(task, &Task::finished, [task] { task->deleteLater(); }); + + ProgressDialog progress(this); + progress.setSkipButton(true, tr("Abort")); + if (progress.execWithTask(task) != QDialog::Accepted) + return; + } + + QDialog::done(result); +} + +void ExportPackDialog::validate() +{ + const bool invalid = + ui->name->text().isEmpty() || ((m_provider == ModPlatform::ResourceProvider::MODRINTH) && ui->version->text().isEmpty()); + ui->buttonBox->button(QDialogButtonBox::Ok)->setDisabled(invalid); +} diff --git a/launcher/ui/dialogs/ExportPackDialog.h b/launcher/ui/dialogs/ExportPackDialog.h new file mode 100644 index 00000000..830c24d2 --- /dev/null +++ b/launcher/ui/dialogs/ExportPackDialog.h @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include "BaseInstance.h" +#include "FastFileIconProvider.h" +#include "FileIgnoreProxy.h" +#include "modplatform/ModIndex.h" + +namespace Ui { +class ExportPackDialog; +} + +class ExportPackDialog : public QDialog { + Q_OBJECT + + public: + explicit ExportPackDialog(InstancePtr instance, + QWidget* parent = nullptr, + ModPlatform::ResourceProvider provider = ModPlatform::ResourceProvider::MODRINTH); + ~ExportPackDialog(); + + void done(int result) override; + void validate(); + + private: + const InstancePtr instance; + Ui::ExportPackDialog* ui; + FileIgnoreProxy* proxy; + FastFileIconProvider icons; + const ModPlatform::ResourceProvider m_provider; +}; diff --git a/launcher/ui/dialogs/ExportPackDialog.ui b/launcher/ui/dialogs/ExportPackDialog.ui new file mode 100644 index 00000000..5762508a --- /dev/null +++ b/launcher/ui/dialogs/ExportPackDialog.ui @@ -0,0 +1,146 @@ + + + ExportPackDialog + + + + 0 + 0 + 650 + 413 + + + + Export Modrinth Pack + + + true + + + + + + Information + + + + + + Summary + + + + + + + + + + Name + + + + + + + Version + + + + + + + + + + 1.0.0 + + + + + + + Author + + + + + + + + + + + + + Files + + + + + + + true + + + QAbstractItemView::ExtendedSelection + + + true + + + false + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + name + version + summary + treeView + + + + + buttonBox + accepted() + ExportPackDialog + accept() + + + 324 + 390 + + + 324 + 206 + + + + + buttonBox + rejected() + ExportPackDialog + reject() + + + 324 + 390 + + + 324 + 206 + + + + + -- cgit From 4a84084d9d605ae4fa9a8063f36bfdbcdc4c5c3d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 15:02:00 +0300 Subject: Added condition for modlist Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 20 +++++++++++--------- launcher/modplatform/flame/FlamePackExportTask.h | 2 ++ launcher/ui/dialogs/ExportPackDialog.cpp | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index fb5bcc0b..dc407653 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -118,7 +118,7 @@ void FlamePackExportTask::collectHashes() } if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), - { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), + { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), true, mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") }); setProgress(m_progress + 1, totalProgres); continue; @@ -128,7 +128,7 @@ void FlamePackExportTask::collectHashes() connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, totalProgres](QString hash) { if (m_state == Task::State::Running) { setProgress(m_progress + 1, totalProgres); - pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled() }); + pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled(), true }); } }); connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); @@ -215,8 +215,8 @@ void FlamePackExportTask::makeApiRequest() setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(mod->name)); if (Json::ensureBoolean(file_obj, "isAvailable", false, "isAvailable")) - resolvedFiles.insert(mod->path, - { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), mod->enabled }); + resolvedFiles.insert(mod->path, { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), + mod->enabled, mod->isMod }); } } catch (Json::JsonException& e) { @@ -336,11 +336,13 @@ void FlamePackExportTask::buildZip() } QString content = ""; for (auto mod : resolvedFiles) { - content += QString(TEMPLATE) - .replace("{name}", mod.name) - .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)) - .replace("{authors}", mod.authors) + - "\n"; + if (mod.isMod) { + content += QString(TEMPLATE) + .replace("{name}", mod.name) + .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)) + .replace("{authors}", mod.authors) + + "\n"; + } } content = "
      " + content + "
    "; modlist.write(content.toUtf8()); diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 629493d8..ee1f4e8d 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -57,6 +57,7 @@ class FlamePackExportTask : public Task { int addonId; int version; bool enabled; + bool isMod; QString name; QString slug; @@ -66,6 +67,7 @@ class FlamePackExportTask : public Task { QString name; QString path; bool enabled; + bool isMod; }; FlameAPI api; diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index 8e921f89..fb71f4a5 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -22,7 +22,7 @@ #include "modplatform/flame/FlamePackExportTask.h" #include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/ProgressDialog.h" -#include "ui_ExportMrPackDialog.h" +#include "ui_ExportPackDialog.h" #include #include -- cgit From 19cb6ad5883c59c27f954042025bf89d44bed096 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 15:04:18 +0300 Subject: Updated Modrinth esport messages Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index dc407653..837ded0f 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -157,12 +157,12 @@ void FlamePackExportTask::collectHashes() void FlamePackExportTask::makeApiRequest() { - setStatus(tr("Find versions for hashes...")); if (pendingHashes.isEmpty()) { buildZip(); return; } + setStatus(tr("Find versions for hashes...")); auto response = std::make_shared(); QList fingerprints; diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index c607bb89..dd748687 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -64,7 +64,8 @@ bool ModrinthPackExportTask::abort() if (buildZipFuture.isRunning()) { buildZipFuture.cancel(); - // NOTE: Here we don't do `emitAborted()` because it will be done when `buildZipFuture` actually cancels, which may not occur immediately. + // NOTE: Here we don't do `emitAborted()` because it will be done when `buildZipFuture` actually cancels, which may not occur + // immediately. return true; } @@ -94,6 +95,7 @@ void ModrinthPackExportTask::collectFiles() void ModrinthPackExportTask::collectHashes() { + setStatus(tr("Find file hashes...")); for (const QFileInfo& file : files) { QCoreApplication::processEvents(); @@ -157,6 +159,7 @@ void ModrinthPackExportTask::makeApiRequest() if (pendingHashes.isEmpty()) buildZip(); else { + setStatus(tr("Find versions for hashes...")); auto response = std::make_shared(); task = api.currentVersions(pendingHashes.values(), "sha512", response); connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); -- cgit From f825d7753afd6c00111c9ff9deedeee8ded5b27a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 15:11:15 +0300 Subject: Updated copyright headers Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 1 + launcher/modplatform/flame/FlamePackExportTask.h | 1 + 2 files changed, 2 insertions(+) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 837ded0f..2759ae09 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index ee1f4e8d..cf67ed5f 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only /* * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 TheKodeToad * Copyright (c) 2023 Trial97 * * This program is free software: you can redistribute it and/or modify -- cgit From 8b576fd2bd442a61092de870b4323c280b04d2d6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 15:59:55 +0300 Subject: Added translation Signed-off-by: Trial97 --- launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp | 2 +- launcher/modplatform/flame/FlameModIndex.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp index b1058ee6..f8ecdb33 100644 --- a/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp +++ b/launcher/minecraft/mod/tasks/GetModDependenciesTask.cpp @@ -48,7 +48,7 @@ GetModDependenciesTask::GetModDependenciesTask(QObject* parent, BaseInstance* instance, ModFolderModel* folder, QList> selected) - : SequentialTask(parent, "Get dependencies") + : SequentialTask(parent, tr("Get dependencies")) , m_selected(selected) , m_flame_provider{ ModPlatform::ResourceProvider::FLAME, std::make_shared(*instance), std::make_shared() } diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp index 9c8eb832..227ce489 100644 --- a/launcher/modplatform/flame/FlameModIndex.cpp +++ b/launcher/modplatform/flame/FlameModIndex.cpp @@ -160,10 +160,9 @@ auto FlameMod::loadIndexedPackVersion(QJsonObject& obj, bool load_changelog) -> case 6: // Include dependency.type = ModPlatform::DependencyType::INCLUDE; break; - default: + default: dependency.type = ModPlatform::DependencyType::UNKNOWN; break; - } file.dependencies.append(dependency); } -- cgit From df932c65875a20fd95a47c3394a802d131e93993 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 20:22:18 +0300 Subject: Updated authors string in modlist Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 2759ae09..54294d7b 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -36,7 +36,7 @@ #include "modplatform/helpers/HashUtils.h" #include "tasks/Task.h" -const QString FlamePackExportTask::TEMPLATE = "
  • {name} (by {authors})
  • "; +const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • "; FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, @@ -338,11 +338,12 @@ void FlamePackExportTask::buildZip() QString content = ""; for (auto mod : resolvedFiles) { if (mod.isMod) { - content += QString(TEMPLATE) - .replace("{name}", mod.name) - .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)) - .replace("{authors}", mod.authors) + - "\n"; + auto line = QString(TEMPLATE) + .replace("{name}", mod.name) + .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)); + if (!mod.authors.isEmpty()) + line = line.replace("{authors}", QString(" (by {%1})").arg(mod.authors)); + content += line + "\n"; } } content = "
      " + content + "
    "; -- cgit From f0e4e07c05bdf68994c9d6a460f4ec4c03a2e627 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 20:43:45 +0300 Subject: Updated url function Signed-off-by: Trial97 --- launcher/minecraft/mod/Mod.cpp | 2 +- launcher/modplatform/ModIndex.cpp | 7 +++---- launcher/modplatform/ModIndex.h | 2 +- launcher/modplatform/flame/FlamePackExportTask.cpp | 12 +++++------- 4 files changed, 10 insertions(+), 13 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index e93ff8bc..d5b96bad 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -170,7 +170,7 @@ auto Mod::metaurl() const -> QString { if (metadata() == nullptr) return homeurl(); - return ModPlatform::getMetaURL(metadata()->provider, metadata()->slug); + return ModPlatform::getMetaURL(metadata()->provider, metadata()->project_id); } auto Mod::description() const -> QString diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index c68333c5..a1c4d891 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -77,11 +77,10 @@ auto ProviderCapabilities::hash(ResourceProvider p, QIODevice* device, QString t return { hash.result().toHex() }; } -QString getMetaURL(ResourceProvider provider, QString slug) +QString getMetaURL(ResourceProvider provider, QVariant projectID) { - return ((provider == ModPlatform::ResourceProvider::FLAME) ? "https://www.curseforge.com/minecraft/mc-mods/" - : "https://modrinth.com/mod/") + - slug.remove(".pw.toml"); + return ((provider == ModPlatform::ResourceProvider::FLAME) ? "https://www.curseforge.com/projects/" : "https://modrinth.com/mod/") + + projectID.toString(); } } // namespace ModPlatform diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 83412169..773ee934 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -128,7 +128,7 @@ struct IndexedPack { return std::any_of(versions.constBegin(), versions.constEnd(), [](auto const& v) { return v.is_currently_selected; }); } }; -QString getMetaURL(ResourceProvider provider, QString slug); +QString getMetaURL(ResourceProvider provider, QVariant projectID); struct OverrideDep { QString quilt; diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 54294d7b..d729e977 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -36,7 +36,7 @@ #include "modplatform/helpers/HashUtils.h" #include "tasks/Task.h" -const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • "; +const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • \n"; FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, @@ -338,12 +338,10 @@ void FlamePackExportTask::buildZip() QString content = ""; for (auto mod : resolvedFiles) { if (mod.isMod) { - auto line = QString(TEMPLATE) - .replace("{name}", mod.name) - .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.slug)); - if (!mod.authors.isEmpty()) - line = line.replace("{authors}", QString(" (by {%1})").arg(mod.authors)); - content += line + "\n"; + content += QString(TEMPLATE) + .replace("{name}", mod.name) + .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.addonId)) + .replace("{authors}", !mod.authors.isEmpty() ? QString(" (by {%1})").arg(mod.authors) : ""); } } content = "
      " + content + "
    "; -- cgit From 69c21454ecf683b1794aec55ddad66d53d3afc7c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 22:15:18 +0300 Subject: removed projectID Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 6 +----- launcher/modplatform/flame/FlamePackExportTask.h | 2 -- launcher/ui/dialogs/ExportPackDialog.cpp | 6 ++---- launcher/ui/dialogs/ExportPackDialog.ui | 11 +---------- 4 files changed, 4 insertions(+), 21 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index d729e977..ac85a628 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -41,14 +41,12 @@ const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors} FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, const QString& author, - const QVariant& projectID, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter) : name(name) , version(version) , author(author) - , projectID(projectID) , instance(instance) , mcInstance(dynamic_cast(instance.get())) , gameRoot(instance->gameRoot()) @@ -341,7 +339,7 @@ void FlamePackExportTask::buildZip() content += QString(TEMPLATE) .replace("{name}", mod.name) .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.addonId)) - .replace("{authors}", !mod.authors.isEmpty() ? QString(" (by {%1})").arg(mod.authors) : ""); + .replace("{authors}", !mod.authors.isEmpty() ? QString(" (by %1)").arg(mod.authors) : ""); } } content = "
      " + content + "
    "; @@ -398,8 +396,6 @@ QByteArray FlamePackExportTask::generateIndex() obj["name"] = name; obj["version"] = version; obj["author"] = author; - if (projectID.toInt() != 0) - obj["projectID"] = projectID.toInt(); obj["overrides"] = "overrides"; if (mcInstance) { QJsonObject version; diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index cf67ed5f..5c8caa45 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -32,7 +32,6 @@ class FlamePackExportTask : public Task { FlamePackExportTask(const QString& name, const QString& version, const QString& author, - const QVariant& projectID, InstancePtr instance, const QString& output, MMCZip::FilterFunction filter); @@ -46,7 +45,6 @@ class FlamePackExportTask : public Task { // inputs const QString name, version, author; - const QVariant projectID; const InstancePtr instance; MinecraftInstance* mcInstance; const QDir gameRoot; diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index fb71f4a5..ea364939 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -41,12 +41,10 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla ui->name->setText(instance->name()); if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); - ui->author->hide(); - ui->authorLabel->hide(); } else { setWindowTitle("Export CurseForge Pack"); ui->version->setText(""); - ui->summaryLabel->setText("ProjectID"); + ui->summaryLabel->setText("Author"); } // ensure a valid pack is generated @@ -117,7 +115,7 @@ void ExportPackDialog::done(int result) task = new ModrinthPackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); else - task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->author->text(), ui->summary->text(), instance, output, + task = new FlamePackExportTask(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, [this](const QString& path) { return proxy->blockedPaths().covers(path); }); connect(task, &Task::failed, diff --git a/launcher/ui/dialogs/ExportPackDialog.ui b/launcher/ui/dialogs/ExportPackDialog.ui index 5762508a..658e2199 100644 --- a/launcher/ui/dialogs/ExportPackDialog.ui +++ b/launcher/ui/dialogs/ExportPackDialog.ui @@ -57,16 +57,7 @@ - - - - Author - - - - - - + -- cgit From 932531c8ba1197e38dcd66c1ad146aeebc9ca177 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sat, 24 Jun 2023 23:48:18 +0300 Subject: fixed authors Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- launcher/ui/dialogs/ExportPackDialog.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index ac85a628..e73f3de5 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -95,8 +95,8 @@ void FlamePackExportTask::collectFiles() resolvedFiles.clear(); if (mcInstance != nullptr) { - connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, &FlamePackExportTask::collectHashes); mcInstance->loaderModList()->update(); + connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, &FlamePackExportTask::collectHashes); } else collectHashes(); } diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index ea364939..fd374246 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -73,6 +73,7 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla MinecraftInstance* mcInstance = dynamic_cast(instance.get()); if (mcInstance) { + mcInstance->loaderModList()->update(); const QDir index = mcInstance->loaderModList()->indexDir(); if (index.exists()) proxy->blockedPaths().insert(root.relativeFilePath(index.absolutePath())); -- cgit From 529e2054eadf4c97231a51d7bd2d25cb75bd74c9 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 24 Jun 2023 22:54:05 +0100 Subject: A few tweaks, with inspiration from Zeke :3 Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 6 +- launcher/ui/dialogs/NewInstanceDialog.cpp | 4 +- launcher/ui/pages/instance/VersionPage.cpp | 1 - launcher/ui/pages/instance/VersionPage.ui | 10 - launcher/ui/pages/modplatform/CustomPage.cpp | 241 +++++++++++++++++++++ launcher/ui/pages/modplatform/CustomPage.h | 104 +++++++++ launcher/ui/pages/modplatform/CustomPage.ui | 290 ++++++++++++++++++++++++++ launcher/ui/pages/modplatform/VanillaPage.cpp | 241 --------------------- launcher/ui/pages/modplatform/VanillaPage.h | 104 --------- launcher/ui/pages/modplatform/VanillaPage.ui | 290 -------------------------- 10 files changed, 640 insertions(+), 651 deletions(-) create mode 100644 launcher/ui/pages/modplatform/CustomPage.cpp create mode 100644 launcher/ui/pages/modplatform/CustomPage.h create mode 100644 launcher/ui/pages/modplatform/CustomPage.ui delete mode 100644 launcher/ui/pages/modplatform/VanillaPage.cpp delete mode 100644 launcher/ui/pages/modplatform/VanillaPage.h delete mode 100644 launcher/ui/pages/modplatform/VanillaPage.ui (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 9bad2a67..c10064c0 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -827,8 +827,8 @@ SET(LAUNCHER_SOURCES ui/pages/global/APIPage.h # GUI - platform pages - ui/pages/modplatform/VanillaPage.cpp - ui/pages/modplatform/VanillaPage.h + ui/pages/modplatform/CustomPage.cpp + ui/pages/modplatform/CustomPage.h ui/pages/modplatform/ResourcePage.cpp ui/pages/modplatform/ResourcePage.h @@ -1034,7 +1034,7 @@ qt_wrap_ui(LAUNCHER_UI ui/pages/instance/ScreenshotsPage.ui ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui ui/pages/modplatform/atlauncher/AtlPage.ui - ui/pages/modplatform/VanillaPage.ui + ui/pages/modplatform/CustomPage.ui ui/pages/modplatform/ResourcePage.ui ui/pages/modplatform/flame/FlamePage.ui ui/pages/modplatform/legacy_ftb/Page.ui diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp index aafaf220..7b9bb944 100644 --- a/launcher/ui/dialogs/NewInstanceDialog.cpp +++ b/launcher/ui/dialogs/NewInstanceDialog.cpp @@ -54,7 +54,7 @@ #include #include "ui/widgets/PageContainer.h" -#include "ui/pages/modplatform/VanillaPage.h" +#include "ui/pages/modplatform/CustomPage.h" #include "ui/pages/modplatform/atlauncher/AtlPage.h" #include "ui/pages/modplatform/legacy_ftb/Page.h" #include "ui/pages/modplatform/flame/FlamePage.h" @@ -162,7 +162,7 @@ QList NewInstanceDialog::getPages() importPage = new ImportPage(this); - pages.append(new VanillaPage(this)); + pages.append(new CustomPage(this)); pages.append(importPage); pages.append(new AtlPage(this)); if (APPLICATION->capabilities() & Application::SupportsFlame) diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 74b7ec7c..59107c53 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -287,7 +287,6 @@ void VersionPage::updateButtons(int row) ui->actionAdd_Empty->setEnabled(controlsEnabled); ui->actionImport_Components->setEnabled(controlsEnabled); ui->actionReload->setEnabled(controlsEnabled); - ui->actionInstall_mods->setEnabled(controlsEnabled); ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled); ui->actionAdd_to_Minecraft_jar->setEnabled(controlsEnabled); ui->actionAdd_Agents->setEnabled(controlsEnabled); diff --git a/launcher/ui/pages/instance/VersionPage.ui b/launcher/ui/pages/instance/VersionPage.ui index 4777eafe..a73c42d6 100644 --- a/launcher/ui/pages/instance/VersionPage.ui +++ b/launcher/ui/pages/instance/VersionPage.ui @@ -102,7 +102,6 @@ - @@ -112,7 +111,6 @@ - @@ -204,14 +202,6 @@ Install the LiteLoader package. - - - Install mods - - - Install normal mods. - - Add to Minecraft.jar diff --git a/launcher/ui/pages/modplatform/CustomPage.cpp b/launcher/ui/pages/modplatform/CustomPage.cpp new file mode 100644 index 00000000..e164171a --- /dev/null +++ b/launcher/ui/pages/modplatform/CustomPage.cpp @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 Jamie Mansfield + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CustomPage.h" +#include "ui_CustomPage.h" + +#include + +#include "Application.h" +#include "Filter.h" +#include "Version.h" +#include "meta/Index.h" +#include "meta/VersionList.h" +#include "minecraft/VanillaInstanceCreationTask.h" +#include "ui/dialogs/NewInstanceDialog.h" + +CustomPage::CustomPage(NewInstanceDialog *dialog, QWidget *parent) + : QWidget(parent), dialog(dialog), ui(new Ui::CustomPage) +{ + ui->setupUi(this); + ui->tabWidget->tabBar()->hide(); + connect(ui->versionList, &VersionSelectWidget::selectedVersionChanged, this, &CustomPage::setSelectedVersion); + filterChanged(); + connect(ui->alphaFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged); + connect(ui->betaFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged); + connect(ui->snapshotFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged); + connect(ui->oldSnapshotFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged); + connect(ui->releaseFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged); + connect(ui->experimentsFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged); + connect(ui->refreshBtn, &QPushButton::clicked, this, &CustomPage::refresh); + + connect(ui->loaderVersionList, &VersionSelectWidget::selectedVersionChanged, this, &CustomPage::setSelectedLoaderVersion); + connect(ui->noneFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged); + connect(ui->forgeFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged); + connect(ui->fabricFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged); + connect(ui->quiltFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged); + connect(ui->liteLoaderFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged); + connect(ui->loaderRefreshBtn, &QPushButton::clicked, this, &CustomPage::loaderRefresh); + +} + +void CustomPage::openedImpl() +{ + if(!initialized) + { + auto vlist = APPLICATION->metadataIndex()->get("net.minecraft"); + ui->versionList->initialize(vlist.get()); + initialized = true; + } + else + { + suggestCurrent(); + } +} + +void CustomPage::refresh() +{ + ui->versionList->loadList(); +} + +void CustomPage::loaderRefresh() +{ + if(ui->noneFilter->isChecked()) + return; + ui->loaderVersionList->loadList(); +} + +void CustomPage::filterChanged() +{ + QStringList out; + if(ui->alphaFilter->isChecked()) + out << "(old_alpha)"; + if(ui->betaFilter->isChecked()) + out << "(old_beta)"; + if(ui->snapshotFilter->isChecked()) + out << "(snapshot)"; + if(ui->oldSnapshotFilter->isChecked()) + out << "(old_snapshot)"; + if(ui->releaseFilter->isChecked()) + out << "(release)"; + if(ui->experimentsFilter->isChecked()) + out << "(experiment)"; + auto regexp = out.join('|'); + ui->versionList->setFilter(BaseVersionList::TypeRole, new RegexpFilter(regexp, false)); +} + +void CustomPage::loaderFilterChanged() +{ + QString minecraftVersion; + if (m_selectedVersion) + { + minecraftVersion = m_selectedVersion->descriptor(); + } + else + { + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // empty list + ui->loaderVersionList->setEmptyString(tr("No Minecraft version is selected.")); + ui->loaderVersionList->setEmptyMode(VersionListView::String); + return; + } + if(ui->noneFilter->isChecked()) + { + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // empty list + ui->loaderVersionList->setEmptyString(tr("No mod loader is selected.")); + ui->loaderVersionList->setEmptyMode(VersionListView::String); + return; + } + else if(ui->forgeFilter->isChecked()) + { + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); + m_selectedLoader = "net.minecraftforge"; + } + else if(ui->fabricFilter->isChecked()) + { + // FIXME: dirty hack because the launcher is unaware of Fabric's dependencies + if (Version(minecraftVersion) >= Version("1.14")) // Fabric/Quilt supported + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, ""); + else // Fabric/Quilt unsupported + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list + m_selectedLoader = "net.fabricmc.fabric-loader"; + } + else if(ui->quiltFilter->isChecked()) + { + // FIXME: dirty hack because the launcher is unaware of Quilt's dependencies (same as Fabric) + if (Version(minecraftVersion) >= Version("1.14")) // Fabric/Quilt supported + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, ""); + else // Fabric/Quilt unsupported + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list + m_selectedLoader = "org.quiltmc.quilt-loader"; + } + else if(ui->liteLoaderFilter->isChecked()) + { + ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); + m_selectedLoader = "com.mumfrey.liteloader"; + } + + auto vlist = APPLICATION->metadataIndex()->get(m_selectedLoader); + ui->loaderVersionList->initialize(vlist.get()); + ui->loaderVersionList->selectRecommended(); + ui->loaderVersionList->setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); +} + +CustomPage::~CustomPage() +{ + delete ui; +} + +bool CustomPage::shouldDisplay() const +{ + return true; +} + +void CustomPage::retranslate() +{ + ui->retranslateUi(this); +} + +BaseVersion::Ptr CustomPage::selectedVersion() const +{ + return m_selectedVersion; +} + +BaseVersion::Ptr CustomPage::selectedLoaderVersion() const +{ + return m_selectedLoaderVersion; +} + +QString CustomPage::selectedLoader() const +{ + return m_selectedLoader; +} + +void CustomPage::suggestCurrent() +{ + if (!isOpened) + { + return; + } + + if(!m_selectedVersion) + { + dialog->setSuggestedPack(); + return; + } + + // There isn't a selected version if the version list is empty + if(ui->loaderVersionList->selectedVersion() == nullptr) + dialog->setSuggestedPack(m_selectedVersion->descriptor(), new VanillaCreationTask(m_selectedVersion)); + else + { + dialog->setSuggestedPack(m_selectedVersion->descriptor(), + new VanillaCreationTask(m_selectedVersion, m_selectedLoader, + m_selectedLoaderVersion)); + } + dialog->setSuggestedIcon("default"); +} + +void CustomPage::setSelectedVersion(BaseVersion::Ptr version) +{ + m_selectedVersion = version; + suggestCurrent(); + loaderFilterChanged(); +} + +void CustomPage::setSelectedLoaderVersion(BaseVersion::Ptr version) +{ + m_selectedLoaderVersion = version; + suggestCurrent(); +} diff --git a/launcher/ui/pages/modplatform/CustomPage.h b/launcher/ui/pages/modplatform/CustomPage.h new file mode 100644 index 00000000..8b5a5011 --- /dev/null +++ b/launcher/ui/pages/modplatform/CustomPage.h @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (c) 2022 Jamie Mansfield + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include "ui/pages/BasePage.h" +#include +#include "tasks/Task.h" + +namespace Ui +{ +class CustomPage; +} + +class NewInstanceDialog; + +class CustomPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit CustomPage(NewInstanceDialog *dialog, QWidget *parent = 0); + virtual ~CustomPage(); + virtual QString displayName() const override + { + return tr("Custom"); + } + virtual QIcon icon() const override + { + return APPLICATION->getThemedIcon("minecraft"); + } + virtual QString id() const override + { + return "vanilla"; + } + virtual QString helpPage() const override + { + return "Vanilla-platform"; + } + virtual bool shouldDisplay() const override; + void retranslate() override; + + void openedImpl() override; + + BaseVersion::Ptr selectedVersion() const; + BaseVersion::Ptr selectedLoaderVersion() const; + QString selectedLoader() const; + +public slots: + void setSelectedVersion(BaseVersion::Ptr version); + void setSelectedLoaderVersion(BaseVersion::Ptr version); + +private slots: + void filterChanged(); + void loaderFilterChanged(); + +private: + void refresh(); + void loaderRefresh(); + void suggestCurrent(); + +private: + bool initialized = false; + NewInstanceDialog *dialog = nullptr; + Ui::CustomPage *ui = nullptr; + bool m_versionSetByUser = false; + BaseVersion::Ptr m_selectedVersion; + BaseVersion::Ptr m_selectedLoaderVersion; + QString m_selectedLoader; +}; diff --git a/launcher/ui/pages/modplatform/CustomPage.ui b/launcher/ui/pages/modplatform/CustomPage.ui new file mode 100644 index 00000000..0d89b595 --- /dev/null +++ b/launcher/ui/pages/modplatform/CustomPage.ui @@ -0,0 +1,290 @@ + + + CustomPage + + + + 0 + 0 + 815 + 607 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + + + + 0 + 0 + + + + + + + + + + Filter + + + Qt::AlignCenter + + + + + + + Releases + + + true + + + true + + + + + + + Snapshots + + + true + + + + + + + Old Snapshots + + + true + + + + + + + Betas + + + true + + + + + + + Alphas + + + true + + + + + + + Experiments + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Refresh + + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + Mod Loader + + + Qt::AlignCenter + + + + + + + None + + + true + + + loaderBtnGroup + + + + + + + Forge + + + loaderBtnGroup + + + + + + + Fabric + + + loaderBtnGroup + + + + + + + Quilt + + + loaderBtnGroup + + + + + + + LiteLoader + + + loaderBtnGroup + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Refresh + + + + + + + + + + + + + + + + VersionSelectWidget + QWidget +
    ui/widgets/VersionSelectWidget.h
    + 1 +
    +
    + + tabWidget + releaseFilter + snapshotFilter + oldSnapshotFilter + betaFilter + alphaFilter + experimentsFilter + refreshBtn + + + + + + +
    diff --git a/launcher/ui/pages/modplatform/VanillaPage.cpp b/launcher/ui/pages/modplatform/VanillaPage.cpp deleted file mode 100644 index 29fecb85..00000000 --- a/launcher/ui/pages/modplatform/VanillaPage.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * PolyMC - Minecraft Launcher - * Copyright (c) 2022 Jamie Mansfield - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright 2013-2021 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "VanillaPage.h" -#include "ui_VanillaPage.h" - -#include - -#include "Application.h" -#include "Filter.h" -#include "Version.h" -#include "meta/Index.h" -#include "meta/VersionList.h" -#include "minecraft/VanillaInstanceCreationTask.h" -#include "ui/dialogs/NewInstanceDialog.h" - -VanillaPage::VanillaPage(NewInstanceDialog *dialog, QWidget *parent) - : QWidget(parent), dialog(dialog), ui(new Ui::VanillaPage) -{ - ui->setupUi(this); - ui->tabWidget->tabBar()->hide(); - connect(ui->versionList, &VersionSelectWidget::selectedVersionChanged, this, &VanillaPage::setSelectedVersion); - filterChanged(); - connect(ui->alphaFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged); - connect(ui->betaFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged); - connect(ui->snapshotFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged); - connect(ui->oldSnapshotFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged); - connect(ui->releaseFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged); - connect(ui->experimentsFilter, &QCheckBox::stateChanged, this, &VanillaPage::filterChanged); - connect(ui->refreshBtn, &QPushButton::clicked, this, &VanillaPage::refresh); - - connect(ui->loaderVersionList, &VersionSelectWidget::selectedVersionChanged, this, &VanillaPage::setSelectedLoaderVersion); - connect(ui->noneFilter, &QRadioButton::toggled, this, &VanillaPage::loaderFilterChanged); - connect(ui->forgeFilter, &QRadioButton::toggled, this, &VanillaPage::loaderFilterChanged); - connect(ui->fabricFilter, &QRadioButton::toggled, this, &VanillaPage::loaderFilterChanged); - connect(ui->quiltFilter, &QRadioButton::toggled, this, &VanillaPage::loaderFilterChanged); - connect(ui->liteLoaderFilter, &QRadioButton::toggled, this, &VanillaPage::loaderFilterChanged); - connect(ui->loaderRefreshBtn, &QPushButton::clicked, this, &VanillaPage::loaderRefresh); - -} - -void VanillaPage::openedImpl() -{ - if(!initialized) - { - auto vlist = APPLICATION->metadataIndex()->get("net.minecraft"); - ui->versionList->initialize(vlist.get()); - initialized = true; - } - else - { - suggestCurrent(); - } -} - -void VanillaPage::refresh() -{ - ui->versionList->loadList(); -} - -void VanillaPage::loaderRefresh() -{ - if(ui->noneFilter->isChecked()) - return; - ui->loaderVersionList->loadList(); -} - -void VanillaPage::filterChanged() -{ - QStringList out; - if(ui->alphaFilter->isChecked()) - out << "(old_alpha)"; - if(ui->betaFilter->isChecked()) - out << "(old_beta)"; - if(ui->snapshotFilter->isChecked()) - out << "(snapshot)"; - if(ui->oldSnapshotFilter->isChecked()) - out << "(old_snapshot)"; - if(ui->releaseFilter->isChecked()) - out << "(release)"; - if(ui->experimentsFilter->isChecked()) - out << "(experiment)"; - auto regexp = out.join('|'); - ui->versionList->setFilter(BaseVersionList::TypeRole, new RegexpFilter(regexp, false)); -} - -void VanillaPage::loaderFilterChanged() -{ - QString minecraftVersion; - if (m_selectedVersion) - { - minecraftVersion = m_selectedVersion->descriptor(); - } - else - { - ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // empty list - ui->loaderVersionList->setEmptyString(tr("No Minecraft version is selected.")); - ui->loaderVersionList->setEmptyMode(VersionListView::String); - return; - } - if(ui->noneFilter->isChecked()) - { - ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // empty list - ui->loaderVersionList->setEmptyString(tr("No mod loader is selected.")); - ui->loaderVersionList->setEmptyMode(VersionListView::String); - return; - } - else if(ui->forgeFilter->isChecked()) - { - ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); - m_selectedLoader = "net.minecraftforge"; - } - else if(ui->fabricFilter->isChecked()) - { - // FIXME: dirty hack because the launcher is unaware of Fabric's dependencies - if (Version(minecraftVersion) >= Version("1.14")) // Fabric/Quilt supported - ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, ""); - else // Fabric/Quilt unsupported - ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list - m_selectedLoader = "net.fabricmc.fabric-loader"; - } - else if(ui->quiltFilter->isChecked()) - { - // FIXME: dirty hack because the launcher is unaware of Quilt's dependencies (same as Fabric) - if (Version(minecraftVersion) >= Version("1.14")) // Fabric/Quilt supported - ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, ""); - else // Fabric/Quilt unsupported - ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list - m_selectedLoader = "org.quiltmc.quilt-loader"; - } - else if(ui->liteLoaderFilter->isChecked()) - { - ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion); - m_selectedLoader = "com.mumfrey.liteloader"; - } - - auto vlist = APPLICATION->metadataIndex()->get(m_selectedLoader); - ui->loaderVersionList->initialize(vlist.get()); - ui->loaderVersionList->selectRecommended(); - ui->loaderVersionList->setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion)); -} - -VanillaPage::~VanillaPage() -{ - delete ui; -} - -bool VanillaPage::shouldDisplay() const -{ - return true; -} - -void VanillaPage::retranslate() -{ - ui->retranslateUi(this); -} - -BaseVersion::Ptr VanillaPage::selectedVersion() const -{ - return m_selectedVersion; -} - -BaseVersion::Ptr VanillaPage::selectedLoaderVersion() const -{ - return m_selectedLoaderVersion; -} - -QString VanillaPage::selectedLoader() const -{ - return m_selectedLoader; -} - -void VanillaPage::suggestCurrent() -{ - if (!isOpened) - { - return; - } - - if(!m_selectedVersion) - { - dialog->setSuggestedPack(); - return; - } - - // There isn't a selected version if the version list is empty - if(ui->loaderVersionList->selectedVersion() == nullptr) - dialog->setSuggestedPack(m_selectedVersion->descriptor(), new VanillaCreationTask(m_selectedVersion)); - else - { - dialog->setSuggestedPack(m_selectedVersion->descriptor(), - new VanillaCreationTask(m_selectedVersion, m_selectedLoader, - m_selectedLoaderVersion)); - } - dialog->setSuggestedIcon("default"); -} - -void VanillaPage::setSelectedVersion(BaseVersion::Ptr version) -{ - m_selectedVersion = version; - suggestCurrent(); - loaderFilterChanged(); -} - -void VanillaPage::setSelectedLoaderVersion(BaseVersion::Ptr version) -{ - m_selectedLoaderVersion = version; - suggestCurrent(); -} diff --git a/launcher/ui/pages/modplatform/VanillaPage.h b/launcher/ui/pages/modplatform/VanillaPage.h deleted file mode 100644 index 39aba760..00000000 --- a/launcher/ui/pages/modplatform/VanillaPage.h +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * PolyMC - Minecraft Launcher - * Copyright (c) 2022 Jamie Mansfield - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright 2013-2021 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -#include "ui/pages/BasePage.h" -#include -#include "tasks/Task.h" - -namespace Ui -{ -class VanillaPage; -} - -class NewInstanceDialog; - -class VanillaPage : public QWidget, public BasePage -{ - Q_OBJECT - -public: - explicit VanillaPage(NewInstanceDialog *dialog, QWidget *parent = 0); - virtual ~VanillaPage(); - virtual QString displayName() const override - { - return tr("Vanilla"); - } - virtual QIcon icon() const override - { - return APPLICATION->getThemedIcon("minecraft"); - } - virtual QString id() const override - { - return "vanilla"; - } - virtual QString helpPage() const override - { - return "Vanilla-platform"; - } - virtual bool shouldDisplay() const override; - void retranslate() override; - - void openedImpl() override; - - BaseVersion::Ptr selectedVersion() const; - BaseVersion::Ptr selectedLoaderVersion() const; - QString selectedLoader() const; - -public slots: - void setSelectedVersion(BaseVersion::Ptr version); - void setSelectedLoaderVersion(BaseVersion::Ptr version); - -private slots: - void filterChanged(); - void loaderFilterChanged(); - -private: - void refresh(); - void loaderRefresh(); - void suggestCurrent(); - -private: - bool initialized = false; - NewInstanceDialog *dialog = nullptr; - Ui::VanillaPage *ui = nullptr; - bool m_versionSetByUser = false; - BaseVersion::Ptr m_selectedVersion; - BaseVersion::Ptr m_selectedLoaderVersion; - QString m_selectedLoader; -}; diff --git a/launcher/ui/pages/modplatform/VanillaPage.ui b/launcher/ui/pages/modplatform/VanillaPage.ui deleted file mode 100644 index 43110927..00000000 --- a/launcher/ui/pages/modplatform/VanillaPage.ui +++ /dev/null @@ -1,290 +0,0 @@ - - - VanillaPage - - - - 0 - 0 - 815 - 607 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - - - - - - - 0 - 0 - - - - Qt::Horizontal - - - - - - - - - - 0 - 0 - - - - - - - - - - Filter - - - Qt::AlignCenter - - - - - - - Releases - - - true - - - true - - - - - - - Snapshots - - - true - - - - - - - Old Snapshots - - - true - - - - - - - Betas - - - true - - - - - - - Alphas - - - true - - - - - - - Experiments - - - true - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Refresh - - - - - - - - - - - - - - 0 - 0 - - - - - - - - - - Mod Loader - - - Qt::AlignCenter - - - - - - - None - - - true - - - loaderBtnGroup - - - - - - - Forge - - - loaderBtnGroup - - - - - - - Fabric - - - loaderBtnGroup - - - - - - - Quilt - - - loaderBtnGroup - - - - - - - LiteLoader - - - loaderBtnGroup - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Refresh - - - - - - - - - - - - - - - - VersionSelectWidget - QWidget -
    ui/widgets/VersionSelectWidget.h
    - 1 -
    -
    - - tabWidget - releaseFilter - snapshotFilter - oldSnapshotFilter - betaFilter - alphaFilter - experimentsFilter - refreshBtn - - - - - - -
    -- cgit From bb8e6ef35ec4d911d199b06d3337dfcd1ab8b202 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 24 Jun 2023 23:26:02 +0100 Subject: Fix flat white launcher icon Signed-off-by: TheKodeToad --- .../resources/flat_white/scalable/launcher.svg | 57 +++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/resources/flat_white/scalable/launcher.svg b/launcher/resources/flat_white/scalable/launcher.svg index 54131b65..aeee8433 100644 --- a/launcher/resources/flat_white/scalable/launcher.svg +++ b/launcher/resources/flat_white/scalable/launcher.svg @@ -1,2 +1,57 @@ - + + + Prism Launcher Logo + + + + + + + + + + + + + + + + + + + + + + + Prism Launcher Logo + 19/10/2022 + + + Prism Launcher + + + + + AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke + + + https://github.com/PrismLauncher/PrismLauncher + + + Prism Launcher + + + + + + + + + + + + + + + -- cgit From 8a3aba1634ca9f8b86c995687c7e2f99740d9111 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 24 Jun 2023 23:30:51 +0100 Subject: Fix Open Global Settings, why not Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/InstanceSettingsPage.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 08977841..893fe2a5 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -86,11 +86,11 @@ void InstanceSettingsPage::globalSettingsButtonClicked(bool) APPLICATION->ShowGlobalSettings(this, "java-settings"); return; case 1: - APPLICATION->ShowGlobalSettings(this, "minecraft-settings"); - return; - case 2: APPLICATION->ShowGlobalSettings(this, "custom-commands"); return; + default: + APPLICATION->ShowGlobalSettings(this, "minecraft-settings"); + return; } } -- cgit From 5eb71fc6a96690e3d9a658f383b0937446ec3f9e Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 24 Jun 2023 23:34:37 +0100 Subject: Revert "feat(Mods): hide 'Provider' column when no mods have providers" With Ryex's change, this causes issues. Apparently you need to sign off reverts! That's just weird... Signed-off-by: TheKodeToad --- launcher/ui/widgets/ModListView.cpp | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/widgets/ModListView.cpp b/launcher/ui/widgets/ModListView.cpp index 893cd120..80a918b6 100644 --- a/launcher/ui/widgets/ModListView.cpp +++ b/launcher/ui/widgets/ModListView.cpp @@ -14,9 +14,6 @@ */ #include "ModListView.h" - -#include "minecraft/mod/ModFolderModel.h" - #include #include #include @@ -65,19 +62,6 @@ void ModListView::setModel ( QAbstractItemModel* model ) for(int i = 1; i < head->count(); i++) head->setSectionResizeMode(i, QHeaderView::ResizeToContents); } - - auto real_model = model; - if (auto proxy_model = dynamic_cast(model); proxy_model) - real_model = proxy_model->sourceModel(); - - if (auto mod_model = dynamic_cast(real_model); mod_model) { - connect(mod_model, &ModFolderModel::updateFinished, this, [this, mod_model]{ - auto mods = mod_model->allMods(); - // Hide the 'Provider' column if no mod has a defined provider! - setColumnHidden(ModFolderModel::Columns::ProviderColumn, - std::none_of(mods.constBegin(), mods.constEnd(), [](auto const mod){ return mod->provider().has_value(); })); - }); - } } void ModListView::setResizeModes(const QList &modes) -- cgit From ce4a86fbcd0c891472b842e76066d285de3aef7b Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 10:41:29 +0300 Subject: Made custom url function Signed-off-by: Trial97 --- launcher/minecraft/mod/Mod.cpp | 7 +++++++ launcher/minecraft/mod/Mod.h | 1 + launcher/modplatform/ModIndex.cpp | 8 +++++++- launcher/modplatform/ModIndex.h | 1 + launcher/ui/pages/instance/ModFolderPage.cpp | 18 +++++------------- launcher/ui/widgets/InfoFrame.cpp | 21 +++------------------ 6 files changed, 24 insertions(+), 32 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index e613ddeb..d5b96bad 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -166,6 +166,13 @@ auto Mod::homeurl() const -> QString return details().homeurl; } +auto Mod::metaurl() const -> QString +{ + if (metadata() == nullptr) + return homeurl(); + return ModPlatform::getMetaURL(metadata()->provider, metadata()->project_id); +} + auto Mod::description() const -> QString { return details().description; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index d4e419f4..d6272f4d 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -70,6 +70,7 @@ public: auto provider() const -> std::optional; auto licenses() const -> const QList&; auto issueTracker() const -> QString; + auto metaurl() const -> QString; /** Get the intneral path to the mod's icon file*/ QString iconPath() const { return m_local_details.icon_file; }; diff --git a/launcher/modplatform/ModIndex.cpp b/launcher/modplatform/ModIndex.cpp index 6a507caf..a1c4d891 100644 --- a/launcher/modplatform/ModIndex.cpp +++ b/launcher/modplatform/ModIndex.cpp @@ -70,11 +70,17 @@ auto ProviderCapabilities::hash(ResourceProvider p, QIODevice* device, QString t } QCryptographicHash hash(algo); - if(!hash.addData(device)) + if (!hash.addData(device)) qCritical() << "Failed to read JAR to create hash!"; Q_ASSERT(hash.result().length() == hash.hashLength(algo)); return { hash.result().toHex() }; } +QString getMetaURL(ResourceProvider provider, QVariant projectID) +{ + return ((provider == ModPlatform::ResourceProvider::FLAME) ? "https://www.curseforge.com/projects/" : "https://modrinth.com/mod/") + + projectID.toString(); +} + } // namespace ModPlatform diff --git a/launcher/modplatform/ModIndex.h b/launcher/modplatform/ModIndex.h index 3b0a03a1..3f51e700 100644 --- a/launcher/modplatform/ModIndex.h +++ b/launcher/modplatform/ModIndex.h @@ -144,6 +144,7 @@ inline auto getOverrideDeps() -> QList { "qvIfYCYJ", "P7dR8mSH", "API", ModPlatform::ResourceProvider::MODRINTH }, { "lwVhp9o5", "Ha28R6CL", "KotlinLibraries", ModPlatform::ResourceProvider::MODRINTH } }; }; +QString getMetaURL(ResourceProvider provider, QVariant projectID); } // namespace ModPlatform diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 9722d483..1d31a292 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -298,17 +298,9 @@ bool NilModFolderPage::shouldDisplay() const void ModFolderPage::visitModPages() { auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); - for (auto mod : m_model->selectedMods(selection)) - if (auto meta = mod->metadata(); meta != nullptr) { - auto slug = meta->slug.remove(".pw.toml"); - switch (meta->provider) { - case ModPlatform::ResourceProvider::MODRINTH: - DesktopServices::openUrl(QString("https://modrinth.com/mod/%1").arg(slug)); - break; - case ModPlatform::ResourceProvider::FLAME: - DesktopServices::openUrl(QString("https://www.curseforge.com/minecraft/mc-mods/%1").arg(slug)); - break; - } - } else if (mod->homeurl().size() != 0) - DesktopServices::openUrl(mod->homeurl()); + for (auto mod : m_model->selectedMods(selection)) { + auto url = mod->metaurl(); + if (!url.isEmpty()) + DesktopServices::openUrl(url); + } } \ No newline at end of file diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 52e79dc0..57562a93 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -41,9 +41,7 @@ #include "ui/dialogs/CustomMessageBox.h" -InfoFrame::InfoFrame(QWidget *parent) : - QFrame(parent), - ui(new Ui::InfoFrame) +InfoFrame::InfoFrame(QWidget* parent) : QFrame(parent), ui(new Ui::InfoFrame) { ui->setupUi(this); ui->descriptionLabel->setHidden(true); @@ -67,31 +65,18 @@ void InfoFrame::updateWithMod(Mod const& m) QString text = ""; QString name = ""; - QString link = ""; + QString link = m.metaurl(); QString toolTip = ""; if (m.name().isEmpty()) name = m.internal_id(); else name = m.name(); - if (auto meta = m.metadata(); meta != nullptr) { - auto slug = meta->slug.remove(".pw.toml"); - switch (meta->provider) { - case ModPlatform::ResourceProvider::MODRINTH: - link = QString("https://modrinth.com/mod/%1").arg(slug); - break; - case ModPlatform::ResourceProvider::FLAME: - link = QString("https://www.curseforge.com/minecraft/mc-mods/%1").arg(slug); - break; - } - } else if (!m.homeurl().isEmpty()) - link = m.homeurl(); - if (link.isEmpty()) text = name; else { text = "
    " + name + ""; - toolTip = tr("Go to mod's home page"); + toolTip = link; } if (!m.authors().isEmpty()) text += " by " + m.authors().join(", "); -- cgit From 40fbae8ff684b6613ff073ec1992587b38dcdf8c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 11:36:37 +0300 Subject: Fixed links tooltip Signed-off-by: Trial97 --- launcher/ui/widgets/InfoFrame.cpp | 36 +++++++++++++++++++++++------------- launcher/ui/widgets/InfoFrame.h | 2 +- 2 files changed, 24 insertions(+), 14 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 57562a93..24349014 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -34,13 +34,24 @@ * limitations under the License. */ +#include #include +#include #include "InfoFrame.h" #include "ui_InfoFrame.h" #include "ui/dialogs/CustomMessageBox.h" +void setupLinkTooTip(QLabel* label) +{ + QObject::connect(label, &QLabel::linkHovered, [label](const QString& link) { + if (!link.isEmpty() && !link.startsWith("http")) + return; + label->setToolTip(link); + }); +} + InfoFrame::InfoFrame(QWidget* parent) : QFrame(parent), ui(new Ui::InfoFrame) { ui->setupUi(this); @@ -48,6 +59,12 @@ InfoFrame::InfoFrame(QWidget* parent) : QFrame(parent), ui(new Ui::InfoFrame) ui->nameLabel->setHidden(true); ui->licenseLabel->setHidden(true); ui->issueTrackerLabel->setHidden(true); + + setupLinkTooTip(ui->iconLabel); + setupLinkTooTip(ui->descriptionLabel); + setupLinkTooTip(ui->nameLabel); + setupLinkTooTip(ui->licenseLabel); + setupLinkTooTip(ui->issueTrackerLabel); updateHiddenState(); } @@ -66,7 +83,6 @@ void InfoFrame::updateWithMod(Mod const& m) QString text = ""; QString name = ""; QString link = m.metaurl(); - QString toolTip = ""; if (m.name().isEmpty()) name = m.internal_id(); else @@ -76,12 +92,11 @@ void InfoFrame::updateWithMod(Mod const& m) text = name; else { text = "" + name + ""; - toolTip = link; } if (!m.authors().isEmpty()) text += " by " + m.authors().join(", "); - setName(text, toolTip); + setName(text); if (m.description().isEmpty()) { setDescription(QString()); @@ -89,14 +104,14 @@ void InfoFrame::updateWithMod(Mod const& m) setDescription(m.description()); } - setImage(m.icon({64,64})); + setImage(m.icon({ 64, 64 })); auto licenses = m.licenses(); QString licenseText = ""; if (!licenses.empty()) { for (auto l : licenses) { if (!licenseText.isEmpty()) { - licenseText += "\n"; // add newline between licenses + licenseText += "\n"; // add newline between licenses } if (!l.name.isEmpty()) { if (l.url.isEmpty()) { @@ -226,29 +241,24 @@ void InfoFrame::updateHiddenState() } } -void InfoFrame::setName(QString text, QString toolTip) +void InfoFrame::setName(QString text) { if (text.isEmpty()) { ui->nameLabel->setHidden(true); - ui->nameLabel->setToolTip({}); } else { ui->nameLabel->setText(text); ui->nameLabel->setHidden(false); - ui->nameLabel->setToolTip(toolTip); } updateHiddenState(); } void InfoFrame::setDescription(QString text) { - if(text.isEmpty()) - { + if (text.isEmpty()) { ui->descriptionLabel->setHidden(true); updateHiddenState(); return; - } - else - { + } else { ui->descriptionLabel->setHidden(false); updateHiddenState(); } diff --git a/launcher/ui/widgets/InfoFrame.h b/launcher/ui/widgets/InfoFrame.h index b8c7e9a0..d6764baa 100644 --- a/launcher/ui/widgets/InfoFrame.h +++ b/launcher/ui/widgets/InfoFrame.h @@ -52,7 +52,7 @@ class InfoFrame : public QFrame { InfoFrame(QWidget* parent = nullptr); ~InfoFrame() override; - void setName(QString text = {}, QString toolTip = {}); + void setName(QString text = {}); void setDescription(QString text = {}); void setImage(QPixmap img = {}); void setLicense(QString text = {}); -- cgit From fd5b155ee7d796015c84c8b348f384bf21d8328d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 12:24:59 +0300 Subject: Added error message when exporting snapshots with curseforge Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 18 +++++++++++------- launcher/ui/MainWindow.cpp | 9 ++++++++- 2 files changed, 19 insertions(+), 8 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index e73f3de5..e5eeb098 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -409,16 +409,20 @@ QByteArray FlamePackExportTask::generateIndex() // convert all available components to mrpack dependencies if (minecraft != nullptr) version["version"] = minecraft->m_version; - - QJsonObject loader; + QString id; if (quilt != nullptr) - loader["id"] = "quilt-" + quilt->getVersion(); + id = "quilt-" + quilt->getVersion(); else if (fabric != nullptr) - loader["id"] = "fabric-" + fabric->getVersion(); + id = "fabric-" + fabric->getVersion(); else if (forge != nullptr) - loader["id"] = "forge-" + forge->getVersion(); - loader["primary"] = true; - version["modLoaders"] = QJsonArray({ loader }); + id = "forge-" + forge->getVersion(); + version["modLoaders"] = QJsonArray(); + if (!id.isEmpty()) { + QJsonObject loader; + loader["id"] = id; + loader["primary"] = true; + version["modLoaders"] = QJsonArray({ loader }); + } obj["minecraft"] = version; } diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 91809c7b..50eb9e64 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1422,9 +1422,16 @@ void MainWindow::on_actionExportInstanceFlamePack_triggered() if (m_selectedInstance) { auto instance = dynamic_cast(m_selectedInstance.get()); if (instance) { + QString errorMsg; if (instance->getPackProfile()->getComponent("org.quiltmc.quilt-loader")) { + errorMsg = tr("Quilt is currently not supported by CurseForge modpacks."); + } else if (auto cmp = instance->getPackProfile()->getComponent("net.minecraft"); + cmp && cmp->getVersionFile() && cmp->getVersionFile()->type == "snapshot") { + errorMsg = tr("Snapshots are currently not supported by CurseForge modpacks."); + } + if (!errorMsg.isEmpty()) { QMessageBox msgBox; - msgBox.setText(tr("Quilt is currently not supported by CurseForge modpacks.")); + msgBox.setText(errorMsg); msgBox.exec(); return; } -- cgit From 603ed220151345f44a43e14538ea449bae843958 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 25 Jun 2023 10:36:54 +0100 Subject: Replace accidental usages of QAbstractButton::pressed This signal is not usually what you want, and creates an inconsistent experience. Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/ManagedPackPage.cpp | 4 ++-- launcher/ui/pages/modplatform/legacy_ftb/Page.cpp | 4 ++-- launcher/ui/setupwizard/SetupWizard.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp index e0a7314f..d89c5bfc 100644 --- a/launcher/ui/pages/instance/ManagedPackPage.cpp +++ b/launcher/ui/pages/instance/ManagedPackPage.cpp @@ -205,7 +205,7 @@ ModrinthManagedPackPage::ModrinthManagedPackPage(BaseInstance* inst, InstanceWin { Q_ASSERT(inst->isManagedPack()); connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion())); - connect(ui->updateButton, &QPushButton::pressed, this, &ModrinthManagedPackPage::update); + connect(ui->updateButton, &QPushButton::clicked, this, &ModrinthManagedPackPage::update); } // MODRINTH @@ -332,7 +332,7 @@ FlameManagedPackPage::FlameManagedPackPage(BaseInstance* inst, InstanceWindow* i { Q_ASSERT(inst->isManagedPack()); connect(ui->versionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(suggestVersion())); - connect(ui->updateButton, &QPushButton::pressed, this, &FlameManagedPackPage::update); + connect(ui->updateButton, &QPushButton::clicked, this, &FlameManagedPackPage::update); } void FlameManagedPackPage::parseManagedPack() diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp index 98ab8799..b3f6261f 100644 --- a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp +++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp @@ -116,8 +116,8 @@ Page::Page(NewInstanceDialog* dialog, QWidget *parent) connect(ui->thirdPartyPackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onThirdPartyPackSelectionChanged); connect(ui->privatePackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onPrivatePackSelectionChanged); - connect(ui->addPackBtn, &QPushButton::pressed, this, &Page::onAddPackClicked); - connect(ui->removePackBtn, &QPushButton::pressed, this, &Page::onRemovePackClicked); + connect(ui->addPackBtn, &QPushButton::clicked, this, &Page::onAddPackClicked); + connect(ui->removePackBtn, &QPushButton::clicked, this, &Page::onRemovePackClicked); connect(ui->tabWidget, &QTabWidget::currentChanged, this, &Page::onTabChanged); diff --git a/launcher/ui/setupwizard/SetupWizard.cpp b/launcher/ui/setupwizard/SetupWizard.cpp index 3fd9bb23..0a47334f 100644 --- a/launcher/ui/setupwizard/SetupWizard.cpp +++ b/launcher/ui/setupwizard/SetupWizard.cpp @@ -59,7 +59,7 @@ void SetupWizard::pageChanged(int id) { setButtonLayout({QWizard::CustomButton1, QWizard::Stretch, QWizard::BackButton, QWizard::NextButton, QWizard::FinishButton}); auto customButton = button(QWizard::CustomButton1); - connect(customButton, &QAbstractButton::pressed, [&](){ + connect(customButton, &QAbstractButton::clicked, [&](){ auto basePagePtr = getCurrentBasePage(); if(basePagePtr) { -- cgit From 514080653f2a862c6d3b2f1efb279a6707ccfb1c Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 25 Jun 2023 11:56:28 +0100 Subject: Fix unsafe usage of std::optional::value in FlameAPI Signed-off-by: TheKodeToad --- launcher/modplatform/flame/FlameAPI.h | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index a0611957..0a6dc78f 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -77,24 +77,28 @@ class FlameAPI : public NetworkResourceAPI { [[nodiscard]] std::optional getVersionsURL(VersionSearchArgs const& args) const override { - auto mappedModLoader = getMappedModLoader(args.loaders.value()); auto addonId = args.pack.addonId.toString(); - if (args.loaders.value() & Quilt) { - auto overide = ModPlatform::getOverrideDeps(); - auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) { - return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt; - }); - if (over != overide.cend()) { - mappedModLoader = 5; - } - } QString url{ QString("https://api.curseforge.com/v1/mods/%1/files?pageSize=10000&").arg(addonId) }; QStringList get_parameters; if (args.mcVersions.has_value()) get_parameters.append(QString("gameVersion=%1").arg(args.mcVersions.value().front().toString())); - if (args.loaders.has_value()) + + if (args.loaders.has_value()) { + int mappedModLoader = getMappedModLoader(args.loaders.value()); + + if (args.loaders.value() & Quilt) { + auto overide = ModPlatform::getOverrideDeps(); + auto over = std::find_if(overide.cbegin(), overide.cend(), [addonId](auto dep) { + return dep.provider == ModPlatform::ResourceProvider::FLAME && addonId == dep.quilt; + }); + if (over != overide.cend()) { + mappedModLoader = 5; + } + } + get_parameters.append(QString("modLoaderType=%1").arg(mappedModLoader)); + } return url + get_parameters.join('&'); }; -- cgit From d1603f19459a499e5278f38b69222e3f4e0875b4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 14:43:11 +0300 Subject: Made it more similar to mrpack export Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 67 ++++++++++++++++------ launcher/modplatform/flame/FlamePackExportTask.h | 2 + 2 files changed, 51 insertions(+), 18 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index e5eeb098..b14c6eb4 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -37,6 +37,8 @@ #include "tasks/Task.h" const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • \n"; +const QStringList FlamePackExportTask::PREFIXES({ "mods/", "resourcepacks/" }); +const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "zip" }); FlamePackExportTask::FlamePackExportTask(const QString& name, const QString& version, @@ -105,33 +107,62 @@ void FlamePackExportTask::collectHashes() { setAbortable(true); setStatus(tr("Find file hashes...")); - auto mods = mcInstance->loaderModList()->allMods(); + auto allMods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); task.reset(hashing_task); - int totalProgres = mods.count(); + int totalProgres = allMods.count(); setProgress(0, totalProgres); - for (auto* mod : mods) { - if (!mod || mod->type() == ResourceType::FOLDER) { - setProgress(m_progress + 1, totalProgres); + + for (const QFileInfo& file : files) { + const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); + // require sensible file types + if (!std::any_of(PREFIXES.begin(), PREFIXES.end(), [&relative](const QString& prefix) { return relative.startsWith(prefix); })) continue; - } - if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { - resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), - { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), true, - mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") }); - setProgress(m_progress + 1, totalProgres); + if (!std::any_of(FILE_EXTENSIONS.begin(), FILE_EXTENSIONS.end(), [&relative](const QString& extension) { + return relative.endsWith('.' + extension) || relative.endsWith('.' + extension + ".disabled"); + })) + continue; + + if (relative.startsWith("resourcepacks/") && + (relative.endsWith(".zip") || relative.endsWith(".zip.disabled"))) { // is resourcepack + totalProgres++; + auto hash_task = Hashing::createFlameHasher(file.absoluteFilePath()); + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, relative, file, totalProgres](QString hash) { + if (m_state == Task::State::Running) { + setProgress(m_progress + 1, totalProgres); + pendingHashes.insert(hash, { relative, file.absoluteFilePath(), relative.endsWith(".zip") }); + } + }); + connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + hashing_task->addTask(hash_task); continue; } - auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, totalProgres](QString hash) { - if (m_state == Task::State::Running) { + if (auto modIter = std::find_if(allMods.begin(), allMods.end(), [&file](Mod* mod) { return mod->fileinfo() == file; }); + modIter != allMods.end()) { + const Mod* mod = *modIter; + if (!mod || mod->type() == ResourceType::FOLDER) { setProgress(m_progress + 1, totalProgres); - pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled(), true }); + continue; } - }); - connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); - hashing_task->addTask(hash_task); + if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { + resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), + { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), true, + mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") }); + setProgress(m_progress + 1, totalProgres); + continue; + } + + auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, totalProgres](QString hash) { + if (m_state == Task::State::Running) { + setProgress(m_progress + 1, totalProgres); + pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled(), true }); + } + }); + connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + hashing_task->addTask(hash_task); + } } for (const QFileInfo& file : files) { diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index 5c8caa45..b6a6c352 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -42,6 +42,8 @@ class FlamePackExportTask : public Task { private: static const QString TEMPLATE; + static const QStringList PREFIXES; + static const QStringList FILE_EXTENSIONS; // inputs const QString name, version, author; -- cgit From c75ba0f8551e911b72152ebdd8b2fe1f8bd8f64f Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 25 Jun 2023 12:46:07 +0100 Subject: Fix big mistake :iea: Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/InstanceSettingsPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/InstanceSettingsPage.cpp b/launcher/ui/pages/instance/InstanceSettingsPage.cpp index 893fe2a5..2a7c5b27 100644 --- a/launcher/ui/pages/instance/InstanceSettingsPage.cpp +++ b/launcher/ui/pages/instance/InstanceSettingsPage.cpp @@ -85,7 +85,7 @@ void InstanceSettingsPage::globalSettingsButtonClicked(bool) case 0: APPLICATION->ShowGlobalSettings(this, "java-settings"); return; - case 1: + case 2: APPLICATION->ShowGlobalSettings(this, "custom-commands"); return; default: -- cgit From 02b628653b4d2574766e1148ebd71b426b52a5d2 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 25 Jun 2023 13:42:45 +0100 Subject: Fix markdown header Signed-off-by: TheKodeToad --- launcher/CMakeLists.txt | 1 + launcher/Markdown.cpp | 31 +++++++++++++++++++++++++++++++ launcher/Markdown.h | 12 +----------- 3 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 launcher/Markdown.cpp (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index c10064c0..3cc8b6e1 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -684,6 +684,7 @@ SET(LAUNCHER_SOURCES VersionProxyModel.h VersionProxyModel.cpp Markdown.h + Markdown.cpp # Super secret! KonamiCode.h diff --git a/launcher/Markdown.cpp b/launcher/Markdown.cpp new file mode 100644 index 00000000..426067bf --- /dev/null +++ b/launcher/Markdown.cpp @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2023 Joshua Goins + * + * 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 . + */ + +#include "Markdown.h" + +QString markdownToHTML(const QString& markdown) +{ + const QByteArray markdownData = markdown.toUtf8(); + char* buffer = cmark_markdown_to_html(markdownData.constData(), markdownData.length(), CMARK_OPT_NOBREAKS | CMARK_OPT_UNSAFE); + + QString htmlStr(buffer); + + free(buffer); + + return htmlStr; +} \ No newline at end of file diff --git a/launcher/Markdown.h b/launcher/Markdown.h index f115dd57..6b261e60 100644 --- a/launcher/Markdown.h +++ b/launcher/Markdown.h @@ -21,14 +21,4 @@ #include #include -static QString markdownToHTML(const QString& markdown) -{ - const QByteArray markdownData = markdown.toUtf8(); - char* buffer = cmark_markdown_to_html(markdownData.constData(), markdownData.length(), CMARK_OPT_NOBREAKS | CMARK_OPT_UNSAFE); - - QString htmlStr(buffer); - - free(buffer); - - return htmlStr; -} \ No newline at end of file +QString markdownToHTML(const QString& markdown); \ No newline at end of file -- cgit From 953a2590e27954a3b1d163224bd343bb75a62b69 Mon Sep 17 00:00:00 2001 From: Leo Date: Sun, 25 Jun 2023 10:11:58 -0300 Subject: Add fixme comment for no SSD detection Co-authored-by: Sefa Eyeoglu Signed-off-by: Leo --- launcher/ui/MainWindow.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 9b8db1ae..7e2c4acf 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -221,6 +221,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi setInstanceActionsEnabled(false); // add a close button at the end of the main toolbar when running on gamescope / steam deck + // FIXME: detect if we don't have server side decorations instead if (qgetenv("XDG_CURRENT_DESKTOP") == "gamescope") { ui->mainToolBar->addAction(ui->actionCloseWindow); } -- cgit From fa3a46498f7fe4a7d6e26558c03b0485126b377c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 16:23:50 +0300 Subject: Removed dupliacte code Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index b14c6eb4..cbb57afa 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -165,21 +165,6 @@ void FlamePackExportTask::collectHashes() } } - for (const QFileInfo& file : files) { - const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); - if (!relative.endsWith(".zip") || !relative.startsWith("resourcepacks/")) - continue; - totalProgres++; - auto hash_task = Hashing::createFlameHasher(file.absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, relative, file, totalProgres](QString hash) { - if (m_state == Task::State::Running) { - setProgress(m_progress + 1, totalProgres); - pendingHashes.insert(hash, { relative, file.absoluteFilePath(), true }); - } - }); - connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); - hashing_task->addTask(hash_task); - } connect(hashing_task.get(), &Task::succeeded, this, &FlamePackExportTask::makeApiRequest); connect(hashing_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); hashing_task->start(); -- cgit From 8ade44c9a3b186fb5ab19d9802a4d7b4187b7258 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 25 Jun 2023 14:39:45 +0100 Subject: Simplify Signed-off-by: TheKodeToad --- launcher/modplatform/flame/FlamePackExportTask.cpp | 3 --- launcher/modplatform/flame/FlamePackExportTask.h | 1 - 2 files changed, 4 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index cbb57afa..1460a4c3 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -37,7 +37,6 @@ #include "tasks/Task.h" const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • \n"; -const QStringList FlamePackExportTask::PREFIXES({ "mods/", "resourcepacks/" }); const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "zip" }); FlamePackExportTask::FlamePackExportTask(const QString& name, @@ -116,8 +115,6 @@ void FlamePackExportTask::collectHashes() for (const QFileInfo& file : files) { const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); // require sensible file types - if (!std::any_of(PREFIXES.begin(), PREFIXES.end(), [&relative](const QString& prefix) { return relative.startsWith(prefix); })) - continue; if (!std::any_of(FILE_EXTENSIONS.begin(), FILE_EXTENSIONS.end(), [&relative](const QString& extension) { return relative.endsWith('.' + extension) || relative.endsWith('.' + extension + ".disabled"); })) diff --git a/launcher/modplatform/flame/FlamePackExportTask.h b/launcher/modplatform/flame/FlamePackExportTask.h index b6a6c352..3dee0a7e 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.h +++ b/launcher/modplatform/flame/FlamePackExportTask.h @@ -42,7 +42,6 @@ class FlamePackExportTask : public Task { private: static const QString TEMPLATE; - static const QStringList PREFIXES; static const QStringList FILE_EXTENSIONS; // inputs -- cgit From 288ea3d19b6edbd2b4570408e71e635df0d7abfe Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 25 Jun 2023 14:52:33 +0100 Subject: Remove metaurl function Signed-off-by: TheKodeToad --- launcher/minecraft/mod/Mod.cpp | 7 ------- launcher/minecraft/mod/Mod.h | 1 - 2 files changed, 8 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index d5b96bad..e613ddeb 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -166,13 +166,6 @@ auto Mod::homeurl() const -> QString return details().homeurl; } -auto Mod::metaurl() const -> QString -{ - if (metadata() == nullptr) - return homeurl(); - return ModPlatform::getMetaURL(metadata()->provider, metadata()->project_id); -} - auto Mod::description() const -> QString { return details().description; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index d6272f4d..d4e419f4 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -70,7 +70,6 @@ public: auto provider() const -> std::optional; auto licenses() const -> const QList&; auto issueTracker() const -> QString; - auto metaurl() const -> QString; /** Get the intneral path to the mod's icon file*/ QString iconPath() const { return m_local_details.icon_file; }; -- cgit From 4745ab64cdf073b781515f43f7b10cd7f776078b Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 25 Jun 2023 15:02:25 +0100 Subject: Deduplicate launcher icon Signed-off-by: TheKodeToad --- launcher/resources/OSX/OSX.qrc | 1 - launcher/resources/OSX/scalable/launcher.svg | 57 ---------------------- .../resources/breeze_dark/scalable/launcher.svg | 57 ---------------------- launcher/resources/flat/flat.qrc | 1 - launcher/resources/flat/scalable/launcher.svg | 57 ---------------------- launcher/resources/flat_white/flat_white.qrc | 1 - .../resources/flat_white/scalable/launcher.svg | 57 ---------------------- launcher/resources/iOS/iOS.qrc | 1 - launcher/resources/iOS/scalable/launcher.svg | 57 ---------------------- launcher/resources/pe_blue/pe_blue.qrc | 1 - launcher/resources/pe_blue/scalable/launcher.svg | 57 ---------------------- launcher/resources/pe_colored/pe_colored.qrc | 1 - .../resources/pe_colored/scalable/launcher.svg | 57 ---------------------- launcher/resources/pe_dark/pe_dark.qrc | 1 - launcher/resources/pe_dark/scalable/launcher.svg | 57 ---------------------- launcher/resources/pe_light/pe_light.qrc | 1 - launcher/resources/pe_light/scalable/launcher.svg | 57 ---------------------- 17 files changed, 521 deletions(-) delete mode 100644 launcher/resources/OSX/scalable/launcher.svg delete mode 100644 launcher/resources/breeze_dark/scalable/launcher.svg delete mode 100644 launcher/resources/flat/scalable/launcher.svg delete mode 100644 launcher/resources/flat_white/scalable/launcher.svg delete mode 100644 launcher/resources/iOS/scalable/launcher.svg delete mode 100644 launcher/resources/pe_blue/scalable/launcher.svg delete mode 100644 launcher/resources/pe_colored/scalable/launcher.svg delete mode 100644 launcher/resources/pe_dark/scalable/launcher.svg delete mode 100644 launcher/resources/pe_light/scalable/launcher.svg (limited to 'launcher') diff --git a/launcher/resources/OSX/OSX.qrc b/launcher/resources/OSX/OSX.qrc index 9d4511d1..49f56b0c 100644 --- a/launcher/resources/OSX/OSX.qrc +++ b/launcher/resources/OSX/OSX.qrc @@ -16,7 +16,6 @@ scalable/jarmods.svg scalable/java.svg scalable/language.svg - scalable/launcher.svg scalable/loadermods.svg scalable/log.svg scalable/minecraft.svg diff --git a/launcher/resources/OSX/scalable/launcher.svg b/launcher/resources/OSX/scalable/launcher.svg deleted file mode 100644 index aeee8433..00000000 --- a/launcher/resources/OSX/scalable/launcher.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - Prism Launcher Logo - - - - - - - - - - - - - - - - - - - - - - - Prism Launcher Logo - 19/10/2022 - - - Prism Launcher - - - - - AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke - - - https://github.com/PrismLauncher/PrismLauncher - - - Prism Launcher - - - - - - - - - - - - - - - diff --git a/launcher/resources/breeze_dark/scalable/launcher.svg b/launcher/resources/breeze_dark/scalable/launcher.svg deleted file mode 100644 index aeee8433..00000000 --- a/launcher/resources/breeze_dark/scalable/launcher.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - Prism Launcher Logo - - - - - - - - - - - - - - - - - - - - - - - Prism Launcher Logo - 19/10/2022 - - - Prism Launcher - - - - - AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke - - - https://github.com/PrismLauncher/PrismLauncher - - - Prism Launcher - - - - - - - - - - - - - - - diff --git a/launcher/resources/flat/flat.qrc b/launcher/resources/flat/flat.qrc index cadf8736..2fd5daef 100644 --- a/launcher/resources/flat/flat.qrc +++ b/launcher/resources/flat/flat.qrc @@ -18,7 +18,6 @@ scalable/jarmods.svg scalable/java.svg scalable/language.svg - scalable/launcher.svg scalable/loadermods.svg scalable/log.svg scalable/minecraft.svg diff --git a/launcher/resources/flat/scalable/launcher.svg b/launcher/resources/flat/scalable/launcher.svg deleted file mode 100644 index aeee8433..00000000 --- a/launcher/resources/flat/scalable/launcher.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - Prism Launcher Logo - - - - - - - - - - - - - - - - - - - - - - - Prism Launcher Logo - 19/10/2022 - - - Prism Launcher - - - - - AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke - - - https://github.com/PrismLauncher/PrismLauncher - - - Prism Launcher - - - - - - - - - - - - - - - diff --git a/launcher/resources/flat_white/flat_white.qrc b/launcher/resources/flat_white/flat_white.qrc index 2701462f..a1c940da 100644 --- a/launcher/resources/flat_white/flat_white.qrc +++ b/launcher/resources/flat_white/flat_white.qrc @@ -18,7 +18,6 @@ scalable/jarmods.svg scalable/java.svg scalable/language.svg - scalable/launcher.svg scalable/loadermods.svg scalable/log.svg scalable/minecraft.svg diff --git a/launcher/resources/flat_white/scalable/launcher.svg b/launcher/resources/flat_white/scalable/launcher.svg deleted file mode 100644 index aeee8433..00000000 --- a/launcher/resources/flat_white/scalable/launcher.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - Prism Launcher Logo - - - - - - - - - - - - - - - - - - - - - - - Prism Launcher Logo - 19/10/2022 - - - Prism Launcher - - - - - AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke - - - https://github.com/PrismLauncher/PrismLauncher - - - Prism Launcher - - - - - - - - - - - - - - - diff --git a/launcher/resources/iOS/iOS.qrc b/launcher/resources/iOS/iOS.qrc index 0b79efb2..9b8d84f5 100644 --- a/launcher/resources/iOS/iOS.qrc +++ b/launcher/resources/iOS/iOS.qrc @@ -16,7 +16,6 @@ scalable/jarmods.svg scalable/java.svg scalable/language.svg - scalable/launcher.svg scalable/loadermods.svg scalable/log.svg scalable/minecraft.svg diff --git a/launcher/resources/iOS/scalable/launcher.svg b/launcher/resources/iOS/scalable/launcher.svg deleted file mode 100644 index aeee8433..00000000 --- a/launcher/resources/iOS/scalable/launcher.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - Prism Launcher Logo - - - - - - - - - - - - - - - - - - - - - - - Prism Launcher Logo - 19/10/2022 - - - Prism Launcher - - - - - AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke - - - https://github.com/PrismLauncher/PrismLauncher - - - Prism Launcher - - - - - - - - - - - - - - - diff --git a/launcher/resources/pe_blue/pe_blue.qrc b/launcher/resources/pe_blue/pe_blue.qrc index 1b2b6291..da45ef9a 100644 --- a/launcher/resources/pe_blue/pe_blue.qrc +++ b/launcher/resources/pe_blue/pe_blue.qrc @@ -16,7 +16,6 @@ scalable/jarmods.svg scalable/java.svg scalable/language.svg - scalable/launcher.svg scalable/loadermods.svg scalable/log.svg scalable/minecraft.svg diff --git a/launcher/resources/pe_blue/scalable/launcher.svg b/launcher/resources/pe_blue/scalable/launcher.svg deleted file mode 100644 index aeee8433..00000000 --- a/launcher/resources/pe_blue/scalable/launcher.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - Prism Launcher Logo - - - - - - - - - - - - - - - - - - - - - - - Prism Launcher Logo - 19/10/2022 - - - Prism Launcher - - - - - AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke - - - https://github.com/PrismLauncher/PrismLauncher - - - Prism Launcher - - - - - - - - - - - - - - - diff --git a/launcher/resources/pe_colored/pe_colored.qrc b/launcher/resources/pe_colored/pe_colored.qrc index 084fca93..ba5bd44f 100644 --- a/launcher/resources/pe_colored/pe_colored.qrc +++ b/launcher/resources/pe_colored/pe_colored.qrc @@ -16,7 +16,6 @@ scalable/jarmods.svg scalable/java.svg scalable/language.svg - scalable/launcher.svg scalable/loadermods.svg scalable/log.svg scalable/minecraft.svg diff --git a/launcher/resources/pe_colored/scalable/launcher.svg b/launcher/resources/pe_colored/scalable/launcher.svg deleted file mode 100644 index aeee8433..00000000 --- a/launcher/resources/pe_colored/scalable/launcher.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - Prism Launcher Logo - - - - - - - - - - - - - - - - - - - - - - - Prism Launcher Logo - 19/10/2022 - - - Prism Launcher - - - - - AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke - - - https://github.com/PrismLauncher/PrismLauncher - - - Prism Launcher - - - - - - - - - - - - - - - diff --git a/launcher/resources/pe_dark/pe_dark.qrc b/launcher/resources/pe_dark/pe_dark.qrc index 5c49b75a..2bfec42c 100644 --- a/launcher/resources/pe_dark/pe_dark.qrc +++ b/launcher/resources/pe_dark/pe_dark.qrc @@ -16,7 +16,6 @@ scalable/jarmods.svg scalable/java.svg scalable/language.svg - scalable/launcher.svg scalable/loadermods.svg scalable/log.svg scalable/minecraft.svg diff --git a/launcher/resources/pe_dark/scalable/launcher.svg b/launcher/resources/pe_dark/scalable/launcher.svg deleted file mode 100644 index aeee8433..00000000 --- a/launcher/resources/pe_dark/scalable/launcher.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - Prism Launcher Logo - - - - - - - - - - - - - - - - - - - - - - - Prism Launcher Logo - 19/10/2022 - - - Prism Launcher - - - - - AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke - - - https://github.com/PrismLauncher/PrismLauncher - - - Prism Launcher - - - - - - - - - - - - - - - diff --git a/launcher/resources/pe_light/pe_light.qrc b/launcher/resources/pe_light/pe_light.qrc index a8e3f157..25d5da73 100644 --- a/launcher/resources/pe_light/pe_light.qrc +++ b/launcher/resources/pe_light/pe_light.qrc @@ -16,7 +16,6 @@ scalable/jarmods.svg scalable/java.svg scalable/language.svg - scalable/launcher.svg scalable/loadermods.svg scalable/log.svg scalable/minecraft.svg diff --git a/launcher/resources/pe_light/scalable/launcher.svg b/launcher/resources/pe_light/scalable/launcher.svg deleted file mode 100644 index aeee8433..00000000 --- a/launcher/resources/pe_light/scalable/launcher.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - Prism Launcher Logo - - - - - - - - - - - - - - - - - - - - - - - Prism Launcher Logo - 19/10/2022 - - - Prism Launcher - - - - - AutiOne, Boba, ely, Fulmine, gon sawa, Pankakes, tobimori, Zeke - - - https://github.com/PrismLauncher/PrismLauncher - - - Prism Launcher - - - - - - - - - - - - - - - -- cgit From d344ffe37047037bd3bca070557a49fbfadcb361 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 17:50:56 +0300 Subject: Removed some setProgress calls Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index cbb57afa..c781ece5 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -110,8 +110,7 @@ void FlamePackExportTask::collectHashes() auto allMods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); task.reset(hashing_task); - int totalProgres = allMods.count(); - setProgress(0, totalProgres); + int totalProgres = 0; for (const QFileInfo& file : files) { const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); @@ -142,17 +141,16 @@ void FlamePackExportTask::collectHashes() modIter != allMods.end()) { const Mod* mod = *modIter; if (!mod || mod->type() == ResourceType::FOLDER) { - setProgress(m_progress + 1, totalProgres); continue; } if (mod->metadata() && mod->metadata()->provider == ModPlatform::ResourceProvider::FLAME) { resolvedFiles.insert(mod->fileinfo().absoluteFilePath(), { mod->metadata()->project_id.toInt(), mod->metadata()->file_id.toInt(), mod->enabled(), true, mod->metadata()->name, mod->metadata()->slug, mod->authors().join(", ") }); - setProgress(m_progress + 1, totalProgres); continue; } + totalProgres++; auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, totalProgres](QString hash) { if (m_state == Task::State::Running) { @@ -209,9 +207,7 @@ void FlamePackExportTask::makeApiRequest() return; } - size_t progress = 0; for (auto match : data_arr) { - setProgress(progress++, data_arr.count()); auto match_obj = Json::ensureObject(match, {}); auto file_obj = Json::ensureObject(match_obj, "file", {}); @@ -284,9 +280,7 @@ void FlamePackExportTask::getProjectsInfo() else entries = Json::requireArray(Json::requireObject(doc), "data"); - size_t progress = 0; for (auto entry : entries) { - setProgress(progress++, entries.count()); auto entry_obj = Json::requireObject(entry); try { -- cgit From 87155e346c33288fccb68c3b9029a11b658395b2 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 19:44:18 +0300 Subject: Complicated a little task progress Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 54 ++++++++++++++++------ 1 file changed, 40 insertions(+), 14 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index dfad364f..13308b50 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -58,7 +58,7 @@ FlamePackExportTask::FlamePackExportTask(const QString& name, void FlamePackExportTask::executeTask() { setStatus(tr("Searching for files...")); - setProgress(0, 0); + setProgress(0, 5); collectFiles(); } @@ -106,11 +106,10 @@ void FlamePackExportTask::collectHashes() { setAbortable(true); setStatus(tr("Find file hashes...")); + setProgress(1, 5); auto allMods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); task.reset(hashing_task); - int totalProgres = 0; - for (const QFileInfo& file : files) { const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); // require sensible file types @@ -121,11 +120,9 @@ void FlamePackExportTask::collectHashes() if (relative.startsWith("resourcepacks/") && (relative.endsWith(".zip") || relative.endsWith(".zip.disabled"))) { // is resourcepack - totalProgres++; auto hash_task = Hashing::createFlameHasher(file.absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, relative, file, totalProgres](QString hash) { + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, relative, file](QString hash) { if (m_state == Task::State::Running) { - setProgress(m_progress + 1, totalProgres); pendingHashes.insert(hash, { relative, file.absoluteFilePath(), relative.endsWith(".zip") }); } }); @@ -147,11 +144,9 @@ void FlamePackExportTask::collectHashes() continue; } - totalProgres++; auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod, totalProgres](QString hash) { + connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { if (m_state == Task::State::Running) { - setProgress(m_progress + 1, totalProgres); pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled(), true }); } }); @@ -159,9 +154,28 @@ void FlamePackExportTask::collectHashes() hashing_task->addTask(hash_task); } } + auto step_progress = std::make_shared(); + connect(hashing_task.get(), &Task::finished, this, [this, step_progress] { + step_progress->state = TaskStepState::Succeeded; + stepProgress(*step_progress); + }); connect(hashing_task.get(), &Task::succeeded, this, &FlamePackExportTask::makeApiRequest); - connect(hashing_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + connect(hashing_task.get(), &Task::failed, this, [this, step_progress](QString reason) { + step_progress->state = TaskStepState::Failed; + stepProgress(*step_progress); + emitFailed(reason); + }); + connect(hashing_task.get(), &Task::stepProgress, this, &FlamePackExportTask::propogateStepProgress); + + connect(hashing_task.get(), &Task::progress, this, [this, step_progress](qint64 current, qint64 total) { + step_progress->update(current, total); + stepProgress(*step_progress); + }); + connect(hashing_task.get(), &Task::status, this, [this, step_progress](QString status) { + step_progress->status = status; + stepProgress(*step_progress); + }); hashing_task->start(); } @@ -173,6 +187,7 @@ void FlamePackExportTask::makeApiRequest() } setStatus(tr("Find versions for hashes...")); + setProgress(2, 5); auto response = std::make_shared(); QList fingerprints; @@ -186,7 +201,7 @@ void FlamePackExportTask::makeApiRequest() QJsonParseError parse_error{}; QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from Modrinth::CurrentVersions at " << parse_error.offset + qWarning() << "Error while parsing JSON response from CurseForge::CurrentVersions at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << *response; @@ -241,6 +256,7 @@ void FlamePackExportTask::makeApiRequest() void FlamePackExportTask::getProjectsInfo() { setStatus(tr("Find project info from CurseForge...")); + setProgress(3, 5); QList addonIds; for (auto resolved : resolvedFiles) { if (resolved.slug.isEmpty()) { @@ -264,9 +280,10 @@ void FlamePackExportTask::getProjectsInfo() QJsonParseError parse_error{}; auto doc = QJsonDocument::fromJson(*response, &parse_error); if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from Modrinth projects task at " << parse_error.offset + qWarning() << "Error while parsing JSON response from CurseForge projects task at " << parse_error.offset << " reason: " << parse_error.errorString(); qWarning() << *response; + failed(parse_error.errorString()); return; } @@ -317,6 +334,7 @@ void FlamePackExportTask::getProjectsInfo() void FlamePackExportTask::buildZip() { setStatus(tr("Adding files...")); + setProgress(4, 5); buildZipFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { QuaZip zip(output); @@ -352,14 +370,19 @@ void FlamePackExportTask::buildZip() content = "
      " + content + "
    "; modlist.write(content.toUtf8()); + auto step_progress = std::make_shared(); + size_t progress = 0; for (const QFileInfo& file : files) { if (buildZipFuture.isCanceled()) { QFile::remove(output); + step_progress->state = TaskStepState::Failed; + stepProgress(*step_progress); return BuildZipResult(); } + step_progress->update(progress, files.length()); + stepProgress(*step_progress); - setProgress(progress, files.length()); const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); if (!resolvedFiles.contains(file.absoluteFilePath()) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) { @@ -373,9 +396,12 @@ void FlamePackExportTask::buildZip() if (zip.getZipError() != 0) { QFile::remove(output); + step_progress->state = TaskStepState::Failed; + stepProgress(*step_progress); return BuildZipResult(tr("A zip error occurred")); } - + step_progress->state = TaskStepState::Succeeded; + stepProgress(*step_progress); return BuildZipResult(); }); connect(&buildZipWatcher, &QFutureWatcher::finished, this, &FlamePackExportTask::finish); -- cgit From 6d0e255ca18b1934d6eb514b6324cde67bb87d60 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 25 Jun 2023 22:00:33 +0300 Subject: fix: Page container extra info set on logs page Signed-off-by: Trial97 --- launcher/ui/pages/BasePage.h | 2 +- launcher/ui/pages/instance/ExternalResourcesPage.cpp | 2 +- launcher/ui/widgets/PageContainer.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/BasePage.h b/launcher/ui/pages/BasePage.h index 5537c28f..dc2bde99 100644 --- a/launcher/ui/pages/BasePage.h +++ b/launcher/ui/pages/BasePage.h @@ -44,7 +44,7 @@ class BasePage { public: - using updateExtraInfoFunc = std::function; + using updateExtraInfoFunc = std::function; virtual ~BasePage() {} virtual QString id() const = 0; virtual QString displayName() const = 0; diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index 8e5226ef..173bcb66 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -83,7 +83,7 @@ ExternalResourcesPage::ExternalResourcesPage(BaseInstance* instance, std::shared connect(selection_model, &QItemSelectionModel::currentChanged, this, &ExternalResourcesPage::current); auto updateExtra = [this]() { if (updateExtraInfo) - updateExtraInfo(extraHeaderInfoString()); + updateExtraInfo(id(), extraHeaderInfoString()); }; connect(selection_model, &QItemSelectionModel::selectionChanged, this, updateExtra); connect(model.get(), &ResourceFolderModel::updateFinished, this, updateExtra); diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp index 34df42ec..b98c9796 100644 --- a/launcher/ui/widgets/PageContainer.cpp +++ b/launcher/ui/widgets/PageContainer.cpp @@ -93,8 +93,8 @@ PageContainer::PageContainer(BasePageProvider *pageProvider, QString defaultId, page->listIndex = counter; page->setParentContainer(this); counter++; - page->updateExtraInfo = [this](QString info) { - if (m_currentPage) + page->updateExtraInfo = [this](QString id, QString info) { + if (m_currentPage && id == m_currentPage->id()) m_header->setText(m_currentPage->displayName() + info); }; } -- cgit From 8bebd7f042fc912dedb652c613a76a346c29a38f Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Mon, 26 Jun 2023 01:18:55 +0100 Subject: Generate special signature :sparkles: composed of multiple elements instead of relying on timestamp for Java version cache invalidation Signed-off-by: TheKodeToad --- launcher/Application.cpp | 2 +- launcher/launch/steps/CheckJava.cpp | 15 ++++++++++----- launcher/launch/steps/CheckJava.h | 2 +- launcher/minecraft/MinecraftInstance.cpp | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) (limited to 'launcher') diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 724e6e44..1d97a5f2 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -594,7 +594,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // Java Settings m_settings->registerSetting("JavaPath", ""); - m_settings->registerSetting("JavaTimestamp", 0); + m_settings->registerSetting("JavaSignature", ""); m_settings->registerSetting("JavaArchitecture", ""); m_settings->registerSetting("JavaRealArchitecture", ""); m_settings->registerSetting("JavaVersion", ""); diff --git a/launcher/launch/steps/CheckJava.cpp b/launcher/launch/steps/CheckJava.cpp index f0187586..7d697ba9 100644 --- a/launcher/launch/steps/CheckJava.cpp +++ b/launcher/launch/steps/CheckJava.cpp @@ -81,15 +81,20 @@ void CheckJava::executeTask() } QFileInfo javaInfo(realJavaPath); - qlonglong javaUnixTime = javaInfo.lastModified().toMSecsSinceEpoch(); - auto storedUnixTime = settings->get("JavaTimestamp").toLongLong(); + qint64 javaUnixTime = javaInfo.lastModified().toMSecsSinceEpoch(); + auto storedSignature = settings->get("JavaSignature").toString(); auto storedArchitecture = settings->get("JavaArchitecture").toString(); auto storedRealArchitecture = settings->get("JavaRealArchitecture").toString(); auto storedVersion = settings->get("JavaVersion").toString(); auto storedVendor = settings->get("JavaVendor").toString(); - m_javaUnixTime = javaUnixTime; + + QCryptographicHash hash(QCryptographicHash::Sha1); + hash.addData(QByteArray::number(javaUnixTime)); + hash.addData(m_javaPath.toUtf8()); + m_javaSignature = hash.result().toHex(); + // if timestamps are not the same, or something is missing, check! - if (javaUnixTime != storedUnixTime || storedVersion.size() == 0 + if (m_javaSignature != storedSignature || storedVersion.size() == 0 || storedArchitecture.size() == 0 || storedRealArchitecture.size() == 0 || storedVendor.size() == 0) { @@ -140,7 +145,7 @@ void CheckJava::checkJavaFinished(JavaCheckResult result) instance->settings()->set("JavaArchitecture", result.mojangPlatform); instance->settings()->set("JavaRealArchitecture", result.realPlatform); instance->settings()->set("JavaVendor", result.javaVendor); - instance->settings()->set("JavaTimestamp", m_javaUnixTime); + instance->settings()->set("JavaSignature", m_javaSignature); emitSucceeded(); return; } diff --git a/launcher/launch/steps/CheckJava.h b/launcher/launch/steps/CheckJava.h index d084b132..bbf06b7c 100644 --- a/launcher/launch/steps/CheckJava.h +++ b/launcher/launch/steps/CheckJava.h @@ -40,6 +40,6 @@ private: private: QString m_javaPath; - qlonglong m_javaUnixTime; + QString m_javaSignature; JavaCheckerPtr m_JavaChecker; }; diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index f8ed5214..aab930de 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -148,7 +148,7 @@ void MinecraftInstance::loadSpecificSettings() m_settings->registerOverride(global_settings->getSetting("IgnoreJavaCompatibility"), javaOrLocation); // special! - m_settings->registerPassthrough(global_settings->getSetting("JavaTimestamp"), javaOrLocation); + m_settings->registerPassthrough(global_settings->getSetting("JavaSignature"), javaOrLocation); m_settings->registerPassthrough(global_settings->getSetting("JavaArchitecture"), javaOrLocation); m_settings->registerPassthrough(global_settings->getSetting("JavaRealArchitecture"), javaOrLocation); m_settings->registerPassthrough(global_settings->getSetting("JavaVersion"), javaOrLocation); -- cgit From dffffc784e0f9d250613a879c1ebe017b782cf77 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 26 Jun 2023 22:33:10 +0300 Subject: Removed unused files Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 2 - launcher/mojang/PackageManifest.cpp | 427 ------------------------------------ launcher/mojang/PackageManifest.h | 171 --------------- tests/CMakeLists.txt | 3 - tests/PackageManifest_test.cpp | 343 ----------------------------- 5 files changed, 946 deletions(-) delete mode 100644 launcher/mojang/PackageManifest.cpp delete mode 100644 launcher/mojang/PackageManifest.h delete mode 100644 tests/PackageManifest_test.cpp (limited to 'launcher') diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 9bad2a67..6ca31d46 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -377,8 +377,6 @@ set(MINECRAFT_SOURCES minecraft/services/SkinDelete.cpp minecraft/services/SkinDelete.h - mojang/PackageManifest.h - mojang/PackageManifest.cpp minecraft/Agent.h) # the screenshots feature diff --git a/launcher/mojang/PackageManifest.cpp b/launcher/mojang/PackageManifest.cpp deleted file mode 100644 index b3dfd7fc..00000000 --- a/launcher/mojang/PackageManifest.cpp +++ /dev/null @@ -1,427 +0,0 @@ -#include "PackageManifest.h" -#include -#include -#include -#include -#include - -#ifndef Q_OS_WIN32 -#include -#include -#include -#endif - -namespace mojang_files { - -const Hash hash_of_empty_string = "da39a3ee5e6b4b0d3255bfef95601890afd80709"; - -int Path::compare(const Path& rhs) const -{ - auto left_cursor = begin(); - auto left_end = end(); - auto right_cursor = rhs.begin(); - auto right_end = rhs.end(); - - while (left_cursor != left_end && right_cursor != right_end) - { - if(*left_cursor < *right_cursor) - { - return -1; - } - else if(*left_cursor > *right_cursor) - { - return 1; - } - left_cursor++; - right_cursor++; - } - - if(left_cursor == left_end) - { - if(right_cursor == right_end) - { - return 0; - } - return -1; - } - return 1; -} - -void Package::addFile(const Path& path, const File& file) { - addFolder(path.parent_path()); - files[path] = file; -} - -void Package::addFolder(Path folder) { - if(!folder.has_parent_path()) { - return; - } - do { - folders.insert(folder); - folder = folder.parent_path(); - } while(folder.has_parent_path()); -} - -void Package::addLink(const Path& path, const Path& target) { - addFolder(path.parent_path()); - symlinks[path] = target; -} - -void Package::addSource(const FileSource& source) { - sources[source.hash] = source; -} - - -namespace { -void fromJson(QJsonDocument & doc, Package & out) { - std::set seen_paths; - if (!doc.isObject()) - { - throw JSONValidationError("file manifest is not an object"); - } - QJsonObject root = doc.object(); - - auto filesObj = Json::ensureObject(root, "files"); - auto iter = filesObj.begin(); - while (iter != filesObj.end()) - { - Path objectPath = Path(iter.key()); - auto value = iter.value(); - iter++; - if(seen_paths.count(objectPath)) { - throw JSONValidationError("duplicate path inside manifest, the manifest is invalid"); - } - if (!value.isObject()) - { - throw JSONValidationError("file entry inside manifest is not an an object"); - } - seen_paths.insert(objectPath); - - auto fileObject = value.toObject(); - auto type = Json::requireString(fileObject, "type"); - if(type == "directory") { - out.addFolder(objectPath); - continue; - } - else if(type == "file") { - FileSource bestSource; - File file; - file.executable = Json::ensureBoolean(fileObject, QString("executable"), false); - auto downloads = Json::requireObject(fileObject, "downloads"); - for(auto iter2 = downloads.begin(); iter2 != downloads.end(); iter2++) { - FileSource source; - - auto downloadObject = Json::requireObject(iter2.value()); - source.hash = Json::requireString(downloadObject, "sha1"); - source.size = Json::requireInteger(downloadObject, "size"); - source.url = Json::requireString(downloadObject, "url"); - - auto compression = iter2.key(); - if(compression == "raw") { - file.hash = source.hash; - file.size = source.size; - source.compression = Compression::Raw; - } - else if (compression == "lzma") { - source.compression = Compression::Lzma; - } - else { - continue; - } - bestSource.upgrade(source); - } - if(bestSource.isBad()) { - throw JSONValidationError("No valid compression method for file " + iter.key()); - } - out.addFile(objectPath, file); - out.addSource(bestSource); - } - else if(type == "link") { - auto target = Json::requireString(fileObject, "target"); - out.symlinks[objectPath] = target; - out.addLink(objectPath, target); - } - else { - throw JSONValidationError("Invalid item type in manifest: " + type); - } - } - // make sure the containing folder exists - out.folders.insert(Path()); -} -} - -Package Package::fromManifestContents(const QByteArray& contents) -{ - Package out; - try - { - auto doc = Json::requireDocument(contents, "Manifest"); - fromJson(doc, out); - return out; - } - catch (const Exception &e) - { - qDebug() << QString("Unable to parse manifest: %1").arg(e.cause()); - out.valid = false; - return out; - } -} - -Package Package::fromManifestFile(const QString & filename) { - Package out; - try - { - auto doc = Json::requireDocument(filename, filename); - fromJson(doc, out); - return out; - } - catch (const Exception &e) - { - qDebug() << QString("Unable to parse manifest file %1: %2").arg(filename, e.cause()); - out.valid = false; - return out; - } -} - -#ifndef Q_OS_WIN32 - -#include -#include -#include - -namespace { -// FIXME: Qt obscures symlink targets by making them absolute. that is useless. this is the workaround - we do it ourselves -bool actually_read_symlink_target(const QString & filepath, Path & out) -{ - struct ::stat st; - // FIXME: here, we assume the native filesystem encoding. May the Gods have mercy upon our Souls. - QByteArray nativePath = filepath.toUtf8(); - const char * filepath_cstr = nativePath.data(); - - if (lstat(filepath_cstr, &st) != 0) - { - return false; - } - - auto size = st.st_size ? st.st_size + 1 : PATH_MAX; - std::string temp(size, '\0'); - // because we don't realiably know how long the damn thing actually is, we loop and expand. POSIX is naff - do - { - auto link_length = ::readlink(filepath_cstr, &temp[0], temp.size()); - if(link_length == -1) - { - return false; - } - if(std::string::size_type(link_length) < temp.size()) - { - // buffer was long enough and we managed to read the link target. RETURN here. - temp.resize(link_length); - out = Path(QString::fromUtf8(temp.c_str())); - return true; - } - temp.resize(temp.size() * 2); - } while (true); -} -} -#endif - -// FIXME: Qt filesystem abstraction is bad, but ... let's hope it doesn't break too much? -// FIXME: The error handling is just DEFICIENT -Package Package::fromInspectedFolder(const QString& folderPath) -{ - QDir root(folderPath); - - Package out; - QDirIterator iterator(folderPath, QDir::NoDotAndDotDot | QDir::AllEntries | QDir::System | QDir::Hidden, QDirIterator::Subdirectories); - while(iterator.hasNext()) { - iterator.next(); - - auto fileInfo = iterator.fileInfo(); - auto relPath = root.relativeFilePath(fileInfo.filePath()); - // FIXME: this is probably completely busted on Windows anyway, so just disable it. - // Qt makes shit up and doesn't understand the platform details - // TODO: Actually use a filesystem library that isn't terrible and has decen license. - // I only know one, and I wrote it. Sadly, currently proprietary. PAIN. -#ifndef Q_OS_WIN32 - if(fileInfo.isSymLink()) { - Path targetPath; - if(!actually_read_symlink_target(fileInfo.filePath(), targetPath)) { - qCritical() << "Folder inspection: Unknown filesystem object:" << fileInfo.absoluteFilePath(); - out.valid = false; - } - out.addLink(relPath, targetPath); - } - else -#endif - if(fileInfo.isDir()) { - out.addFolder(relPath); - } - else if(fileInfo.isFile()) { - File f; - f.executable = fileInfo.isExecutable(); - f.size = fileInfo.size(); - // FIXME: async / optimize the hashing - QFile input(fileInfo.absoluteFilePath()); - if(!input.open(QIODevice::ReadOnly)) { - qCritical() << "Folder inspection: Failed to open file:" << fileInfo.absoluteFilePath(); - out.valid = false; - break; - } - f.hash = QCryptographicHash::hash(input.readAll(), QCryptographicHash::Sha1).toHex().constData(); - out.addFile(relPath, f); - } - else { - // Something else... oh my - qCritical() << "Folder inspection: Unknown filesystem object:" << fileInfo.absoluteFilePath(); - out.valid = false; - break; - } - } - out.folders.insert(Path(".")); - out.valid = true; - return out; -} - -namespace { -struct shallow_first_sort -{ - bool operator()(const Path &lhs, const Path &rhs) const - { - auto lhs_depth = lhs.length(); - auto rhs_depth = rhs.length(); - if(lhs_depth < rhs_depth) - { - return true; - } - else if(lhs_depth == rhs_depth) - { - if(lhs < rhs) - { - return true; - } - } - return false; - } -}; - -struct deep_first_sort -{ - bool operator()(const Path &lhs, const Path &rhs) const - { - auto lhs_depth = lhs.length(); - auto rhs_depth = rhs.length(); - if(lhs_depth > rhs_depth) - { - return true; - } - else if(lhs_depth == rhs_depth) - { - if(lhs < rhs) - { - return true; - } - } - return false; - } -}; -} - -UpdateOperations UpdateOperations::resolve(const Package& from, const Package& to) -{ - UpdateOperations out; - - if(!from.valid || !to.valid) { - out.valid = false; - return out; - } - - // Files - for(auto iter = from.files.begin(); iter != from.files.end(); iter++) { - const auto ¤t_hash = iter->second.hash; - const auto ¤t_executable = iter->second.executable; - const auto &path = iter->first; - - auto iter2 = to.files.find(path); - if(iter2 == to.files.end()) { - // removed - out.deletes.push_back(path); - continue; - } - auto new_hash = iter2->second.hash; - auto new_executable = iter2->second.executable; - if (current_hash != new_hash) { - out.deletes.push_back(path); - out.downloads.emplace( - std::pair{ - path, - FileDownload(to.sources.at(iter2->second.hash), iter2->second.executable) - } - ); - } - else if (current_executable != new_executable) { - out.executable_fixes[path] = new_executable; - } - } - for(auto iter = to.files.begin(); iter != to.files.end(); iter++) { - auto path = iter->first; - if(!from.files.count(path)) { - out.downloads.emplace( - std::pair{ - path, - FileDownload(to.sources.at(iter->second.hash), iter->second.executable) - } - ); - } - } - - // Folders - std::set remove_folders; - std::set make_folders; - for(auto from_path: from.folders) { - auto iter = to.folders.find(from_path); - if(iter == to.folders.end()) { - remove_folders.insert(from_path); - } - } - for(auto & rmdir: remove_folders) { - out.rmdirs.push_back(rmdir); - } - for(auto to_path: to.folders) { - auto iter = from.folders.find(to_path); - if(iter == from.folders.end()) { - make_folders.insert(to_path); - } - } - for(auto & mkdir: make_folders) { - out.mkdirs.push_back(mkdir); - } - - // Symlinks - for(auto iter = from.symlinks.begin(); iter != from.symlinks.end(); iter++) { - const auto ¤t_target = iter->second; - const auto &path = iter->first; - - auto iter2 = to.symlinks.find(path); - if(iter2 == to.symlinks.end()) { - // removed - out.deletes.push_back(path); - continue; - } - const auto &new_target = iter2->second; - if (current_target != new_target) { - out.deletes.push_back(path); - out.mklinks[path] = iter2->second; - } - } - for(auto iter = to.symlinks.begin(); iter != to.symlinks.end(); iter++) { - auto path = iter->first; - if(!from.symlinks.count(path)) { - out.mklinks[path] = iter->second; - } - } - out.valid = true; - return out; -} - -} diff --git a/launcher/mojang/PackageManifest.h b/launcher/mojang/PackageManifest.h deleted file mode 100644 index fd7ab0ad..00000000 --- a/launcher/mojang/PackageManifest.h +++ /dev/null @@ -1,171 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include "tasks/Task.h" - -namespace mojang_files { - -using Hash = QString; -extern const Hash empty_hash; - -// simple-ish path implementation. assumes always relative and does not allow '..' entries -class Path -{ -public: - using parts_type = QStringList; - - Path() = default; - Path(QString string) { - auto parts_in = string.split('/'); - for(auto & part: parts_in) { - if(part.isEmpty() || part == ".") { - continue; - } - if(part == "..") { - if(parts.size()) { - parts.pop_back(); - } - continue; - } - parts.push_back(part); - } - } - - bool has_parent_path() const - { - return parts.size() > 0; - } - - Path parent_path() const - { - if (parts.empty()) - return Path(); - return Path(parts.begin(), std::prev(parts.end())); - } - - bool empty() const - { - return parts.empty(); - } - - int length() const - { - return parts.length(); - } - - bool operator==(const Path & rhs) const { - return parts == rhs.parts; - } - - bool operator!=(const Path & rhs) const { - return parts != rhs.parts; - } - - inline bool operator<(const Path& rhs) const - { - return compare(rhs) < 0; - } - - parts_type::const_iterator begin() const - { - return parts.begin(); - } - - parts_type::const_iterator end() const - { - return parts.end(); - } - - QString toString() const { - return parts.join("/"); - } - -private: - Path(const parts_type::const_iterator & start, const parts_type::const_iterator & end) { - auto cursor = start; - while(cursor != end) { - parts.push_back(*cursor); - cursor++; - } - } - int compare(const Path& p) const; - - parts_type parts; -}; - - -enum class Compression { - Raw, - Lzma, - Unknown -}; - - -struct FileSource -{ - Compression compression = Compression::Unknown; - Hash hash; - QString url; - std::size_t size = 0; - void upgrade(const FileSource & other) { - if(compression == Compression::Unknown || other.size < size) { - *this = other; - } - } - bool isBad() const { - return compression == Compression::Unknown; - } -}; - -struct File -{ - Hash hash; - bool executable; - std::uint64_t size = 0; -}; - -struct Package { - static Package fromInspectedFolder(const QString &folderPath); - static Package fromManifestFile(const QString &path); - static Package fromManifestContents(const QByteArray& contents); - - explicit operator bool() const - { - return valid; - } - void addFolder(Path folder); - void addFile(const Path & path, const File & file); - void addLink(const Path & path, const Path & target); - void addSource(const FileSource & source); - - std::map sources; - bool valid = true; - std::set folders; - std::map files; - std::map symlinks; -}; - -struct FileDownload : FileSource -{ - FileDownload(const FileSource& source, bool executable) { - static_cast (*this) = source; - this->executable = executable; - } - bool executable = false; -}; - -struct UpdateOperations { - static UpdateOperations resolve(const Package & from, const Package & to); - bool valid = false; - std::vector deletes; - std::vector rmdirs; - std::vector mkdirs; - std::map downloads; - std::map mklinks; - std::map executable_fixes; -}; - -} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 36a3b0f8..a26a49fe 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,9 +9,6 @@ ecm_add_test(GZip_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}:: ecm_add_test(GradleSpecifier_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test TEST_NAME GradleSpecifier) -ecm_add_test(PackageManifest_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test - TEST_NAME PackageManifest) - ecm_add_test(MojangVersionFormat_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test TEST_NAME MojangVersionFormat) diff --git a/tests/PackageManifest_test.cpp b/tests/PackageManifest_test.cpp deleted file mode 100644 index e38abf80..00000000 --- a/tests/PackageManifest_test.cpp +++ /dev/null @@ -1,343 +0,0 @@ -#include -#include - -#include - -using namespace mojang_files; - -QDebug operator<<(QDebug debug, const Path &path) -{ - debug << path.toString(); - return debug; -} - -class PackageManifestTest : public QObject -{ - Q_OBJECT - -private slots: - void test_parse(); - void test_parse_file(); - void test_inspect(); -#ifndef Q_OS_WIN32 - void test_inspect_symlinks(); -#endif - void mkdir_deep(); - void rmdir_deep(); - - void identical_file(); - void changed_file(); - void added_file(); - void removed_file(); -}; - -namespace { -QByteArray basic_manifest = R"END( -{ - "files": { - "a/b.txt": { - "type": "file", - "downloads": { - "raw": { - "url": "http://dethware.org/b.txt", - "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709", - "size": 0 - } - }, - "executable": true - }, - "a/b/c": { - "type": "directory" - }, - "a/b/c.txt": { - "type": "link", - "target": "../b.txt" - } - } -} -)END"; -} - -void PackageManifestTest::test_parse() -{ - auto manifest = Package::fromManifestContents(basic_manifest); - QVERIFY(manifest.valid == true); - QVERIFY(manifest.files.size() == 1); - QVERIFY(manifest.files.count(Path("a/b.txt"))); - auto &file = manifest.files[Path("a/b.txt")]; - QVERIFY(file.executable == true); - QVERIFY(file.hash == "da39a3ee5e6b4b0d3255bfef95601890afd80709"); - QVERIFY(file.size == 0); - QVERIFY(manifest.folders.size() == 4); - QVERIFY(manifest.folders.count(Path("."))); - QVERIFY(manifest.folders.count(Path("a"))); - QVERIFY(manifest.folders.count(Path("a/b"))); - QVERIFY(manifest.folders.count(Path("a/b/c"))); - QVERIFY(manifest.symlinks.size() == 1); - auto symlinkPath = Path("a/b/c.txt"); - QVERIFY(manifest.symlinks.count(symlinkPath)); - auto &symlink = manifest.symlinks[symlinkPath]; - QVERIFY(symlink == Path("../b.txt")); - QVERIFY(manifest.sources.size() == 1); -} - -void PackageManifestTest::test_parse_file() { - auto path = QFINDTESTDATA("testdata/PackageManifest/1.8.0_202-x64.json"); - auto manifest = Package::fromManifestFile(path); - QVERIFY(manifest.valid == true); -} - - -void PackageManifestTest::test_inspect() { - auto path = QFINDTESTDATA("testdata/PackageManifest/inspect_win/"); - auto manifest = Package::fromInspectedFolder(path); - QVERIFY(manifest.valid == true); - QVERIFY(manifest.files.size() == 2); - QVERIFY(manifest.files.count(Path("a/b.txt"))); - auto &file1 = manifest.files[Path("a/b.txt")]; - QVERIFY(file1.executable == false); - QVERIFY(file1.hash == "da39a3ee5e6b4b0d3255bfef95601890afd80709"); - QVERIFY(file1.size == 0); - QVERIFY(manifest.files.count(Path("a/b/b.txt"))); - auto &file2 = manifest.files[Path("a/b/b.txt")]; - QVERIFY(file2.executable == false); - QVERIFY(file2.hash == "da39a3ee5e6b4b0d3255bfef95601890afd80709"); - QVERIFY(file2.size == 0); - QVERIFY(manifest.folders.size() == 3); - QVERIFY(manifest.folders.count(Path("."))); - QVERIFY(manifest.folders.count(Path("a"))); - QVERIFY(manifest.folders.count(Path("a/b"))); - QVERIFY(manifest.symlinks.size() == 0); -} - -#ifndef Q_OS_WIN32 -void PackageManifestTest::test_inspect_symlinks() { - auto path = QFINDTESTDATA("testdata/PackageManifest/inspect/"); - auto manifest = Package::fromInspectedFolder(path); - QVERIFY(manifest.valid == true); - QVERIFY(manifest.files.size() == 1); - QVERIFY(manifest.files.count(Path("a/b.txt"))); - auto &file = manifest.files[Path("a/b.txt")]; - QVERIFY(file.executable == true); - QVERIFY(file.hash == "da39a3ee5e6b4b0d3255bfef95601890afd80709"); - QVERIFY(file.size == 0); - QVERIFY(manifest.folders.size() == 3); - QVERIFY(manifest.folders.count(Path("."))); - QVERIFY(manifest.folders.count(Path("a"))); - QVERIFY(manifest.folders.count(Path("a/b"))); - QVERIFY(manifest.symlinks.size() == 1); - QVERIFY(manifest.symlinks.count(Path("a/b/b.txt"))); - qDebug() << manifest.symlinks[Path("a/b/b.txt")]; - QVERIFY(manifest.symlinks[Path("a/b/b.txt")] == Path("../b.txt")); -} -#endif - -void PackageManifestTest::mkdir_deep() { - - Package from; - auto to = Package::fromManifestContents(R"END( -{ - "files": { - "a/b/c/d/e": { - "type": "directory" - } - } -} -)END"); - auto operations = UpdateOperations::resolve(from, to); - QVERIFY(operations.deletes.size() == 0); - QVERIFY(operations.rmdirs.size() == 0); - - QVERIFY(operations.mkdirs.size() == 6); - QVERIFY(operations.mkdirs[0] == Path(".")); - QVERIFY(operations.mkdirs[1] == Path("a")); - QVERIFY(operations.mkdirs[2] == Path("a/b")); - QVERIFY(operations.mkdirs[3] == Path("a/b/c")); - QVERIFY(operations.mkdirs[4] == Path("a/b/c/d")); - QVERIFY(operations.mkdirs[5] == Path("a/b/c/d/e")); - - QVERIFY(operations.downloads.size() == 0); - QVERIFY(operations.mklinks.size() == 0); - QVERIFY(operations.executable_fixes.size() == 0); -} - -void PackageManifestTest::rmdir_deep() { - - Package to; - auto from = Package::fromManifestContents(R"END( -{ - "files": { - "a/b/c/d/e": { - "type": "directory" - } - } -} -)END"); - auto operations = UpdateOperations::resolve(from, to); - QVERIFY(operations.deletes.size() == 0); - - QVERIFY(operations.rmdirs.size() == 6); - QVERIFY(operations.rmdirs[0] == Path("a/b/c/d/e")); - QVERIFY(operations.rmdirs[1] == Path("a/b/c/d")); - QVERIFY(operations.rmdirs[2] == Path("a/b/c")); - QVERIFY(operations.rmdirs[3] == Path("a/b")); - QVERIFY(operations.rmdirs[4] == Path("a")); - QVERIFY(operations.rmdirs[5] == Path(".")); - - QVERIFY(operations.mkdirs.size() == 0); - QVERIFY(operations.downloads.size() == 0); - QVERIFY(operations.mklinks.size() == 0); - QVERIFY(operations.executable_fixes.size() == 0); -} - -void PackageManifestTest::identical_file() { - QByteArray manifest = R"END( -{ - "files": { - "a/b/c/d/empty.txt": { - "type": "file", - "downloads": { - "raw": { - "url": "http://dethware.org/empty.txt", - "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709", - "size": 0 - } - }, - "executable": false - } - } -} -)END"; - auto from = Package::fromManifestContents(manifest); - auto to = Package::fromManifestContents(manifest); - auto operations = UpdateOperations::resolve(from, to); - QVERIFY(operations.deletes.size() == 0); - QVERIFY(operations.rmdirs.size() == 0); - QVERIFY(operations.mkdirs.size() == 0); - QVERIFY(operations.downloads.size() == 0); - QVERIFY(operations.mklinks.size() == 0); - QVERIFY(operations.executable_fixes.size() == 0); -} - -void PackageManifestTest::changed_file() { - auto from = Package::fromManifestContents(R"END( -{ - "files": { - "a/b/c/d/file": { - "type": "file", - "downloads": { - "raw": { - "url": "http://dethware.org/empty.txt", - "sha1": "da39a3ee5e6b4b0d3255bfef95601890afd80709", - "size": 0 - } - }, - "executable": false - } - } -} -)END"); - auto to = Package::fromManifestContents(R"END( -{ - "files": { - "a/b/c/d/file": { - "type": "file", - "downloads": { - "raw": { - "url": "http://dethware.org/space.txt", - "sha1": "dd122581c8cd44d0227f9c305581ffcb4b6f1b46", - "size": 1 - } - }, - "executable": false - } - } -} -)END"); - auto operations = UpdateOperations::resolve(from, to); - QVERIFY(operations.deletes.size() == 1); - QCOMPARE(operations.deletes[0], Path("a/b/c/d/file")); - QVERIFY(operations.rmdirs.size() == 0); - QVERIFY(operations.mkdirs.size() == 0); - QVERIFY(operations.downloads.size() == 1); - QVERIFY(operations.mklinks.size() == 0); - QVERIFY(operations.executable_fixes.size() == 0); -} - -void PackageManifestTest::added_file() { - auto from = Package::fromManifestContents(R"END( -{ - "files": { - "a/b/c/d": { - "type": "directory" - } - } -} -)END"); - auto to = Package::fromManifestContents(R"END( -{ - "files": { - "a/b/c/d/file": { - "type": "file", - "downloads": { - "raw": { - "url": "http://dethware.org/space.txt", - "sha1": "dd122581c8cd44d0227f9c305581ffcb4b6f1b46", - "size": 1 - } - }, - "executable": false - } - } -} -)END"); - auto operations = UpdateOperations::resolve(from, to); - QVERIFY(operations.deletes.size() == 0); - QVERIFY(operations.rmdirs.size() == 0); - QVERIFY(operations.mkdirs.size() == 0); - QVERIFY(operations.downloads.size() == 1); - QVERIFY(operations.mklinks.size() == 0); - QVERIFY(operations.executable_fixes.size() == 0); -} - -void PackageManifestTest::removed_file() { - auto from = Package::fromManifestContents(R"END( -{ - "files": { - "a/b/c/d/file": { - "type": "file", - "downloads": { - "raw": { - "url": "http://dethware.org/space.txt", - "sha1": "dd122581c8cd44d0227f9c305581ffcb4b6f1b46", - "size": 1 - } - }, - "executable": false - } - } -} -)END"); - auto to = Package::fromManifestContents(R"END( -{ - "files": { - "a/b/c/d": { - "type": "directory" - } - } -} -)END"); - auto operations = UpdateOperations::resolve(from, to); - QVERIFY(operations.deletes.size() == 1); - QCOMPARE(operations.deletes[0], Path("a/b/c/d/file")); - QVERIFY(operations.rmdirs.size() == 0); - QVERIFY(operations.mkdirs.size() == 0); - QVERIFY(operations.downloads.size() == 0); - QVERIFY(operations.mklinks.size() == 0); - QVERIFY(operations.executable_fixes.size() == 0); -} - -QTEST_GUILESS_MAIN(PackageManifestTest) - -#include "PackageManifest_test.moc" - -- cgit From 6e5716f097d89b4b7b4c48ae18e37474ef23b3e8 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 27 Jun 2023 19:05:32 +0300 Subject: Fixed illegal characters in shortcuts name Signed-off-by: Trial97 --- launcher/FileSystem.cpp | 11 ++- launcher/ui/MainWindow.cpp | 203 +++++++++++++++++++-------------------------- 2 files changed, 95 insertions(+), 119 deletions(-) (limited to 'launcher') diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 835ad925..1ea9f755 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -372,7 +372,7 @@ void create_link::make_link_list(const QString& offset) auto src_path = source_it.next(); auto relative_path = src_dir.relativeFilePath(src_path); - if (m_max_depth >= 0 && pathDepth(relative_path) > m_max_depth){ + if (m_max_depth >= 0 && pathDepth(relative_path) > m_max_depth) { relative_path = pathTruncate(relative_path, m_max_depth); src_path = src_dir.filePath(relative_path); if (linkedPaths.contains(src_path)) { @@ -663,7 +663,7 @@ QString pathTruncate(const QString& path, int depth) QString trunc = QFileInfo(path).path(); - if (pathDepth(trunc) > depth ) { + if (pathDepth(trunc) > depth) { return pathTruncate(trunc, depth); } @@ -769,6 +769,9 @@ QString getDesktopDir() // Cross-platform Shortcut creation bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon) { + if (destination.isEmpty()) { + destination = PathCombine(getDesktopDir(), RemoveInvalidFilenameChars(name)); + } #if defined(Q_OS_MACOS) destination += ".command"; @@ -791,6 +794,8 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri return true; #elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) + if (!destination.endsWith(".desktop")) // in case of isFlatpak destination is already populated + destination += ".desktop"; QFile f(destination); f.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream stream(&f); @@ -974,7 +979,7 @@ FilesystemType getFilesystemType(const QString& name) { for (auto iter = s_filesystem_type_names.constBegin(); iter != s_filesystem_type_names.constEnd(); ++iter) { auto fs_names = iter.value(); - if(fs_names.contains(name.toUpper())) + if (fs_names.contains(name.toUpper())) return iter.key(); } return FilesystemType::UNKNOWN; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index eeb78c53..7407483f 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1510,140 +1510,111 @@ void MainWindow::on_actionKillInstance_triggered() void MainWindow::on_actionCreateInstanceShortcut_triggered() { - if (m_selectedInstance) - { - auto desktopPath = FS::getDesktopDir(); - if (desktopPath.isEmpty()) { - // TODO come up with an alternative solution (open "save file" dialog) - QMessageBox::critical(this, tr("Create instance shortcut"), tr("Couldn't find desktop?!")); - return; - } + if (!m_selectedInstance) + return; + auto desktopPath = FS::getDesktopDir(); + if (desktopPath.isEmpty()) { + // TODO come up with an alternative solution (open "save file" dialog) + QMessageBox::critical(this, tr("Create instance shortcut"), tr("Couldn't find desktop?!")); + return; + } + QString desktopFilePath; + QString appPath = QApplication::applicationFilePath(); + QString iconPath; + QStringList args; #if defined(Q_OS_MACOS) - QString appPath = QApplication::applicationFilePath(); - if (appPath.startsWith("/private/var/")) { - QMessageBox::critical(this, tr("Create instance shortcut"), tr("The launcher is in the folder it was extracted from, therefore it cannot create shortcuts.")); - return; - } - - if (FS::createShortcut(FS::PathCombine(desktopPath, m_selectedInstance->name()), - appPath, { "--launch", m_selectedInstance->id() }, - m_selectedInstance->name(), "")) { - QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!")); - } - else - { - QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!")); - } + if (appPath.startsWith("/private/var/")) { + QMessageBox::critical(this, tr("Create instance shortcut"), + tr("The launcher is in the folder it was extracted from, therefore it cannot create shortcuts.")); + return; + } #elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) - QString appPath = QApplication::applicationFilePath(); - if (appPath.startsWith("/tmp/.mount_")) { - // AppImage! - appPath = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE")); - if (appPath.isEmpty()) - { - QMessageBox::critical(this, tr("Create instance shortcut"), tr("Launcher is running as misconfigured AppImage? ($APPIMAGE environment variable is missing)")); - } - else if (appPath.endsWith("/")) - { - appPath.chop(1); - } + if (appPath.startsWith("/tmp/.mount_")) { + // AppImage! + appPath = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE")); + if (appPath.isEmpty()) { + QMessageBox::critical(this, tr("Create instance shortcut"), + tr("Launcher is running as misconfigured AppImage? ($APPIMAGE environment variable is missing)")); + } else if (appPath.endsWith("/")) { + appPath.chop(1); } + } - auto icon = APPLICATION->icons()->icon(m_selectedInstance->iconKey()); - if (icon == nullptr) - { - icon = APPLICATION->icons()->icon("grass"); - } + auto icon = APPLICATION->icons()->icon(m_selectedInstance->iconKey()); + if (icon == nullptr) { + icon = APPLICATION->icons()->icon("grass"); + } - QString iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "icon.png"); + iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "icon.png"); - QFile iconFile(iconPath); - if (!iconFile.open(QFile::WriteOnly)) - { - QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut.")); - return; - } - bool success = icon->icon().pixmap(64, 64).save(&iconFile, "PNG"); - iconFile.close(); + QFile iconFile(iconPath); + if (!iconFile.open(QFile::WriteOnly)) { + QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut.")); + return; + } + bool success = icon->icon().pixmap(64, 64).save(&iconFile, "PNG"); + iconFile.close(); - if (!success) - { - iconFile.remove(); - QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut.")); - return; - } + if (!success) { + iconFile.remove(); + QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut.")); + return; + } + + if (DesktopServices::isFlatpak()) { + desktopFilePath = FS::PathCombine(desktopPath, FS::RemoveInvalidFilenameChars(m_selectedInstance->name()) + ".desktop"); + QFileDialog fileDialog; + // workaround to make sure the portal file dialog opens in the desktop directory + fileDialog.setDirectoryUrl(desktopPath); + desktopFilePath = fileDialog.getSaveFileName(this, tr("Create Shortcut"), desktopFilePath, tr("Desktop Entries (*.desktop)")); + if (desktopFilePath.isEmpty()) + return; // file dialog canceled by user + appPath = "flatpak"; + QString flatpakAppId = BuildConfig.LAUNCHER_DESKTOPFILENAME; + flatpakAppId.remove(".desktop"); + args.append({ "run", flatpakAppId }); + } - QString desktopFilePath = FS::PathCombine(desktopPath, m_selectedInstance->name() + ".desktop"); - QStringList args; - if (DesktopServices::isFlatpak()) { - QFileDialog fileDialog; - // workaround to make sure the portal file dialog opens in the desktop directory - fileDialog.setDirectoryUrl(desktopPath); - desktopFilePath = fileDialog.getSaveFileName( - this, tr("Create Shortcut"), desktopFilePath, - tr("Desktop Entries (*.desktop)")); - if (desktopFilePath.isEmpty()) - return; // file dialog canceled by user - appPath = "flatpak"; - QString flatpakAppId = BuildConfig.LAUNCHER_DESKTOPFILENAME; - flatpakAppId.remove(".desktop"); - args.append({ "run", flatpakAppId }); - } - args.append({ "--launch", m_selectedInstance->id() }); - if (FS::createShortcut(desktopFilePath, appPath, args, m_selectedInstance->name(), iconPath)) { - QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!")); - } - else - { - iconFile.remove(); - QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!")); - } #elif defined(Q_OS_WIN) - auto icon = APPLICATION->icons()->icon(m_selectedInstance->iconKey()); - if (icon == nullptr) - { - icon = APPLICATION->icons()->icon("grass"); - } + auto icon = APPLICATION->icons()->icon(m_selectedInstance->iconKey()); + if (icon == nullptr) { + icon = APPLICATION->icons()->icon("grass"); + } - QString iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "icon.ico"); + iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "icon.ico"); - // part of fix for weird bug involving the window icon being replaced - // dunno why it happens, but this 2-line fix seems to be enough, so w/e - auto appIcon = APPLICATION->getThemedIcon("logo"); + // part of fix for weird bug involving the window icon being replaced + // dunno why it happens, but this 2-line fix seems to be enough, so w/e + auto appIcon = APPLICATION->getThemedIcon("logo"); - QFile iconFile(iconPath); - if (!iconFile.open(QFile::WriteOnly)) - { - QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut.")); - return; - } - bool success = icon->icon().pixmap(64, 64).save(&iconFile, "ICO"); - iconFile.close(); + QFile iconFile(iconPath); + if (!iconFile.open(QFile::WriteOnly)) { + QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut.")); + return; + } + bool success = icon->icon().pixmap(64, 64).save(&iconFile, "ICO"); + iconFile.close(); - // restore original window icon - QGuiApplication::setWindowIcon(appIcon); + // restore original window icon + QGuiApplication::setWindowIcon(appIcon); - if (!success) - { - iconFile.remove(); - QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut.")); - return; - } + if (!success) { + iconFile.remove(); + QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut.")); + return; + } - if (FS::createShortcut(FS::PathCombine(desktopPath, m_selectedInstance->name()), - QApplication::applicationFilePath(), { "--launch", m_selectedInstance->id() }, - m_selectedInstance->name(), iconPath)) { - QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!")); - } - else - { - iconFile.remove(); - QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!")); - } #else - QMessageBox::critical(this, tr("Create instance shortcut"), tr("Not supported on your platform!")); + QMessageBox::critical(this, tr("Create instance shortcut"), tr("Not supported on your platform!")); + return; #endif + args.append({ "--launch", m_selectedInstance->id() }); + if (FS::createShortcut(desktopFilePath, appPath, args, m_selectedInstance->name(), iconPath)) { + QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!")); + } else { + iconFile.remove(); + QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!")); } } -- cgit From 92847b977409f4f4b4daa1e34196596e40becc05 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 27 Jun 2023 19:15:20 +0300 Subject: omit icon remove on macos Signed-off-by: Trial97 --- launcher/ui/MainWindow.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 7407483f..496738e3 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1613,7 +1613,9 @@ void MainWindow::on_actionCreateInstanceShortcut_triggered() if (FS::createShortcut(desktopFilePath, appPath, args, m_selectedInstance->name(), iconPath)) { QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!")); } else { +#if not defined(Q_OS_MACOS) iconFile.remove(); +#endif QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!")); } } -- cgit From 54cb077b40b1785174a9bd111d055a399b725e52 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 27 Jun 2023 19:31:36 +0300 Subject: Added more information to the screenshot upload warning Signed-off-by: Trial97 --- launcher/ui/pages/instance/ScreenshotsPage.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp index ca368d3b..35237594 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.cpp +++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp @@ -36,6 +36,7 @@ */ #include "ScreenshotsPage.h" +#include "BuildConfig.h" #include "ui_ScreenshotsPage.h" #include @@ -380,16 +381,18 @@ void ScreenshotsPage::on_actionUpload_triggered() if (selection.isEmpty()) return; - QString text; + QUrl baseUrl(BuildConfig.IMGUR_BASE_URL); if (selection.size() > 1) - text = tr("You are about to upload %1 screenshots.\n\n" + text = tr("You are about to upload %1 screenshots to %2.\n" + "You should double-check for personal information.\n\n" "Are you sure?") - .arg(selection.size()); + .arg(QString::number(selection.size()), baseUrl.host()); else - text = - tr("You are about to upload the selected screenshot.\n\n" - "Are you sure?"); + text = tr("You are about to upload the selected screenshot to %1.\n" + "You should double-check for personal information.\n\n" + "Are you sure?") + .arg(baseUrl.host()); auto response = CustomMessageBox::selectable(this, "Confirm Upload", text, QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) -- cgit From 23b3711f96bd93171eebc401f983ccf0fb862772 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 27 Jun 2023 12:41:36 -0700 Subject: fix(filesystem): track failed copies and clones Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/FileSystem.cpp | 9 +++++++++ launcher/FileSystem.h | 9 +++++++++ 2 files changed, 18 insertions(+) (limited to 'launcher') diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 835ad925..0554cab8 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -36,6 +36,7 @@ */ #include "FileSystem.h" +#include #include "BuildConfig.h" @@ -246,6 +247,7 @@ bool copy::operator()(const QString& offset, bool dryRun) { using copy_opts = fs::copy_options; m_copied = 0; // reset counter + m_failedPaths.clear(); // NOTE always deep copy on windows. the alternatives are too messy. #if defined Q_OS_WIN32 @@ -277,6 +279,9 @@ bool copy::operator()(const QString& offset, bool dryRun) qWarning() << "Failed to copy files:" << QString::fromStdString(err.message()); qDebug() << "Source file:" << src_path; qDebug() << "Destination file:" << dst_path; + m_failedPaths.append(dst_path); + emit copyFailed(relative_dst_path); + return; } m_copied++; emit fileCopied(relative_dst_path); @@ -1072,6 +1077,7 @@ bool clone::operator()(const QString& offset, bool dryRun) } m_cloned = 0; // reset counter + m_failedClones.clear(); auto src = PathCombine(m_src.absolutePath(), offset); auto dst = PathCombine(m_dst.absolutePath(), offset); @@ -1092,6 +1098,9 @@ bool clone::operator()(const QString& offset, bool dryRun) qDebug() << "Failed to clone files: error" << err.value() << "message" << QString::fromStdString(err.message()); qDebug() << "Source file:" << src_path; qDebug() << "Destination file:" << dst_path; + m_failedClones.append(qMakePair(src_path, dst_path)); + emit cloneFailed(src_path, dst_path); + return; } m_cloned++; emit fileCloned(src_path, dst_path); diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index cb581d0c..f8a82bae 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -112,9 +113,12 @@ class copy : public QObject { bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); } int totalCopied() { return m_copied; } + int totalFailed() { return m_failedPaths.length(); } + QStringList failed() { return m_failedPaths; } signals: void fileCopied(const QString& relativeName); + void copyFailed(const QString& relativeName); // TODO: maybe add a "shouldCopy" signal in the future? private: @@ -127,6 +131,7 @@ class copy : public QObject { QDir m_src; QDir m_dst; int m_copied; + QStringList m_failedPaths; }; struct LinkPair { @@ -471,6 +476,9 @@ class clone : public QObject { bool operator()(bool dryRun = false) { return operator()(QString(), dryRun); } int totalCloned() { return m_cloned; } + int totalFailed() { return m_failedClones.length(); } + + QList> failed() { return m_failedClones; } signals: void fileCloned(const QString& src, const QString& dst); @@ -485,6 +493,7 @@ class clone : public QObject { QDir m_src; QDir m_dst; int m_cloned; + QList> m_failedClones; }; /** -- cgit From 00be211169134022813562cd09c69f831d0e400e Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Tue, 27 Jun 2023 13:01:28 -0700 Subject: Update launcher/FileSystem.cpp Co-authored-by: TheKodeToad Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/FileSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 0554cab8..8a417831 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -36,7 +36,7 @@ */ #include "FileSystem.h" -#include +#include #include "BuildConfig.h" -- cgit From 0f64ee6a5f6d157e493d474b74004a4ebd0dae43 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 28 Jun 2023 18:28:25 +0300 Subject: Added warnings for running instances Signed-off-by: Trial97 --- launcher/minecraft/mod/ResourceFolderModel.cpp | 18 ++++++++++++++++-- launcher/ui/pages/instance/ExternalResourcesPage.cpp | 20 ++++++++++++++++++++ launcher/ui/pages/instance/ModFolderPage.cpp | 10 ++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 1a56b679..c2c0d178 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -1,14 +1,15 @@ #include "ResourceFolderModel.h" +#include #include #include #include #include +#include #include #include #include #include -#include #include "Application.h" #include "FileSystem.h" @@ -18,6 +19,7 @@ #include "settings/Setting.h" #include "tasks/Task.h" +#include "ui/dialogs/CustomMessageBox.h" ResourceFolderModel::ResourceFolderModel(QDir dir, BaseInstance* instance, QObject* parent, bool create_dir) : QAbstractListModel(parent), m_dir(dir), m_instance(instance), m_watcher(this) @@ -451,8 +453,20 @@ bool ResourceFolderModel::setData(const QModelIndex& index, const QVariant& valu if (row < 0 || row >= rowCount(index.parent()) || !index.isValid()) return false; - if (role == Qt::CheckStateRole) + if (role == Qt::CheckStateRole) { + if (m_instance != nullptr && m_instance->isRunning()) { + auto response = + CustomMessageBox::selectable(nullptr, "Confirm toggle", + "If you enable/disable this resource while the game is running it may crash your game.\n" + "Are you sure you want to do this?", + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response != QMessageBox::Yes) + return false; + } return setResourceEnabled({ index }, EnableAction::TOGGLE); + } return false; } diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index 87a3df10..12038f88 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -250,6 +250,16 @@ void ExternalResourcesPage::removeItem() void ExternalResourcesPage::removeItems(const QItemSelection& selection) { + if (m_instance != nullptr && m_instance->isRunning()) { + auto response = CustomMessageBox::selectable(this, "Confirm Delete", + "If you remove this resource while the game is running it may crash your game.\n" + "Are you sure you want to do this?", + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response != QMessageBox::Yes) + return; + } m_model->deleteResources(selection.indexes()); } @@ -261,6 +271,16 @@ void ExternalResourcesPage::enableItem() void ExternalResourcesPage::disableItem() { + if (m_instance != nullptr && m_instance->isRunning()) { + auto response = CustomMessageBox::selectable(this, "Confirm disable", + "If you disable this resource while the game is running it may crash your game.\n" + "Are you sure you want to do this?", + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response != QMessageBox::Yes) + return; + } auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); m_model->setResourceEnabled(selection.indexes(), EnableAction::DISABLE); } diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 9812bbe9..3176396f 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -120,6 +120,16 @@ bool ModFolderPage::onSelectionChanged(const QModelIndex& current, const QModelI void ModFolderPage::removeItems(const QItemSelection& selection) { + if (m_instance != nullptr && m_instance->isRunning()) { + auto response = CustomMessageBox::selectable(this, "Confirm Delete", + "If you remove mods while the game is running it may crash your game.\n" + "Are you sure you want to do this?", + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response != QMessageBox::Yes) + return; + } m_model->deleteMods(selection.indexes()); } -- cgit From 0008b22d8b352e3591ee7ba7c6d9313ed23cbd4a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 28 Jun 2023 18:41:47 +0300 Subject: Renamed function Signed-off-by: Trial97 --- launcher/ui/MainWindow.cpp | 2 +- launcher/ui/instanceview/InstanceView.cpp | 9 ++++++--- launcher/ui/instanceview/InstanceView.h | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 26fcb3a3..515abf07 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -927,7 +927,7 @@ void MainWindow::onCatToggled(bool state) void MainWindow::setCatBackground(bool enabled) { - view->setCatVisible(enabled); + view->setPaintCat(enabled); view->viewport()->repaint(); } diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp index 4c83e94a..1911dd59 100644 --- a/launcher/ui/instanceview/InstanceView.cpp +++ b/launcher/ui/instanceview/InstanceView.cpp @@ -74,7 +74,7 @@ InstanceView::InstanceView(QWidget *parent) setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); setAcceptDrops(true); setAutoScroll(true); - setCatVisible(APPLICATION->settings()->get("TheCat").toBool()); + setPaintCat(APPLICATION->settings()->get("TheCat").toBool()); } InstanceView::~InstanceView() @@ -500,10 +500,13 @@ void InstanceView::mouseDoubleClickEvent(QMouseEvent *event) } } -void InstanceView::setCatVisible(bool visible) +void InstanceView::setPaintCat(bool visible) { m_catVisible = visible; - m_catPixmap.load(QString(":/backgrounds/%1").arg(ThemeManager::getCatImage())); + if (visible) + m_catPixmap.load(QString(":/backgrounds/%1").arg(ThemeManager::getCatImage())); + else + m_catPixmap = QPixmap(); } void InstanceView::paintEvent(QPaintEvent* event) diff --git a/launcher/ui/instanceview/InstanceView.h b/launcher/ui/instanceview/InstanceView.h index a9bd0bd7..36405675 100644 --- a/launcher/ui/instanceview/InstanceView.h +++ b/launcher/ui/instanceview/InstanceView.h @@ -86,7 +86,7 @@ public: virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override; int spacing() const { return m_spacing; }; - void setCatVisible(bool visible); + void setPaintCat(bool visible); public slots: virtual void updateGeometries() override; -- cgit From 87efa700ab53148f0555605fa21c683f3a9c3d15 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 30 Jun 2023 00:01:36 +0300 Subject: Removed logs from instance export Signed-off-by: Trial97 --- launcher/FileIgnoreProxy.cpp | 14 ++++++++++++++ launcher/FileIgnoreProxy.h | 8 ++++++++ launcher/ui/dialogs/ExportInstanceDialog.cpp | 22 +++++++++++++--------- launcher/ui/dialogs/ExportMrPackDialog.cpp | 3 ++- 4 files changed, 37 insertions(+), 10 deletions(-) (limited to 'launcher') diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp index a3b7d505..1f6b664c 100644 --- a/launcher/FileIgnoreProxy.cpp +++ b/launcher/FileIgnoreProxy.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include "FileSystem.h" #include "SeparatorPrefixTree.h" #include "StringUtils.h" @@ -254,3 +255,16 @@ bool FileIgnoreProxy::filterAcceptsColumn(int source_column, const QModelIndex& return true; } + +bool FileIgnoreProxy::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const +{ + QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + QFileSystemModel* fsm = qobject_cast(sourceModel()); + + auto fileInfo = fsm->fileInfo(index); + auto fileName = fileInfo.fileName(); + auto path = relPath(fileInfo.absoluteFilePath()); + return !(path.startsWith("..") || // just in case ignore files outside the gameroot + std::any_of(m_ignoreFiles.cbegin(), m_ignoreFiles.cend(), [fileName](auto iFileName) { return fileName == iFileName; }) || + std::any_of(m_ignoreFilePaths.cbegin(), m_ignoreFilePaths.cend(), [path](auto iPath) { return path == iPath; })); +} diff --git a/launcher/FileIgnoreProxy.h b/launcher/FileIgnoreProxy.h index a5a1153d..dbd353e0 100644 --- a/launcher/FileIgnoreProxy.h +++ b/launcher/FileIgnoreProxy.h @@ -63,10 +63,18 @@ class FileIgnoreProxy : public QSortFilterProxyModel { inline const SeparatorPrefixTree<'/'>& blockedPaths() const { return blocked; } inline SeparatorPrefixTree<'/'>& blockedPaths() { return blocked; } + // list of file names that need to be removed completely from model + inline QStringList& ignoreFilesWithName() { return m_ignoreFiles; } + // list of relative paths that need to be removed completely from model + inline QStringList& ignoreFilesWithPath() { return m_ignoreFilePaths; } + protected: bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const; + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; private: const QString root; SeparatorPrefixTree<'/'> blocked; + QStringList m_ignoreFiles; + QStringList m_ignoreFilePaths; }; diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index 8ecd91a9..8d0e05a2 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -35,24 +35,24 @@ */ #include "ExportInstanceDialog.h" -#include "ui_ExportInstanceDialog.h" #include #include #include -#include #include +#include +#include "ui_ExportInstanceDialog.h" -#include +#include +#include #include +#include #include +#include #include -#include -#include "SeparatorPrefixTree.h" #include "Application.h" -#include -#include +#include "SeparatorPrefixTree.h" -ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget *parent) +ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget* parent) : QDialog(parent), ui(new Ui::ExportInstanceDialog), m_instance(instance) { ui->setupUi(this); @@ -60,8 +60,12 @@ ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget *parent model->setIconProvider(&icons); auto root = instance->instanceRoot(); proxyModel = new FileIgnoreProxy(root, this); - loadPackIgnore(); proxyModel->setSourceModel(model); + auto prefix = QDir(instance->instanceRoot()).relativeFilePath(instance->gameRoot()); + proxyModel->ignoreFilesWithPath().append({ FS::PathCombine(prefix, "logs"), FS::PathCombine(prefix, "crash-reports") }); + proxyModel->ignoreFilesWithName().append({ ".DS_Store", "thumbs.db", "Thumbs.db" }); + loadPackIgnore(); + ui->treeView->setModel(proxyModel); ui->treeView->setRootIndex(proxyModel->mapFromSource(model->index(root))); ui->treeView->sortByColumn(0, Qt::AscendingOrder); diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index 60ecefd5..f1d2610a 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -52,8 +52,9 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) // use the game root - everything outside cannot be exported const QDir root(instance->gameRoot()); proxy = new FileIgnoreProxy(instance->gameRoot(), this); + proxy->ignoreFilesWithPath().append({ "logs", "crash-reports" }); + proxy->ignoreFilesWithName().append({ ".DS_Store", "thumbs.db", "Thumbs.db" }); proxy->setSourceModel(model); - proxy->setFilterRegularExpression("^(?!(\\.DS_Store)|([tT]humbs\\.db)).+$"); const QDir::Filters filter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden); -- cgit From 81207c65027a35d37394abe3ba6e3ef43777910a Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 30 Jun 2023 10:52:10 +0300 Subject: Made sure the logs are ignored when collecting files Signed-off-by: Trial97 --- launcher/FileIgnoreProxy.cpp | 16 +++++++++++++--- launcher/FileIgnoreProxy.h | 9 +++++++-- launcher/ui/dialogs/ExportInstanceDialog.cpp | 8 ++++---- launcher/ui/dialogs/ExportMrPackDialog.cpp | 4 ++-- 4 files changed, 26 insertions(+), 11 deletions(-) (limited to 'launcher') diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp index 1f6b664c..556e992c 100644 --- a/launcher/FileIgnoreProxy.cpp +++ b/launcher/FileIgnoreProxy.cpp @@ -262,9 +262,19 @@ bool FileIgnoreProxy::filterAcceptsRow(int sourceRow, const QModelIndex& sourceP QFileSystemModel* fsm = qobject_cast(sourceModel()); auto fileInfo = fsm->fileInfo(index); + return !ignoreFile(fileInfo); +} + +bool FileIgnoreProxy::ignoreFile(QFileInfo fileInfo) const +{ auto fileName = fileInfo.fileName(); auto path = relPath(fileInfo.absoluteFilePath()); - return !(path.startsWith("..") || // just in case ignore files outside the gameroot - std::any_of(m_ignoreFiles.cbegin(), m_ignoreFiles.cend(), [fileName](auto iFileName) { return fileName == iFileName; }) || - std::any_of(m_ignoreFilePaths.cbegin(), m_ignoreFilePaths.cend(), [path](auto iPath) { return path == iPath; })); + return (path.startsWith("..") || // just in case ignore files outside the gameroot + std::any_of(m_ignoreFiles.cbegin(), m_ignoreFiles.cend(), [fileName](auto iFileName) { return fileName == iFileName; }) || + m_ignoreFilePaths.covers(path)); +} + +bool FileIgnoreProxy::filterFile(const QString& fileName) const +{ + return blocked.covers(fileName) || ignoreFile(QFileInfo(QDir(root), fileName)); } diff --git a/launcher/FileIgnoreProxy.h b/launcher/FileIgnoreProxy.h index dbd353e0..e01a2651 100644 --- a/launcher/FileIgnoreProxy.h +++ b/launcher/FileIgnoreProxy.h @@ -36,6 +36,7 @@ #pragma once +#include #include #include "SeparatorPrefixTree.h" @@ -66,15 +67,19 @@ class FileIgnoreProxy : public QSortFilterProxyModel { // list of file names that need to be removed completely from model inline QStringList& ignoreFilesWithName() { return m_ignoreFiles; } // list of relative paths that need to be removed completely from model - inline QStringList& ignoreFilesWithPath() { return m_ignoreFilePaths; } + inline SeparatorPrefixTree<'/'>& ignoreFilesWithPath() { return m_ignoreFilePaths; } + + bool filterFile(const QString& fileName) const; protected: bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const; bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; + bool ignoreFile(QFileInfo file) const; + private: const QString root; SeparatorPrefixTree<'/'> blocked; QStringList m_ignoreFiles; - QStringList m_ignoreFilePaths; + SeparatorPrefixTree<'/'> m_ignoreFilePaths; }; diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp index 8d0e05a2..cc41c394 100644 --- a/launcher/ui/dialogs/ExportInstanceDialog.cpp +++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp @@ -40,6 +40,7 @@ #include #include #include +#include "FileIgnoreProxy.h" #include "ui_ExportInstanceDialog.h" #include @@ -49,6 +50,7 @@ #include #include #include +#include #include "Application.h" #include "SeparatorPrefixTree.h" @@ -62,7 +64,7 @@ ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget* parent proxyModel = new FileIgnoreProxy(root, this); proxyModel->setSourceModel(model); auto prefix = QDir(instance->instanceRoot()).relativeFilePath(instance->gameRoot()); - proxyModel->ignoreFilesWithPath().append({ FS::PathCombine(prefix, "logs"), FS::PathCombine(prefix, "crash-reports") }); + proxyModel->ignoreFilesWithPath().insert({ FS::PathCombine(prefix, "logs"), FS::PathCombine(prefix, "crash-reports") }); proxyModel->ignoreFilesWithName().append({ ".DS_Store", "thumbs.db", "Thumbs.db" }); loadPackIgnore(); @@ -137,11 +139,9 @@ bool ExportInstanceDialog::doExport() SaveIcon(m_instance); - auto & blocked = proxyModel->blockedPaths(); - using std::placeholders::_1; auto files = QFileInfoList(); if (!MMCZip::collectFileListRecursively(m_instance->instanceRoot(), nullptr, &files, - std::bind(&SeparatorPrefixTree<'/'>::covers, blocked, _1))) { + std::bind(&FileIgnoreProxy::filterFile, proxyModel, std::placeholders::_1))) { QMessageBox::warning(this, tr("Error"), tr("Unable to export instance")); return false; } diff --git a/launcher/ui/dialogs/ExportMrPackDialog.cpp b/launcher/ui/dialogs/ExportMrPackDialog.cpp index f1d2610a..b302f7ba 100644 --- a/launcher/ui/dialogs/ExportMrPackDialog.cpp +++ b/launcher/ui/dialogs/ExportMrPackDialog.cpp @@ -52,7 +52,7 @@ ExportMrPackDialog::ExportMrPackDialog(InstancePtr instance, QWidget* parent) // use the game root - everything outside cannot be exported const QDir root(instance->gameRoot()); proxy = new FileIgnoreProxy(instance->gameRoot(), this); - proxy->ignoreFilesWithPath().append({ "logs", "crash-reports" }); + proxy->ignoreFilesWithPath().insert({ "logs", "crash-reports" }); proxy->ignoreFilesWithName().append({ ".DS_Store", "thumbs.db", "Thumbs.db" }); proxy->setSourceModel(model); @@ -100,7 +100,7 @@ void ExportMrPackDialog::done(int result) return; ModrinthPackExportTask task(ui->name->text(), ui->version->text(), ui->summary->text(), instance, output, - [this](const QString& path) { return proxy->blockedPaths().covers(path); }); + std::bind(&FileIgnoreProxy::filterFile, proxy, std::placeholders::_1)); connect(&task, &Task::failed, [this](const QString reason) { CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Critical)->show(); }); -- cgit From 18e628e8733df2f49f20cc1989817b2272cdf151 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 30 Jun 2023 12:10:00 +0300 Subject: removed extra condition Signed-off-by: Trial97 --- launcher/FileIgnoreProxy.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/FileIgnoreProxy.cpp b/launcher/FileIgnoreProxy.cpp index 556e992c..4c8c64c7 100644 --- a/launcher/FileIgnoreProxy.cpp +++ b/launcher/FileIgnoreProxy.cpp @@ -269,9 +269,8 @@ bool FileIgnoreProxy::ignoreFile(QFileInfo fileInfo) const { auto fileName = fileInfo.fileName(); auto path = relPath(fileInfo.absoluteFilePath()); - return (path.startsWith("..") || // just in case ignore files outside the gameroot - std::any_of(m_ignoreFiles.cbegin(), m_ignoreFiles.cend(), [fileName](auto iFileName) { return fileName == iFileName; }) || - m_ignoreFilePaths.covers(path)); + return std::any_of(m_ignoreFiles.cbegin(), m_ignoreFiles.cend(), [fileName](auto iFileName) { return fileName == iFileName; }) || + m_ignoreFilePaths.covers(path); } bool FileIgnoreProxy::filterFile(const QString& fileName) const -- cgit From 3fe518ff2b9ef902ff44b2c8249bafdf61f8e5eb Mon Sep 17 00:00:00 2001 From: Finian Wright Date: Sun, 2 Jul 2023 00:35:37 -0400 Subject: Fix compiling on OpenBSD Signed-off-by: Finian Wright --- launcher/FileSystem.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 1ea9f755..3ce8dd2c 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -102,7 +102,7 @@ namespace fs = ghc::filesystem; #include #include #include -#elif defined(Q_OS_MACOS) || defined(Q_OS_OPENBSD) +#elif defined(Q_OS_MACOS) #include #include #elif defined(Q_OS_WIN) @@ -1156,7 +1156,7 @@ bool clone_file(const QString& src, const QString& dst, std::error_code& ec) return false; } -#elif defined(Q_OS_MACOS) || defined(Q_OS_OPENBSD) +#elif defined(Q_OS_MACOS) if (!macos_bsd_clonefile(src_path, dst_path, ec)) { qDebug() << "failed macos_bsd_clonefile:"; @@ -1385,7 +1385,7 @@ bool linux_ficlone(const std::string& src_path, const std::string& dst_path, std return true; } -#elif defined(Q_OS_MACOS) || defined(Q_OS_OPENBSD) +#elif defined(Q_OS_MACOS) bool macos_bsd_clonefile(const std::string& src_path, const std::string& dst_path, std::error_code& ec) { -- cgit From aad5ca5474ff015da30809260fe0f9d6cb503d61 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 2 Jul 2023 16:45:15 +0300 Subject: fixed typos Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 10 +++++----- launcher/ui/dialogs/ExportPackDialog.cpp | 1 + launcher/ui/dialogs/ExportPackDialog.ui | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 13308b50..927146e1 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -105,7 +105,7 @@ void FlamePackExportTask::collectFiles() void FlamePackExportTask::collectHashes() { setAbortable(true); - setStatus(tr("Find file hashes...")); + setStatus(tr("Finding file hashes...")); setProgress(1, 5); auto allMods = mcInstance->loaderModList()->allMods(); ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); @@ -186,7 +186,7 @@ void FlamePackExportTask::makeApiRequest() return; } - setStatus(tr("Find versions for hashes...")); + setStatus(tr("Finding versions for hashes...")); setProgress(2, 5); auto response = std::make_shared(); @@ -255,10 +255,10 @@ void FlamePackExportTask::makeApiRequest() void FlamePackExportTask::getProjectsInfo() { - setStatus(tr("Find project info from CurseForge...")); + setStatus(tr("Finding project info from CurseForge...")); setProgress(3, 5); - QList addonIds; - for (auto resolved : resolvedFiles) { + QStringList addonIds; + for (const auto& resolved : resolvedFiles) { if (resolved.slug.isEmpty()) { addonIds << QString::number(resolved.addonId); } diff --git a/launcher/ui/dialogs/ExportPackDialog.cpp b/launcher/ui/dialogs/ExportPackDialog.cpp index a54a3c86..2abe2805 100644 --- a/launcher/ui/dialogs/ExportPackDialog.cpp +++ b/launcher/ui/dialogs/ExportPackDialog.cpp @@ -41,6 +41,7 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla ui->name->setText(instance->name()); if (m_provider == ModPlatform::ResourceProvider::MODRINTH) { ui->summary->setText(instance->notes().split(QRegularExpression("\\r?\\n"))[0]); + setWindowTitle("Export Modrinth Pack"); } else { setWindowTitle("Export CurseForge Pack"); ui->version->setText(""); diff --git a/launcher/ui/dialogs/ExportPackDialog.ui b/launcher/ui/dialogs/ExportPackDialog.ui index 658e2199..3976e28f 100644 --- a/launcher/ui/dialogs/ExportPackDialog.ui +++ b/launcher/ui/dialogs/ExportPackDialog.ui @@ -11,7 +11,7 @@
    - Export Modrinth Pack + Export Pack true -- cgit From 5f63c781b400aab29298b1eb2822477e35d87c01 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 2 Jul 2023 18:50:29 +0300 Subject: resolved local vaiables names Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 132 ++++++++++----------- .../modrinth/ModrinthPackExportTask.cpp | 4 +- 2 files changed, 68 insertions(+), 68 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 927146e1..1b75908a 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -108,8 +108,8 @@ void FlamePackExportTask::collectHashes() setStatus(tr("Finding file hashes...")); setProgress(1, 5); auto allMods = mcInstance->loaderModList()->allMods(); - ConcurrentTask::Ptr hashing_task(new ConcurrentTask(this, "MakeHashesTask", 10)); - task.reset(hashing_task); + ConcurrentTask::Ptr hashingTask(new ConcurrentTask(this, "MakeHashesTask", 10)); + task.reset(hashingTask); for (const QFileInfo& file : files) { const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); // require sensible file types @@ -120,14 +120,14 @@ void FlamePackExportTask::collectHashes() if (relative.startsWith("resourcepacks/") && (relative.endsWith(".zip") || relative.endsWith(".zip.disabled"))) { // is resourcepack - auto hash_task = Hashing::createFlameHasher(file.absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, relative, file](QString hash) { + auto hashTask = Hashing::createFlameHasher(file.absoluteFilePath()); + connect(hashTask.get(), &Hashing::Hasher::resultsReady, [this, relative, file](QString hash) { if (m_state == Task::State::Running) { pendingHashes.insert(hash, { relative, file.absoluteFilePath(), relative.endsWith(".zip") }); } }); - connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); - hashing_task->addTask(hash_task); + connect(hashTask.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + hashingTask->addTask(hashTask); continue; } @@ -144,39 +144,39 @@ void FlamePackExportTask::collectHashes() continue; } - auto hash_task = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); - connect(hash_task.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { + auto hashTask = Hashing::createFlameHasher(mod->fileinfo().absoluteFilePath()); + connect(hashTask.get(), &Hashing::Hasher::resultsReady, [this, mod](QString hash) { if (m_state == Task::State::Running) { pendingHashes.insert(hash, { mod->name(), mod->fileinfo().absoluteFilePath(), mod->enabled(), true }); } }); - connect(hash_task.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); - hashing_task->addTask(hash_task); + connect(hashTask.get(), &Task::failed, this, &FlamePackExportTask::emitFailed); + hashingTask->addTask(hashTask); } } - auto step_progress = std::make_shared(); - connect(hashing_task.get(), &Task::finished, this, [this, step_progress] { - step_progress->state = TaskStepState::Succeeded; - stepProgress(*step_progress); + auto progressStep = std::make_shared(); + connect(hashingTask.get(), &Task::finished, this, [this, progressStep] { + progressStep->state = TaskStepState::Succeeded; + stepProgress(*progressStep); }); - connect(hashing_task.get(), &Task::succeeded, this, &FlamePackExportTask::makeApiRequest); - connect(hashing_task.get(), &Task::failed, this, [this, step_progress](QString reason) { - step_progress->state = TaskStepState::Failed; - stepProgress(*step_progress); + connect(hashingTask.get(), &Task::succeeded, this, &FlamePackExportTask::makeApiRequest); + connect(hashingTask.get(), &Task::failed, this, [this, progressStep](QString reason) { + progressStep->state = TaskStepState::Failed; + stepProgress(*progressStep); emitFailed(reason); }); - connect(hashing_task.get(), &Task::stepProgress, this, &FlamePackExportTask::propogateStepProgress); + connect(hashingTask.get(), &Task::stepProgress, this, &FlamePackExportTask::propogateStepProgress); - connect(hashing_task.get(), &Task::progress, this, [this, step_progress](qint64 current, qint64 total) { - step_progress->update(current, total); - stepProgress(*step_progress); + connect(hashingTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) { + progressStep->update(current, total); + stepProgress(*progressStep); }); - connect(hashing_task.get(), &Task::status, this, [this, step_progress](QString status) { - step_progress->status = status; - stepProgress(*step_progress); + connect(hashingTask.get(), &Task::status, this, [this, progressStep](QString status) { + progressStep->status = status; + stepProgress(*progressStep); }); - hashing_task->start(); + hashingTask->start(); } void FlamePackExportTask::makeApiRequest() @@ -198,38 +198,38 @@ void FlamePackExportTask::makeApiRequest() task.reset(api.matchFingerprints(fingerprints, response)); connect(task.get(), &Task::succeeded, this, [this, response] { - QJsonParseError parse_error{}; - QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from CurseForge::CurrentVersions at " << parse_error.offset - << " reason: " << parse_error.errorString(); + QJsonParseError parseError{}; + QJsonDocument doc = QJsonDocument::fromJson(*response, &parseError); + if (parseError.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from CurseForge::CurrentVersions at " << parseError.offset + << " reason: " << parseError.errorString(); qWarning() << *response; - failed(parse_error.errorString()); + failed(parseError.errorString()); return; } try { - auto doc_obj = Json::requireObject(doc); - auto data_obj = Json::requireObject(doc_obj, "data"); - auto data_arr = Json::requireArray(data_obj, "exactMatches"); + auto docObj = Json::requireObject(doc); + auto dataObj = Json::requireObject(docObj, "data"); + auto dataArr = Json::requireArray(dataObj, "exactMatches"); - if (data_arr.isEmpty()) { + if (dataArr.isEmpty()) { qWarning() << "No matches found for fingerprint search!"; return; } - for (auto match : data_arr) { - auto match_obj = Json::ensureObject(match, {}); - auto file_obj = Json::ensureObject(match_obj, "file", {}); + for (auto match : dataArr) { + auto matchObj = Json::ensureObject(match, {}); + auto fileObj = Json::ensureObject(matchObj, "file", {}); - if (match_obj.isEmpty() || file_obj.isEmpty()) { + if (matchObj.isEmpty() || fileObj.isEmpty()) { qWarning() << "Fingerprint match is empty!"; return; } - auto fingerprint = QString::number(Json::ensureVariant(file_obj, "fileFingerprint").toUInt()); + auto fingerprint = QString::number(Json::ensureVariant(fileObj, "fileFingerprint").toUInt()); auto mod = pendingHashes.find(fingerprint); if (mod == pendingHashes.end()) { qWarning() << "Invalid fingerprint from the API response."; @@ -237,8 +237,8 @@ void FlamePackExportTask::makeApiRequest() } setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(mod->name)); - if (Json::ensureBoolean(file_obj, "isAvailable", false, "isAvailable")) - resolvedFiles.insert(mod->path, { Json::requireInteger(file_obj, "modId"), Json::requireInteger(file_obj, "id"), + if (Json::ensureBoolean(fileObj, "isAvailable", false, "isAvailable")) + resolvedFiles.insert(mod->path, { Json::requireInteger(fileObj, "modId"), Json::requireInteger(fileObj, "id"), mod->enabled, mod->isMod }); } @@ -265,25 +265,25 @@ void FlamePackExportTask::getProjectsInfo() } auto response = std::make_shared(); - Task::Ptr proj_task; + Task::Ptr projTask; if (addonIds.isEmpty()) { buildZip(); return; } else if (addonIds.size() == 1) { - proj_task = api.getProject(*addonIds.begin(), response); + projTask = api.getProject(*addonIds.begin(), response); } else { - proj_task = api.getProjects(addonIds, response); + projTask = api.getProjects(addonIds, response); } - connect(proj_task.get(), &Task::succeeded, this, [this, response, addonIds] { - QJsonParseError parse_error{}; - auto doc = QJsonDocument::fromJson(*response, &parse_error); - if (parse_error.error != QJsonParseError::NoError) { - qWarning() << "Error while parsing JSON response from CurseForge projects task at " << parse_error.offset - << " reason: " << parse_error.errorString(); + connect(projTask.get(), &Task::succeeded, this, [this, response, addonIds] { + QJsonParseError parseError{}; + auto doc = QJsonDocument::fromJson(*response, &parseError); + if (parseError.error != QJsonParseError::NoError) { + qWarning() << "Error while parsing JSON response from CurseForge projects task at " << parseError.offset + << " reason: " << parseError.errorString(); qWarning() << *response; - failed(parse_error.errorString()); + failed(parseError.errorString()); return; } @@ -295,13 +295,13 @@ void FlamePackExportTask::getProjectsInfo() entries = Json::requireArray(Json::requireObject(doc), "data"); for (auto entry : entries) { - auto entry_obj = Json::requireObject(entry); + auto entryObj = Json::requireObject(entry); try { - setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(Json::requireString(entry_obj, "name"))); + setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(Json::requireString(entryObj, "name"))); ModPlatform::IndexedPack pack; - FlameMod::loadIndexedPack(pack, entry_obj); + FlameMod::loadIndexedPack(pack, entryObj); for (auto key : resolvedFiles.keys()) { auto val = resolvedFiles.value(key); if (val.addonId == pack.addonId) { @@ -327,7 +327,7 @@ void FlamePackExportTask::getProjectsInfo() } buildZip(); }); - task.reset(proj_task); + task.reset(projTask); task->start(); } @@ -370,18 +370,18 @@ void FlamePackExportTask::buildZip() content = "
      " + content + "
    "; modlist.write(content.toUtf8()); - auto step_progress = std::make_shared(); + auto progressStep = std::make_shared(); size_t progress = 0; for (const QFileInfo& file : files) { if (buildZipFuture.isCanceled()) { QFile::remove(output); - step_progress->state = TaskStepState::Failed; - stepProgress(*step_progress); + progressStep->state = TaskStepState::Failed; + stepProgress(*progressStep); return BuildZipResult(); } - step_progress->update(progress, files.length()); - stepProgress(*step_progress); + progressStep->update(progress, files.length()); + stepProgress(*progressStep); const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath()); if (!resolvedFiles.contains(file.absoluteFilePath()) && @@ -396,12 +396,12 @@ void FlamePackExportTask::buildZip() if (zip.getZipError() != 0) { QFile::remove(output); - step_progress->state = TaskStepState::Failed; - stepProgress(*step_progress); + progressStep->state = TaskStepState::Failed; + stepProgress(*progressStep); return BuildZipResult(tr("A zip error occurred")); } - step_progress->state = TaskStepState::Succeeded; - stepProgress(*step_progress); + progressStep->state = TaskStepState::Succeeded; + stepProgress(*progressStep); return BuildZipResult(); }); connect(&buildZipWatcher, &QFutureWatcher::finished, this, &FlamePackExportTask::finish); diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index a9a1f1c4..c8206f1e 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -95,7 +95,7 @@ void ModrinthPackExportTask::collectFiles() void ModrinthPackExportTask::collectHashes() { - setStatus(tr("Find file hashes...")); + setStatus(tr("Finding file hashes...")); for (const QFileInfo& file : files) { QCoreApplication::processEvents(); @@ -159,7 +159,7 @@ void ModrinthPackExportTask::makeApiRequest() if (pendingHashes.isEmpty()) buildZip(); else { - setStatus(tr("Find versions for hashes...")); + setStatus(tr("Finding versions for hashes...")); auto response = std::make_shared(); task = api.currentVersions(pendingHashes.values(), "sha512", response); connect(task.get(), &NetJob::succeeded, [this, response]() { parseApiResponse(response); }); -- cgit From 4004e0faeed99b3deb0ffb0b0f469594843ca14b Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 2 Jul 2023 20:22:25 -0700 Subject: fix: segfault in progress dialog - dialog tries to resize after unhiding the subtask scroll area - after resize attempts to recenter on parent - `calls parentWidget()->{x|y}()` - what if there is no parent? nullptr->() = segfault - recenter on last pos, don't access parent Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 246a0fd4..84f9db7e 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -34,6 +34,7 @@ */ #include "ProgressDialog.h" +#include #include "ui_ProgressDialog.h" #include @@ -96,21 +97,30 @@ ProgressDialog::~ProgressDialog() void ProgressDialog::updateSize() { QSize lastSize = this->size(); - QSize qSize = QSize(480, minimumSizeHint().height()); + QPoint lastPos = this->pos(); + int minHeight = minimumSizeHint().height(); + if (ui->taskProgressScrollArea->isHidden()) + minHeight -= ui->taskProgressScrollArea->minimumSizeHint().height(); + QSize labelMinSize = ui->globalStatusLabel->minimumSize(); + int labelHeight = ui->globalStatusLabel->height(); + if (labelHeight > labelMinSize.height()) + minHeight += labelHeight - labelMinSize.height(); // account for multiline label + minHeight = std::max(minHeight, 0); + QSize minSize = QSize(480, minHeight); // if the current window is too small - if ((lastSize != qSize) && (lastSize.height() < qSize.height())) + if ((lastSize != minSize) && (lastSize.height() < minSize.height())) { - resize(qSize); - - // keep the dialog in the center after a resize - this->move( - this->parentWidget()->x() + (this->parentWidget()->width() - this->width()) / 2, - this->parentWidget()->y() + (this->parentWidget()->height() - this->height()) / 2 - ); + resize(minSize); + + QSize newSize = this->size(); + QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative + // center on old position after resize + QPoint newPos(lastPos.x() + (sizeDiff.width() / 2), lastPos.y() + (sizeDiff.height() / 2)); + this->move(newPos); } - setMinimumSize(qSize); + setMinimumSize(minSize); } -- cgit From 3960eb7d32af6ea776634b9f94e12f8df2397627 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 2 Jul 2023 21:24:43 -0700 Subject: fix: properly calculate min size for progress dialog, apply it at creation Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 84f9db7e..f70eee49 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -69,6 +69,7 @@ ProgressDialog::ProgressDialog(QWidget* parent) : QDialog(parent), ui(new Ui::Pr setAttribute(Qt::WidgetAttribute::WA_QuitOnClose, true); setSkipButton(false); changeProgress(0, 100); + updateSize(); } void ProgressDialog::setSkipButton(bool present, QString label) @@ -98,30 +99,28 @@ void ProgressDialog::updateSize() { QSize lastSize = this->size(); QPoint lastPos = this->pos(); - int minHeight = minimumSizeHint().height(); - if (ui->taskProgressScrollArea->isHidden()) - minHeight -= ui->taskProgressScrollArea->minimumSizeHint().height(); - QSize labelMinSize = ui->globalStatusLabel->minimumSize(); - int labelHeight = ui->globalStatusLabel->height(); - if (labelHeight > labelMinSize.height()) - minHeight += labelHeight - labelMinSize.height(); // account for multiline label - minHeight = std::max(minHeight, 0); + int minHeight = ui->globalStatusDetailsLabel->minimumSize().height() + (ui->verticalLayout->spacing() * 2); + minHeight += ui->globalProgressBar->minimumSize().height() + ui->verticalLayout->spacing(); + if (!ui->taskProgressScrollArea->isHidden()) + minHeight += ui->taskProgressScrollArea->minimumSizeHint().height() + ui->verticalLayout->spacing(); + if (ui->skipButton->isVisible()) + minHeight += ui->skipButton->height() + ui->verticalLayout->spacing(); + minHeight = std::max(minHeight, 60); QSize minSize = QSize(480, minHeight); + setMinimumSize(minSize); + adjustSize(); + + QSize newSize = this->size(); // if the current window is too small if ((lastSize != minSize) && (lastSize.height() < minSize.height())) { - resize(minSize); - - QSize newSize = this->size(); QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative // center on old position after resize QPoint newPos(lastPos.x() + (sizeDiff.width() / 2), lastPos.y() + (sizeDiff.height() / 2)); this->move(newPos); } - setMinimumSize(minSize); - } int ProgressDialog::execWithTask(Task* task) @@ -211,7 +210,9 @@ void ProgressDialog::onTaskSucceeded() void ProgressDialog::changeStatus(const QString& status) { ui->globalStatusLabel->setText(task->getStatus()); + ui->globalStatusLabel->adjustSize(); ui->globalStatusDetailsLabel->setText(task->getDetails()); + ui->globalStatusDetailsLabel->adjustSize(); updateSize(); } -- cgit From 73d83439140377a7ece34e262ca4efab1608a03d Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 2 Jul 2023 22:27:24 -0700 Subject: fix: header `` -> `` Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index f70eee49..c6d8e573 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -34,7 +34,7 @@ */ #include "ProgressDialog.h" -#include +#include #include "ui_ProgressDialog.h" #include -- cgit From 8cb8273e67d4770300fdb7c3ce61feb19b1a899b Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 2 Jul 2023 22:29:45 -0700 Subject: fix: update if new size is larger Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index c6d8e573..f422d91e 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -113,7 +113,7 @@ void ProgressDialog::updateSize() QSize newSize = this->size(); // if the current window is too small - if ((lastSize != minSize) && (lastSize.height() < minSize.height())) + if ((lastSize != minSize) && (lastSize.height() < newSize.height())) { QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative // center on old position after resize -- cgit From e5b9bfb2e78ca86917d91fd41de1e797e570cf83 Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sun, 2 Jul 2023 22:30:25 -0700 Subject: fix: update if new size is larger Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index f422d91e..3368a8c4 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -113,7 +113,7 @@ void ProgressDialog::updateSize() QSize newSize = this->size(); // if the current window is too small - if ((lastSize != minSize) && (lastSize.height() < newSize.height())) + if ((lastSize != newSize) && (lastSize.height() < newSize.height())) { QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative // center on old position after resize -- cgit From 026293f7731181b1198c3c5a9552dd340d13b4b5 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 3 Jul 2023 14:17:39 +0300 Subject: updated option text Signed-off-by: Trial97 --- launcher/ui/pages/instance/ExternalResourcesPage.ui | 2 +- launcher/ui/pages/instance/ModFolderPage.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 351aaf75..3c836691 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -162,7 +162,7 @@ false
    - Visit on mod's page + Visit mod's page Go to mods home page diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 1d31a292..ce6968f5 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -104,7 +104,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr auto selected = std::count_if(mods_list.cbegin(), mods_list.cend(), [](Mod* v) { return v->metadata() != nullptr || v->homeurl().size() != 0; }); if (selected <= 1) { - ui->actionVisitItemPage->setText(tr("Visit on mod's page")); + ui->actionVisitItemPage->setText(tr("Visit mod's page")); ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); } else { ui->actionVisitItemPage->setText(tr("Visit the pages of the selected mods")); -- cgit From f0aab541f817347a932c65d3b06d2d4c1e7b90c1 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 3 Jul 2023 15:09:35 +0300 Subject: fixed typo Signed-off-by: Trial97 --- launcher/ui/widgets/InfoFrame.cpp | 91 +++++++++++++++------------------------ 1 file changed, 34 insertions(+), 57 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 24349014..b16bc097 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -43,7 +43,7 @@ #include "ui/dialogs/CustomMessageBox.h" -void setupLinkTooTip(QLabel* label) +void setupLinkToolTip(QLabel* label) { QObject::connect(label, &QLabel::linkHovered, [label](const QString& link) { if (!link.isEmpty() && !link.startsWith("http")) @@ -60,11 +60,11 @@ InfoFrame::InfoFrame(QWidget* parent) : QFrame(parent), ui(new Ui::InfoFrame) ui->licenseLabel->setHidden(true); ui->issueTrackerLabel->setHidden(true); - setupLinkTooTip(ui->iconLabel); - setupLinkTooTip(ui->descriptionLabel); - setupLinkTooTip(ui->nameLabel); - setupLinkTooTip(ui->licenseLabel); - setupLinkTooTip(ui->issueTrackerLabel); + setupLinkToolTip(ui->iconLabel); + setupLinkToolTip(ui->descriptionLabel); + setupLinkToolTip(ui->nameLabel); + setupLinkToolTip(ui->licenseLabel); + setupLinkToolTip(ui->issueTrackerLabel); updateHiddenState(); } @@ -123,9 +123,9 @@ void InfoFrame::updateWithMod(Mod const& m) licenseText += "" + l.url + ""; } if (!l.description.isEmpty() && l.description != l.name) { - licenseText += " " + l.description; + licenseText += " " + l.description; } - } + } } if (!licenseText.isEmpty()) { setLicense(tr("License: %1").arg(licenseText)); @@ -137,7 +137,7 @@ void InfoFrame::updateWithMod(Mod const& m) if (!m.issueTracker().isEmpty()) { issueTracker += tr("Report issues to: "); issueTracker += "" + m.issueTracker() + ""; - } + } setIssueTracker(issueTracker); } @@ -147,7 +147,8 @@ void InfoFrame::updateWithResource(const Resource& resource) setImage(); } -QString InfoFrame::renderColorCodes(QString input) { +QString InfoFrame::renderColorCodes(QString input) +{ // We have to manually set the colors for use. // // A color is set using §x, with x = a hex number from 0 to f. @@ -158,16 +159,12 @@ QString InfoFrame::renderColorCodes(QString input) { // TODO: Wrap links inside tags // https://minecraft.fandom.com/wiki/Formatting_codes#Color_codes - const QMap color_codes_map = { - {'0', "#000000"}, {'1', "#0000AA"}, {'2', "#00AA00"}, {'3', "#00AAAA"}, {'4', "#AA0000"}, - {'5', "#AA00AA"}, {'6', "#FFAA00"}, {'7', "#AAAAAA"}, {'8', "#555555"}, {'9', "#5555FF"}, - {'a', "#55FF55"}, {'b', "#55FFFF"}, {'c', "#FF5555"}, {'d', "#FF55FF"}, {'e', "#FFFF55"}, - {'f', "#FFFFFF"} - }; + const QMap color_codes_map = { { '0', "#000000" }, { '1', "#0000AA" }, { '2', "#00AA00" }, { '3', "#00AAAA" }, + { '4', "#AA0000" }, { '5', "#AA00AA" }, { '6', "#FFAA00" }, { '7', "#AAAAAA" }, + { '8', "#555555" }, { '9', "#5555FF" }, { 'a', "#55FF55" }, { 'b', "#55FFFF" }, + { 'c', "#FF5555" }, { 'd', "#FF55FF" }, { 'e', "#FFFF55" }, { 'f', "#FFFFFF" } }; // https://minecraft.fandom.com/wiki/Formatting_codes#Formatting_codes - const QMap formatting_codes_map = { - {'l', "b"}, {'m', "s"}, {'n', "u"}, {'o', "i"} - }; + const QMap formatting_codes_map = { { 'l', "b" }, { 'm', "s" }, { 'n', "u" }, { 'o', "i" } }; QString html(""); QList tags{}; @@ -212,14 +209,14 @@ void InfoFrame::updateWithResourcePack(ResourcePack& resource_pack) { setName(renderColorCodes(resource_pack.name())); setDescription(renderColorCodes(resource_pack.description())); - setImage(resource_pack.image({64, 64})); + setImage(resource_pack.image({ 64, 64 })); } void InfoFrame::updateWithTexturePack(TexturePack& texture_pack) { setName(renderColorCodes(texture_pack.name())); setDescription(renderColorCodes(texture_pack.description())); - setImage(texture_pack.image({64, 64})); + setImage(texture_pack.image({ 64, 64 })); } void InfoFrame::clear() @@ -268,9 +265,8 @@ void InfoFrame::setDescription(QString text) QChar rem('\n'); QString finaltext; finaltext.reserve(intermediatetext.size()); - foreach(const QChar& c, intermediatetext) - { - if(c == rem && prev){ + foreach (const QChar& c, intermediatetext) { + if (c == rem && prev) { continue; } prev = c == rem; @@ -278,17 +274,14 @@ void InfoFrame::setDescription(QString text) } QString labeltext; labeltext.reserve(300); - if(finaltext.length() > 290) - { + if (finaltext.length() > 290) { ui->descriptionLabel->setOpenExternalLinks(false); ui->descriptionLabel->setTextFormat(Qt::TextFormat::RichText); m_description = text; // This allows injecting HTML here. labeltext.append("" + finaltext.left(287) + "..."); QObject::connect(ui->descriptionLabel, &QLabel::linkActivated, this, &InfoFrame::descriptionEllipsisHandler); - } - else - { + } else { ui->descriptionLabel->setTextFormat(Qt::TextFormat::AutoText); labeltext.append(finaltext); } @@ -297,14 +290,11 @@ void InfoFrame::setDescription(QString text) void InfoFrame::setLicense(QString text) { - if(text.isEmpty()) - { + if (text.isEmpty()) { ui->licenseLabel->setHidden(true); updateHiddenState(); return; - } - else - { + } else { ui->licenseLabel->setHidden(false); updateHiddenState(); } @@ -314,9 +304,8 @@ void InfoFrame::setLicense(QString text) QChar rem('\n'); QString finaltext; finaltext.reserve(intermediatetext.size()); - foreach(const QChar& c, intermediatetext) - { - if(c == rem && prev){ + foreach (const QChar& c, intermediatetext) { + if (c == rem && prev) { continue; } prev = c == rem; @@ -324,17 +313,14 @@ void InfoFrame::setLicense(QString text) } QString labeltext; labeltext.reserve(300); - if(finaltext.length() > 290) - { + if (finaltext.length() > 290) { ui->licenseLabel->setOpenExternalLinks(false); ui->licenseLabel->setTextFormat(Qt::TextFormat::RichText); m_description = text; // This allows injecting HTML here. labeltext.append("" + finaltext.left(287) + "..."); QObject::connect(ui->licenseLabel, &QLabel::linkActivated, this, &InfoFrame::licenseEllipsisHandler); - } - else - { + } else { ui->licenseLabel->setTextFormat(Qt::TextFormat::AutoText); labeltext.append(finaltext); } @@ -343,12 +329,9 @@ void InfoFrame::setLicense(QString text) void InfoFrame::setIssueTracker(QString text) { - if(text.isEmpty()) - { + if (text.isEmpty()) { ui->issueTrackerLabel->setHidden(true); - } - else - { + } else { ui->issueTrackerLabel->setText(text); ui->issueTrackerLabel->setHidden(false); } @@ -367,28 +350,22 @@ void InfoFrame::setImage(QPixmap img) void InfoFrame::descriptionEllipsisHandler(QString link) { - if(!m_current_box) - { + if (!m_current_box) { m_current_box = CustomMessageBox::selectable(this, "", m_description); connect(m_current_box, &QMessageBox::finished, this, &InfoFrame::boxClosed); m_current_box->show(); - } - else - { + } else { m_current_box->setText(m_description); } } void InfoFrame::licenseEllipsisHandler(QString link) { - if(!m_current_box) - { + if (!m_current_box) { m_current_box = CustomMessageBox::selectable(this, "", m_license); connect(m_current_box, &QMessageBox::finished, this, &InfoFrame::boxClosed); m_current_box->show(); - } - else - { + } else { m_current_box->setText(m_license); } } -- cgit From fa7cfc77d8b723a53577734a0a3c76df7d9dc6d7 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Mon, 3 Jul 2023 16:08:20 +0300 Subject: fixed template Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index 1b75908a..b8edf7df 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -36,7 +36,7 @@ #include "modplatform/helpers/HashUtils.h" #include "tasks/Task.h" -const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • \n"; +const QString FlamePackExportTask::TEMPLATE = "
  • {name}{authors}
  • \n"; const QStringList FlamePackExportTask::FILE_EXTENSIONS({ "jar", "zip" }); FlamePackExportTask::FlamePackExportTask(const QString& name, -- cgit From 908ac813e0f96126a643851e99379956faa08cda Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 4 Jul 2023 15:16:54 +0300 Subject: escaped modlist inner html Signed-off-by: Trial97 --- launcher/modplatform/flame/FlamePackExportTask.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/flame/FlamePackExportTask.cpp b/launcher/modplatform/flame/FlamePackExportTask.cpp index b8edf7df..ac0da214 100644 --- a/launcher/modplatform/flame/FlamePackExportTask.cpp +++ b/launcher/modplatform/flame/FlamePackExportTask.cpp @@ -362,9 +362,9 @@ void FlamePackExportTask::buildZip() for (auto mod : resolvedFiles) { if (mod.isMod) { content += QString(TEMPLATE) - .replace("{name}", mod.name) - .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.addonId)) - .replace("{authors}", !mod.authors.isEmpty() ? QString(" (by %1)").arg(mod.authors) : ""); + .replace("{name}", mod.name.toHtmlEscaped()) + .replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.addonId).toHtmlEscaped()) + .replace("{authors}", !mod.authors.isEmpty() ? QString(" (by %1)").arg(mod.authors).toHtmlEscaped() : ""); } } content = "
      " + content + "
    "; -- cgit From 1fbc17d275b99d194906302f98412f78fbb77538 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Tue, 4 Jul 2023 16:38:04 -0400 Subject: Remove break and add fallthrough comment in WorldListPage.cpp Signed-off-by: PandaNinjas --- launcher/ui/pages/instance/WorldListPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index b5dc5a17..b2200b1a 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -338,8 +338,8 @@ void WorldListPage::mceditState(LoggedProcess::State state) case LoggedProcess::Aborted: { failed = true; - break; } + /* fallthrough */ case LoggedProcess::Running: case LoggedProcess::Finished: { -- cgit From 34cf28712c254ba378bdbf728471d0dfbb4ab58f Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Tue, 4 Jul 2023 16:39:24 -0400 Subject: Replace break with return true; Signed-off-by: PandaNinjas --- launcher/ui/setupwizard/JavaWizardPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/setupwizard/JavaWizardPage.cpp b/launcher/ui/setupwizard/JavaWizardPage.cpp index e8833535..2b70c47c 100644 --- a/launcher/ui/setupwizard/JavaWizardPage.cpp +++ b/launcher/ui/setupwizard/JavaWizardPage.cpp @@ -69,7 +69,7 @@ bool JavaWizardPage::validatePage() case JavaSettingsWidget::ValidationStatus::AllOK: { settings->set("JavaPath", m_java_widget->javaPath()); - break; + return true; } case JavaSettingsWidget::ValidationStatus::JavaBad: { -- cgit From 817ecf822583caf3a510f177d40fe8c6b3218165 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Tue, 4 Jul 2023 17:19:08 -0400 Subject: Fix VersionProxyModel.cpp Signed-off-by: PandaNinjas --- launcher/VersionProxyModel.cpp | 51 +++++++++++------------------------------- 1 file changed, 13 insertions(+), 38 deletions(-) (limited to 'launcher') diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 03130b23..91f94f41 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -191,36 +191,21 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const return QVariant(); } } - case Qt::ToolTipRole: { + case Qt::ToolTipRole: + { if (column == Name && hasRecommended) { - auto recommendedValue = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(recommendedValue.toBool()) { + auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); + if (value.toBool()) { return tr("Recommended"); - } - else if(hasLatest) { - auto latestValue = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(latestValue.toBool()) - { - auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if(value.toBool()) - { - return tr("Recommended"); - } - else if(hasLatest) - { - auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) - { - return tr("Latest"); - } - } + } else if(hasLatest) { + auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); + if(value.toBool()) { + return tr("Latest"); } } - else if(index.row() == 0) { - return tr("Latest"); - } + } else { + return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole); } - return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole); } case Qt::DecorationRole: { @@ -255,20 +240,10 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const return pixmap; } } - else if(index.row() == 0) { - return APPLICATION->getThemedIcon("bug"); - } - QPixmap pixmap; - QPixmapCache::find("placeholder", &pixmap); - if(!pixmap) { - QPixmap px(16,16); - px.fill(Qt::transparent); - QPixmapCache::insert("placeholder", px); - return px; + default: + { + return QVariant(); } - return pixmap; - } else { - return QVariant(); } } default: -- cgit From 13d67c6524a29daea51242d17ba0c6a2b8593747 Mon Sep 17 00:00:00 2001 From: PandaNinjas Date: Thu, 6 Jul 2023 08:51:42 -0400 Subject: Keep formatting consistent Signed-off-by: PandaNinjas --- launcher/VersionProxyModel.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp index 91f94f41..63a43465 100644 --- a/launcher/VersionProxyModel.cpp +++ b/launcher/VersionProxyModel.cpp @@ -193,13 +193,16 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const } case Qt::ToolTipRole: { - if (column == Name && hasRecommended) { + if(column == Name && hasRecommended) + { auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole); - if (value.toBool()) { + if(value.toBool()) + { return tr("Recommended"); } else if(hasLatest) { auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole); - if(value.toBool()) { + if(value.toBool()) + { return tr("Latest"); } } -- cgit From 93870c315f84d2bb599d669be8205990ee48907d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 6 Jul 2023 18:46:59 +0300 Subject: better url handling Signed-off-by: Trial97 --- launcher/ui/widgets/InfoFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index b16bc097..a0fda952 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -46,7 +46,7 @@ void setupLinkToolTip(QLabel* label) { QObject::connect(label, &QLabel::linkHovered, [label](const QString& link) { - if (!link.isEmpty() && !link.startsWith("http")) + if (auto url = QUrl(link); !url.isValid() || (url.scheme() != "http" && url.scheme() != "https")) return; label->setToolTip(link); }); -- cgit From 8ae67b84dbf154bef957bfba1342eac27cd4837e Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Thu, 6 Jul 2023 20:03:25 +0100 Subject: Optional mods in mrpack export Signed-off-by: TheKodeToad --- .../modrinth/ModrinthPackExportTask.cpp | 50 +++++++++++++--------- 1 file changed, 30 insertions(+), 20 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index 4cd88aa6..cbdfd04f 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -263,13 +263,13 @@ void ModrinthPackExportTask::finish() QByteArray ModrinthPackExportTask::generateIndex() { - QJsonObject obj; - obj["formatVersion"] = 1; - obj["game"] = "minecraft"; - obj["name"] = name; - obj["versionId"] = version; + QJsonObject out; + out["formatVersion"] = 1; + out["game"] = "minecraft"; + out["name"] = name; + out["versionId"] = version; if (!summary.isEmpty()) - obj["summary"] = summary; + out["summary"] = summary; if (mcInstance) { auto profile = mcInstance->getPackProfile(); @@ -290,30 +290,40 @@ QByteArray ModrinthPackExportTask::generateIndex() if (forge != nullptr) dependencies["forge"] = forge->m_version; - obj["dependencies"] = dependencies; + out["dependencies"] = dependencies; } - QJsonArray files; - QMapIterator iterator(resolvedFiles); - while (iterator.hasNext()) { - iterator.next(); + QJsonArray filesOut; + for (auto iterator = resolvedFiles.constBegin(); iterator != resolvedFiles.constEnd(); iterator++) { + QJsonObject fileOut; + QString path = iterator.key(); const ResolvedFile& value = iterator.value(); - QJsonObject file; - file["path"] = iterator.key(); - file["downloads"] = QJsonArray({ iterator.value().url }); + // detect disabled mod + QString disabledSuffix = ".disabled"; + if (path.endsWith(disabledSuffix)) { + // rename it + path = path.left(path.length() - disabledSuffix.length()); + // ...and make it optional + QJsonObject env; + env["client"] = "optional"; + env["server"] = "optional"; + fileOut["env"] = env; + } + + fileOut["path"] = path; + fileOut["downloads"] = QJsonArray{ iterator.value().url }; QJsonObject hashes; hashes["sha1"] = value.sha1; hashes["sha512"] = value.sha512; + fileOut["hashes"] = hashes; - file["hashes"] = hashes; - file["fileSize"] = value.size; - - files << file; + fileOut["fileSize"] = value.size; + filesOut << fileOut; } - obj["files"] = files; + out["files"] = filesOut; - return QJsonDocument(obj).toJson(QJsonDocument::Compact); + return QJsonDocument(out).toJson(QJsonDocument::Compact); } -- cgit From 073cb91f885b780ae04b6d9a4b94702307f07321 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 7 Jul 2023 15:56:04 +0200 Subject: fix(ui): validate meta override url Signed-off-by: Sefa Eyeoglu --- launcher/ui/pages/global/APIPage.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'launcher') diff --git a/launcher/ui/pages/global/APIPage.cpp b/launcher/ui/pages/global/APIPage.cpp index dca1b3a6..fab31dbd 100644 --- a/launcher/ui/pages/global/APIPage.cpp +++ b/launcher/ui/pages/global/APIPage.cpp @@ -81,6 +81,8 @@ APIPage::APIPage(QWidget *parent) : connect(ui->pasteTypeComboBox, currentIndexChangedSignal, this, &APIPage::updateBaseURLPlaceholder); // This function needs to be called even when the ComboBox's index is still in its default state. updateBaseURLPlaceholder(ui->pasteTypeComboBox->currentIndex()); + // NOTE: this allows http://, but we replace that with https later anyway + ui->metaURL->setValidator(new QRegularExpressionValidator(validUrlRegExp, ui->metaURL)); ui->baseURLEntry->setValidator(new QRegularExpressionValidator(validUrlRegExp, ui->baseURLEntry)); ui->msaClientID->setValidator(new QRegularExpressionValidator(validMSAClientID, ui->msaClientID)); ui->flameKey->setValidator(new QRegularExpressionValidator(validFlameKey, ui->flameKey)); -- cgit From 6fcdac0d36865eadc2454244ce03c77e6eed767b Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 7 Jul 2023 15:57:24 +0200 Subject: fix: reset invalid meta url on launch Signed-off-by: Sefa Eyeoglu --- launcher/Application.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 1d97a5f2..34e1320a 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -687,8 +687,16 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) m_settings->reset("PastebinCustomAPIBase"); } } - // meta URL - m_settings->registerSetting("MetaURLOverride", ""); + { + // Meta URL + m_settings->registerSetting("MetaURLOverride", ""); + + QUrl metaUrl = m_settings->get("MetaURLOverride").toString(); + + // get rid of invalid meta urls + if (!metaUrl.isValid() || metaUrl.scheme() != "http" || metaUrl.scheme() != "https") + m_settings->reset("MetaURLOverride"); + } m_settings->registerSetting("CloseAfterLaunch", false); m_settings->registerSetting("QuitAfterGameStop", false); -- cgit From 3139af8487ae8ea20468023e477be02cf0b96a4d Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 7 Jul 2023 17:12:10 +0300 Subject: Made action text simpler Signed-off-by: Trial97 --- launcher/ui/pages/instance/ModFolderPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index ce6968f5..fe2f21c9 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -107,7 +107,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionVisitItemPage->setText(tr("Visit mod's page")); ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); } else { - ui->actionVisitItemPage->setText(tr("Visit the pages of the selected mods")); + ui->actionVisitItemPage->setText(tr("Visit mods pages")); ui->actionVisitItemPage->setToolTip(tr("Go to the pages of the selected mods")); } ui->actionVisitItemPage->setEnabled(selected != 0); -- cgit From b8482a5d89b4044482e7b55aa1c2e2547b41f4fd Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Fri, 7 Jul 2023 15:53:50 +0100 Subject: Update ModFolderPage.cpp Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/ModFolderPage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index fe2f21c9..041d1bfd 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -107,7 +107,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr ui->actionVisitItemPage->setText(tr("Visit mod's page")); ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); } else { - ui->actionVisitItemPage->setText(tr("Visit mods pages")); + ui->actionVisitItemPage->setText(tr("Visit mods' pages")); ui->actionVisitItemPage->setToolTip(tr("Go to the pages of the selected mods")); } ui->actionVisitItemPage->setEnabled(selected != 0); @@ -303,4 +303,4 @@ void ModFolderPage::visitModPages() if (!url.isEmpty()) DesktopServices::openUrl(url); } -} \ No newline at end of file +} -- cgit From 51e62761ee8e8cd868c5f2a7eb63d54de5b71d6a Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 7 Jul 2023 19:25:12 +0200 Subject: fix: improve QUrl construction Signed-off-by: Sefa Eyeoglu --- launcher/Application.cpp | 2 +- launcher/ui/pages/global/APIPage.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'launcher') diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 34e1320a..7858d713 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -691,7 +691,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) // Meta URL m_settings->registerSetting("MetaURLOverride", ""); - QUrl metaUrl = m_settings->get("MetaURLOverride").toString(); + QUrl metaUrl(m_settings->get("MetaURLOverride").toString()); // get rid of invalid meta urls if (!metaUrl.isValid() || metaUrl.scheme() != "http" || metaUrl.scheme() != "https") diff --git a/launcher/ui/pages/global/APIPage.cpp b/launcher/ui/pages/global/APIPage.cpp index fab31dbd..668aa007 100644 --- a/launcher/ui/pages/global/APIPage.cpp +++ b/launcher/ui/pages/global/APIPage.cpp @@ -165,7 +165,7 @@ void APIPage::applySettings() QString msaClientID = ui->msaClientID->text(); s->set("MSAClientIDOverride", msaClientID); - QUrl metaURL = ui->metaURL->text(); + QUrl metaURL(ui->metaURL->text()); // Add required trailing slash if (!metaURL.isEmpty() && !metaURL.path().endsWith('/')) { -- cgit From 20c781b23b0d2bd2be8bed0c015eb6c82312c29a Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Sat, 8 Jul 2023 02:28:37 -0700 Subject: fix(progress dialog): if there is a parent center on creation Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 23 +++++++++++++++-------- launcher/ui/dialogs/ProgressDialog.h | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 3368a8c4..4243e291 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -67,9 +67,9 @@ ProgressDialog::ProgressDialog(QWidget* parent) : QDialog(parent), ui(new Ui::Pr ui->taskProgressScrollArea->setHidden(true); this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); setAttribute(Qt::WidgetAttribute::WA_QuitOnClose, true); - setSkipButton(false); changeProgress(0, 100); - updateSize(); + updateSize(true); + setSkipButton(false); } void ProgressDialog::setSkipButton(bool present, QString label) @@ -95,7 +95,7 @@ ProgressDialog::~ProgressDialog() delete ui; } -void ProgressDialog::updateSize() +void ProgressDialog::updateSize(bool recenterParent) { QSize lastSize = this->size(); QPoint lastPos = this->pos(); @@ -112,13 +112,20 @@ void ProgressDialog::updateSize() adjustSize(); QSize newSize = this->size(); - // if the current window is too small - if ((lastSize != newSize) && (lastSize.height() < newSize.height())) + // if the current window is a different size + auto parent = this->parentWidget(); + if (recenterParent && parent) { + auto newX = std::max(0, parent->x() + ((parent->width() - newSize.width()) / 2)); + auto newY = std::max(0, parent->y() + ((parent->height() - newSize.height()) / 2)); + this->move(newX, newY); + } + else if (lastSize != newSize) { - QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative // center on old position after resize - QPoint newPos(lastPos.x() + (sizeDiff.width() / 2), lastPos.y() + (sizeDiff.height() / 2)); - this->move(newPos); + QSize sizeDiff = lastSize - newSize; // last size was smaller, the results should be negative + auto newX = std::max(0, lastPos.x() + (sizeDiff.width() / 2)); + auto newY = std::max(0, lastPos.y() + (sizeDiff.height() / 2)); + this->move(newX, newY); } } diff --git a/launcher/ui/dialogs/ProgressDialog.h b/launcher/ui/dialogs/ProgressDialog.h index fc9a0fbc..f062be08 100644 --- a/launcher/ui/dialogs/ProgressDialog.h +++ b/launcher/ui/dialogs/ProgressDialog.h @@ -62,7 +62,7 @@ public: explicit ProgressDialog(QWidget *parent = 0); ~ProgressDialog(); - void updateSize(); + void updateSize(bool recenterParent = false); int execWithTask(Task* task); int execWithTask(std::unique_ptr &&task); -- cgit From 0c6362f28d1caec4d256c538d2874b226390ad85 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 8 Jul 2023 18:51:28 +0100 Subject: Make trash hungry Signed-off-by: TheKodeToad --- launcher/minecraft/mod/Mod.cpp | 4 ++-- launcher/minecraft/mod/Mod.h | 2 +- launcher/minecraft/mod/ModFolderModel.cpp | 6 +++--- launcher/minecraft/mod/Resource.cpp | 8 ++------ launcher/minecraft/mod/Resource.h | 2 +- launcher/minecraft/mod/ResourceFolderModel.cpp | 2 +- launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp | 2 +- 7 files changed, 11 insertions(+), 15 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index fa1a0253..880dacb1 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -126,7 +126,7 @@ bool Mod::applyFilter(QRegularExpression filter) const return Resource::applyFilter(filter); } -auto Mod::destroy(QDir& index_dir, bool preserve_metadata) -> bool +auto Mod::destroy(QDir& index_dir, bool preserve_metadata, bool attempt_trash) -> bool { if (!preserve_metadata) { qDebug() << QString("Destroying metadata for '%1' on purpose").arg(name()); @@ -139,7 +139,7 @@ auto Mod::destroy(QDir& index_dir, bool preserve_metadata) -> bool } } - return Resource::destroy(); + return Resource::destroy(attempt_trash); } auto Mod::details() const -> const ModDetails& diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index d6272f4d..b67bd465 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -93,7 +93,7 @@ public: [[nodiscard]] bool applyFilter(QRegularExpression filter) const override; // Delete all the files of this mod - auto destroy(QDir& index_dir, bool preserve_metadata = false) -> bool; + auto destroy(QDir& index_dir, bool preserve_metadata = false, bool attempt_trash = true) -> bool; void finishResolvingWithDetails(ModDetails&& details); diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index af98d834..50f96b72 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -199,10 +199,10 @@ Task* ModFolderModel::createParseTask(Resource& resource) bool ModFolderModel::uninstallMod(const QString& filename, bool preserve_metadata) { - for(auto mod : allMods()){ - if(mod->fileinfo().fileName() == filename){ + for(auto mod : allMods()) { + if(mod->fileinfo().fileName() == filename) { auto index_dir = indexDir(); - mod->destroy(index_dir, preserve_metadata); + mod->destroy(index_dir, preserve_metadata, false); update(); diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index e5077260..098a617f 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -148,14 +148,10 @@ bool Resource::enable(EnableAction action) return true; } -bool Resource::destroy() +bool Resource::destroy(bool attemptTrash) { m_type = ResourceType::UNKNOWN; - - if (FS::trash(m_file_info.filePath())) - return true; - - return FS::deletePath(m_file_info.filePath()); + return (attemptTrash && FS::trash(m_file_info.filePath())) || FS::deletePath(m_file_info.filePath()); } bool Resource::isSymLinkUnder(const QString& instPath) const diff --git a/launcher/minecraft/mod/Resource.h b/launcher/minecraft/mod/Resource.h index a5e9ae91..94f3160c 100644 --- a/launcher/minecraft/mod/Resource.h +++ b/launcher/minecraft/mod/Resource.h @@ -92,7 +92,7 @@ class Resource : public QObject { } // Delete all files of this resource. - bool destroy(); + bool destroy(bool attemptTrash = true); [[nodiscard]] auto isSymLink() const -> bool { return m_file_info.isSymLink(); } diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 7700fd36..79169ae8 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -159,7 +159,7 @@ bool ResourceFolderModel::uninstallResource(QString file_name) { for (auto& resource : m_resources) { if (resource->fileinfo().fileName() == file_name) { - auto res = resource->destroy(); + auto res = resource->destroy(false); update(); diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index 3677a1dc..ef353c70 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -103,7 +103,7 @@ void ModFolderLoadTask::executeTask() while (iter.hasNext()) { auto mod = iter.next().value(); if (mod->status() == ModStatus::NotInstalled) { - mod->destroy(m_index_dir, false); + mod->destroy(m_index_dir, false, false); iter.remove(); } } -- cgit From 08c140b9b45b1a8afd134793acedf867526d6432 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 8 Jul 2023 20:51:27 +0100 Subject: Fix actionVisitItemPage insersion, and prevent widebar segfault Signed-off-by: TheKodeToad --- launcher/ui/pages/instance/ModFolderPage.cpp | 2 +- launcher/ui/widgets/WideBar.cpp | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 041d1bfd..9f077618 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -89,7 +89,7 @@ ModFolderPage::ModFolderPage(BaseInstance* inst, std::shared_ptr connect(ui->actionUpdateItem, &QAction::triggered, this, &ModFolderPage::updateMods); ui->actionVisitItemPage->setToolTip(tr("Go to mod's home page")); - ui->actionsToolbar->insertActionAfter(ui->actionViewFolder, ui->actionVisitItemPage); + ui->actionsToolbar->addAction(ui->actionVisitItemPage); connect(ui->actionVisitItemPage, &QAction::triggered, this, &ModFolderPage::visitModPages); auto check_allow_update = [this] { diff --git a/launcher/ui/widgets/WideBar.cpp b/launcher/ui/widgets/WideBar.cpp index ac34e3aa..a77c45fe 100644 --- a/launcher/ui/widgets/WideBar.cpp +++ b/launcher/ui/widgets/WideBar.cpp @@ -116,12 +116,21 @@ void WideBar::insertActionAfter(QAction* after, QAction* action) if (iter == m_entries.end()) return; + iter++; + // the action to insert after is present + // however, the element after it isn't valid + if (iter == m_entries.end()) { + // append the action instead of inserting it + addAction(action); + return; + } + BarEntry entry; - entry.bar_action = insertWidget((iter + 1)->bar_action, new ActionButton(action, this, m_use_default_action)); + entry.bar_action = insertWidget(iter->bar_action, new ActionButton(action, this, m_use_default_action)); entry.menu_action = action; entry.type = BarEntry::Type::Action; - m_entries.insert(iter + 1, entry); + m_entries.insert(iter, entry); m_menu_state = MenuState::Dirty; } -- cgit From d53d58a5d42684c5151680016f38a0f4bd1c0298 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 8 Jul 2023 22:03:47 +0100 Subject: LiteMod downloading Signed-off-by: TheKodeToad --- launcher/minecraft/PackProfile.cpp | 3 ++- launcher/modplatform/flame/FlameAPI.h | 2 ++ launcher/modplatform/modrinth/ModrinthAPI.h | 6 +++--- launcher/ui/dialogs/ResourceDownloadDialog.cpp | 9 +++++++-- 4 files changed, 14 insertions(+), 6 deletions(-) (limited to 'launcher') diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp index aff05dbc..e8fd2157 100644 --- a/launcher/minecraft/PackProfile.cpp +++ b/launcher/minecraft/PackProfile.cpp @@ -65,7 +65,8 @@ static const QMap modloaderMapping{ {"net.minecraftforge", ResourceAPI::Forge}, {"net.fabricmc.fabric-loader", ResourceAPI::Fabric}, - {"org.quiltmc.quilt-loader", ResourceAPI::Quilt} + {"org.quiltmc.quilt-loader", ResourceAPI::Quilt}, + {"com.mumfrey.liteloader", ResourceAPI::LiteLoader} }; PackProfile::PackProfile(MinecraftInstance * instance) diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 0a6dc78f..49bc316f 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -23,6 +23,8 @@ class FlameAPI : public NetworkResourceAPI { [[nodiscard]] auto getSortingMethods() const -> QList override; + static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool { return loaders & (Forge | Fabric | Quilt); } + private: static int getClassId(ModPlatform::ResourceType type) { diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index e83ed2bf..58af14cc 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -38,7 +38,7 @@ class ModrinthAPI : public NetworkResourceAPI { static auto getModLoaderStrings(const ModLoaderTypes types) -> const QStringList { QStringList l; - for (auto loader : { Forge, Fabric, Quilt }) { + for (auto loader : { Forge, Fabric, Quilt, LiteLoader }) { if (types & loader) { l << getModLoaderString(loader); } @@ -92,7 +92,7 @@ class ModrinthAPI : public NetworkResourceAPI { { if (args.loaders.has_value()) { if (!validateModLoaders(args.loaders.value())) { - qWarning() << "Modrinth only have Forge and Fabric-compatible mods!"; + qWarning() << "Modrinth - or our interface - does not support any the provided mod loaders!"; return {}; } } @@ -141,7 +141,7 @@ class ModrinthAPI : public NetworkResourceAPI { return s.isEmpty() ? QString() : s; } - inline auto validateModLoaders(ModLoaderTypes loaders) const -> bool { return loaders & (Forge | Fabric | Quilt); } + static inline auto validateModLoaders(ModLoaderTypes loaders) -> bool { return loaders & (Forge | Fabric | Quilt | LiteLoader); } [[nodiscard]] std::optional getDependencyURL(DependencySearchArgs const& args) const override { diff --git a/launcher/ui/dialogs/ResourceDownloadDialog.cpp b/launcher/ui/dialogs/ResourceDownloadDialog.cpp index 4f59f560..b17eced3 100644 --- a/launcher/ui/dialogs/ResourceDownloadDialog.cpp +++ b/launcher/ui/dialogs/ResourceDownloadDialog.cpp @@ -43,6 +43,8 @@ #include "ui/pages/modplatform/flame/FlameResourcePages.h" #include "ui/pages/modplatform/modrinth/ModrinthResourcePages.h" +#include "modplatform/flame/FlameAPI.h" +#include "modplatform/modrinth/ModrinthAPI.h" #include "ui/widgets/PageContainer.h" namespace ResourceDownload { @@ -281,8 +283,11 @@ QList ModDownloadDialog::getPages() { QList pages; - pages.append(ModrinthModPage::create(this, *m_instance)); - if (APPLICATION->capabilities() & Application::SupportsFlame) + auto loaders = static_cast(m_instance)->getPackProfile()->getModLoaders().value(); + + if (ModrinthAPI::validateModLoaders(loaders)) + pages.append(ModrinthModPage::create(this, *m_instance)); + if (APPLICATION->capabilities() & Application::SupportsFlame && FlameAPI::validateModLoaders(loaders)) pages.append(FlameModPage::create(this, *m_instance)); m_selectedPage = dynamic_cast(pages[0]); -- cgit From 6e2fcc9e1102d3955a509c3346b8df15ce52a6a1 Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sun, 9 Jul 2023 12:08:15 +0100 Subject: Replace string manipulation in favour of QFileInfo Signed-off-by: TheKodeToad --- launcher/modplatform/modrinth/ModrinthPackExportTask.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'launcher') diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp index cbdfd04f..50f6a33c 100644 --- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp +++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp @@ -301,10 +301,10 @@ QByteArray ModrinthPackExportTask::generateIndex() const ResolvedFile& value = iterator.value(); // detect disabled mod - QString disabledSuffix = ".disabled"; - if (path.endsWith(disabledSuffix)) { + const QFileInfo pathInfo(path); + if (pathInfo.suffix() == "disabled") { // rename it - path = path.left(path.length() - disabledSuffix.length()); + path = pathInfo.dir().filePath(pathInfo.completeBaseName()); // ...and make it optional QJsonObject env; env["client"] = "optional"; -- cgit From 159f14c0768a1cd8ab99b8a46f2021d163e6740c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 9 Jul 2023 22:47:38 +0300 Subject: feat:unlocked versions page Signed-off-by: Trial97 --- launcher/ui/pages/instance/VersionPage.cpp | 313 +++++++++++------------------ launcher/ui/pages/instance/VersionPage.h | 55 ++--- 2 files changed, 138 insertions(+), 230 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 59107c53..7db1b19f 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -40,14 +40,13 @@ #include "Application.h" -#include -#include +#include #include #include +#include +#include #include -#include #include -#include #include #include @@ -55,49 +54,42 @@ #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/dialogs/VersionSelectDialog.h" #include "ui/GuiUtil.h" +#include "DesktopServices.h" +#include "Exception.h" +#include "Version.h" +#include "icons/IconList.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 -{ +class IconProxy : public QIdentityProxyModel { Q_OBJECT -public: - - IconProxy(QWidget *parentWidget) : QIdentityProxyModel(parentWidget) + 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 + 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()) - { + if (column == 0 && role == Qt::DecorationRole && m_parentWidget) { + if (!var.isNull()) { auto string = var.toString(); - if(string == "warning") - { + if (string == "warning") { return APPLICATION->getThemedIcon("status-yellow"); - } - else if(string == "error") - { + } else if (string == "error") { return APPLICATION->getThemedIcon("status-bad"); } } @@ -105,14 +97,11 @@ public: } return var; } -private slots: - void widgetGone() - { - m_parentWidget = nullptr; - } + private slots: + void widgetGone() { m_parentWidget = nullptr; } -private: - QWidget *m_parentWidget = nullptr; + private: + QWidget* m_parentWidget = nullptr; }; QIcon VersionPage::icon() const @@ -144,15 +133,14 @@ void VersionPage::closedImpl() m_wide_bar_setting->set(ui->toolBar->getVisibilityState()); } -QMenu * VersionPage::createPopupMenu() +QMenu* VersionPage::createPopupMenu() { QMenu* filteredMenu = QMainWindow::createPopupMenu(); - filteredMenu->removeAction( ui->toolBar->toggleViewAction() ); + filteredMenu->removeAction(ui->toolBar->toggleViewAction()); return filteredMenu; } -VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent) - : QMainWindow(parent), ui(new Ui::VersionPage), m_inst(inst) +VersionPage::VersionPage(MinecraftInstance* inst, QWidget* parent) : QMainWindow(parent), ui(new Ui::VersionPage), m_inst(inst) { ui->setupUi(this); @@ -182,10 +170,8 @@ VersionPage::VersionPage(MinecraftInstance *inst, QWidget *parent) 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); } @@ -202,18 +188,16 @@ void VersionPage::showContextMenu(const QPoint& pos) delete menu; } -void VersionPage::packageCurrent(const QModelIndex ¤t, const QModelIndex &previous) +void VersionPage::packageCurrent(const QModelIndex& current, const QModelIndex& previous) { - if (!current.isValid()) - { + if (!current.isValid()) { ui->frame->clear(); return; } int row = current.row(); auto patch = m_profile->getComponent(row); auto severity = patch->getProblemSeverity(); - switch(severity) - { + switch (severity) { case ProblemSeverity::Warning: ui->frame->setName(tr("%1 possibly has issues.").arg(patch->getName())); break; @@ -226,16 +210,12 @@ void VersionPage::packageCurrent(const QModelIndex ¤t, const QModelIndex & return; } - auto &problems = patch->getProblems(); + auto& problems = patch->getProblems(); QString problemOut; - for (auto &problem: problems) - { - if(problem.m_severity == ProblemSeverity::Error) - { + for (auto& problem : problems) { + if (problem.m_severity == ProblemSeverity::Error) { problemOut += tr("Error: "); - } - else if(problem.m_severity == ProblemSeverity::Warning) - { + } else if (problem.m_severity == ProblemSeverity::Warning) { problemOut += tr("Warning: "); } problemOut += problem.m_description; @@ -244,71 +224,56 @@ void VersionPage::packageCurrent(const QModelIndex ¤t, const QModelIndex & ui->frame->setDescription(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")); - ui->actionInstall_Forge->setEnabled(controlsEnabled); + ui->actionInstall_Forge->setEnabled(true); bool supportsFabric = minecraftVersion >= Version("1.14"); - ui->actionInstall_Fabric->setEnabled(controlsEnabled && supportsFabric); + ui->actionInstall_Fabric->setEnabled(supportsFabric); bool supportsQuilt = minecraftVersion >= Version("1.14"); - ui->actionInstall_Quilt->setEnabled(controlsEnabled && supportsQuilt); + ui->actionInstall_Quilt->setEnabled(supportsQuilt); bool supportsLiteLoader = minecraftVersion <= Version("1.12.2"); - ui->actionInstall_LiteLoader->setEnabled(controlsEnabled && supportsLiteLoader); + ui->actionInstall_LiteLoader->setEnabled(supportsLiteLoader); updateButtons(); } void VersionPage::updateButtons(int row) { - if(row == -1) + 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->actionImport_Components->setEnabled(controlsEnabled); - ui->actionReload->setEnabled(controlsEnabled); - ui->actionReplace_Minecraft_jar->setEnabled(controlsEnabled); - ui->actionAdd_to_Minecraft_jar->setEnabled(controlsEnabled); - ui->actionAdd_Agents->setEnabled(controlsEnabled); + ui->actionRemove->setEnabled(patch && patch->isRemovable()); + ui->actionMove_down->setEnabled(patch && patch->isMoveable()); + ui->actionMove_up->setEnabled(patch && patch->isMoveable()); + ui->actionChange_version->setEnabled(patch && patch->isVersionChangeable()); + ui->actionEdit->setEnabled(patch && patch->isCustom()); + ui->actionCustomize->setEnabled(patch && patch->isCustomizable()); + ui->actionRevert->setEnabled(patch && patch->isRevertible()); + ui->actionDownload_All->setEnabled(true); + ui->actionAdd_Empty->setEnabled(true); + ui->actionImport_Components->setEnabled(true); + ui->actionReload->setEnabled(true); + ui->actionReplace_Minecraft_jar->setEnabled(true); + ui->actionAdd_to_Minecraft_jar->setEnabled(true); + ui->actionAdd_Agents->setEnabled(true); } bool VersionPage::reloadPackProfile() { - try - { + try { m_profile->reload(Net::Mode::Online); return true; - } - catch (const Exception &e) - { + } 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.")); + } catch (...) { + QMessageBox::critical(this, tr("Error"), tr("Couldn't load the instance profile.")); return false; } } @@ -321,14 +286,12 @@ void VersionPage::on_actionReload_triggered() void VersionPage::on_actionRemove_triggered() { - if (!ui->packageView->currentIndex().isValid()) - { + if (!ui->packageView->currentIndex().isValid()) { return; } int index = ui->packageView->currentIndex().row(); auto component = m_profile->getComponent(index); - if (component->isCustom()) - { + if (component->isCustom()) { auto response = CustomMessageBox::selectable(this, tr("Confirm Removal"), tr("You are about to remove \"%1\".\n" "This is permanent and will completely remove the custom component.\n\n" @@ -341,8 +304,7 @@ void VersionPage::on_actionRemove_triggered() return; } // FIXME: use actual model, not reloading. - if (!m_profile->remove(index)) - { + if (!m_profile->remove(index)) { QMessageBox::critical(this, tr("Error"), tr("Couldn't remove file")); } updateButtons(); @@ -352,17 +314,16 @@ void VersionPage::on_actionRemove_triggered() void VersionPage::on_actionInstall_mods_triggered() { - if(m_container) - { + 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()) - { + 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(); @@ -370,9 +331,9 @@ void VersionPage::on_actionAdd_to_Minecraft_jar_triggered() 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()) - { + 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(); @@ -406,12 +367,9 @@ void VersionPage::on_actionAdd_Agents_triggered() void VersionPage::on_actionMove_up_triggered() { - try - { + try { m_profile->move(currentRow(), PackProfile::MoveUp); - } - catch (const Exception &e) - { + } catch (const Exception& e) { QMessageBox::critical(this, tr("Error"), e.cause()); } updateButtons(); @@ -419,12 +377,9 @@ void VersionPage::on_actionMove_up_triggered() void VersionPage::on_actionMove_down_triggered() { - try - { + try { m_profile->move(currentRow(), PackProfile::MoveDown); - } - catch (const Exception &e) - { + } catch (const Exception& e) { QMessageBox::critical(this, tr("Error"), e.cause()); } updateButtons(); @@ -433,39 +388,32 @@ void VersionPage::on_actionMove_down_triggered() void VersionPage::on_actionChange_version_triggered() { auto versionRow = currentRow(); - if(versionRow == -1) - { + if (versionRow == -1) { return; } auto patch = m_profile->getComponent(versionRow); auto name = patch->getName(); auto list = patch->getVersionList(); - if(!list) - { + 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") - { + if (uid == "net.minecraftforge") { on_actionInstall_Forge_triggered(); return; - } - else if (uid == "com.mumfrey.liteloader") - { + } 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" || uid == "org.quiltmc.hashed") - { + if (uid == "net.fabricmc.intermediary" || uid == "org.quiltmc.hashed") { 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()) - { + if (!currentVersion.isEmpty()) { vselect.setCurrentVersion(currentVersion); } if (!vselect.exec() || !vselect.selectedVersion()) @@ -473,8 +421,7 @@ void VersionPage::on_actionChange_version_triggered() qDebug() << "Change" << uid << "to" << vselect.selectedVersion()->descriptor(); bool important = false; - if(uid == "net.minecraft") - { + if (uid == "net.minecraft") { important = true; } m_profile->setComponentVersion(uid, vselect.selectedVersion()->descriptor(), important); @@ -484,19 +431,17 @@ void VersionPage::on_actionChange_version_triggered() void VersionPage::on_actionDownload_All_triggered() { - if (!APPLICATION->accounts()->anyAccountIsValid()) - { - CustomMessageBox::selectable( - this, tr("Error"), - tr("Cannot download Minecraft or update instances unless you have at least " - "one account added.\nPlease add your Mojang or Minecraft account."), - QMessageBox::Warning)->show(); + if (!APPLICATION->accounts()->anyAccountIsValid()) { + CustomMessageBox::selectable(this, tr("Error"), + tr("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) - { + if (!updateTask) { return; } ProgressDialog tDialog(this); @@ -510,28 +455,26 @@ void VersionPage::on_actionDownload_All_triggered() void VersionPage::on_actionInstall_Forge_triggered() { auto vlist = APPLICATION->metadataIndex()->get("net.minecraftforge"); - if(!vlist) - { + 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.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()) - { + if (!currentVersion.isEmpty()) { vselect.setCurrentVersion(currentVersion); } - if (vselect.exec() && vselect.selectedVersion()) - { + 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); + preselect(m_profile->rowCount(QModelIndex()) - 1); m_container->refreshContainer(); } } @@ -539,8 +482,7 @@ void VersionPage::on_actionInstall_Forge_triggered() void VersionPage::on_actionInstall_Fabric_triggered() { auto vlist = APPLICATION->metadataIndex()->get("net.fabricmc.fabric-loader"); - if(!vlist) - { + if (!vlist) { return; } VersionSelectDialog vselect(vlist.get(), tr("Select Fabric Loader version"), this); @@ -548,17 +490,15 @@ void VersionPage::on_actionInstall_Fabric_triggered() 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()) - { + if (!currentVersion.isEmpty()) { vselect.setCurrentVersion(currentVersion); } - if (vselect.exec() && vselect.selectedVersion()) - { + 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); + preselect(m_profile->rowCount(QModelIndex()) - 1); m_container->refreshContainer(); } } @@ -566,8 +506,7 @@ void VersionPage::on_actionInstall_Fabric_triggered() void VersionPage::on_actionInstall_Quilt_triggered() { auto vlist = APPLICATION->metadataIndex()->get("org.quiltmc.quilt-loader"); - if(!vlist) - { + if (!vlist) { return; } VersionSelectDialog vselect(vlist.get(), tr("Select Quilt Loader version"), this); @@ -575,17 +514,15 @@ void VersionPage::on_actionInstall_Quilt_triggered() 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()) - { + if (!currentVersion.isEmpty()) { vselect.setCurrentVersion(currentVersion); } - if (vselect.exec() && vselect.selectedVersion()) - { + 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); + preselect(m_profile->rowCount(QModelIndex()) - 1); m_container->refreshContainer(); } } @@ -594,14 +531,12 @@ void VersionPage::on_actionAdd_Empty_triggered() { NewComponentDialog compdialog(QString(), QString(), this); QStringList blacklist; - for(int i = 0; i < m_profile->rowCount(); i++) - { + 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()) - { + if (compdialog.exec()) { qDebug() << "name:" << compdialog.name(); qDebug() << "uid:" << compdialog.uid(); m_profile->installEmpty(compdialog.uid(), compdialog.name()); @@ -611,28 +546,26 @@ void VersionPage::on_actionAdd_Empty_triggered() void VersionPage::on_actionInstall_LiteLoader_triggered() { auto vlist = APPLICATION->metadataIndex()->get("com.mumfrey.liteloader"); - if(!vlist) - { + 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.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()) - { + if (!currentVersion.isEmpty()) { vselect.setCurrentVersion(currentVersion); } - if (vselect.exec() && vselect.selectedVersion()) - { + 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); + preselect(m_profile->rowCount(QModelIndex()) - 1); m_container->refreshContainer(); } } @@ -647,7 +580,7 @@ void VersionPage::on_actionMinecraftFolder_triggered() DesktopServices::openDirectory(m_inst->gameRoot(), true); } -void VersionPage::versionCurrent(const QModelIndex ¤t, const QModelIndex &previous) +void VersionPage::versionCurrent(const QModelIndex& current, const QModelIndex& previous) { currentIdx = current.row(); updateButtons(currentIdx); @@ -655,16 +588,13 @@ void VersionPage::versionCurrent(const QModelIndex ¤t, const QModelIndex & void VersionPage::preselect(int row) { - if(row < 0) - { + if (row < 0) { row = 0; } - if(row >= m_profile->rowCount(QModelIndex())) - { + if (row >= m_profile->rowCount(QModelIndex())) { row = m_profile->rowCount(QModelIndex()) - 1; } - if(row < 0) - { + if (row < 0) { return; } auto model_index = m_profile->index(row); @@ -680,8 +610,7 @@ void VersionPage::onGameUpdateError(QString error) ComponentPtr VersionPage::current() { auto row = currentRow(); - if(row < 0) - { + if (row < 0) { return nullptr; } return m_profile->getComponent(row); @@ -689,8 +618,7 @@ ComponentPtr VersionPage::current() int VersionPage::currentRow() { - if (ui->packageView->selectionModel()->selectedRows().isEmpty()) - { + if (ui->packageView->selectionModel()->selectedRows().isEmpty()) { return -1; } return ui->packageView->selectionModel()->selectedRows().first().row(); @@ -699,18 +627,15 @@ int VersionPage::currentRow() void VersionPage::on_actionCustomize_triggered() { auto version = currentRow(); - if(version == -1) - { + if (version == -1) { return; } auto patch = m_profile->getComponent(version); - if(!patch->getVersionFile()) - { + if (!patch->getVersionFile()) { // TODO: wait for the update task to finish here... return; } - if(!m_profile->customize(version)) - { + if (!m_profile->customize(version)) { // TODO: some error box here } updateButtons(); @@ -720,13 +645,11 @@ void VersionPage::on_actionCustomize_triggered() void VersionPage::on_actionEdit_triggered() { auto version = current(); - if(!version) - { + if (!version) { return; } auto filename = version->getFilename(); - if(!QFileInfo::exists(filename)) - { + if (!QFileInfo::exists(filename)) { qWarning() << "file" << filename << "can't be opened for editing, doesn't exist!"; return; } @@ -736,8 +659,7 @@ void VersionPage::on_actionEdit_triggered() void VersionPage::on_actionRevert_triggered() { auto version = currentRow(); - if(version == -1) - { + if (version == -1) { return; } auto component = m_profile->getComponent(version); @@ -753,8 +675,7 @@ void VersionPage::on_actionRevert_triggered() if (response != QMessageBox::Yes) return; - if(!m_profile->revertToBase(version)) - { + if (!m_profile->revertToBase(version)) { // TODO: some error box here } updateButtons(); @@ -762,7 +683,7 @@ void VersionPage::on_actionRevert_triggered() m_container->refreshContainer(); } -void VersionPage::onFilterTextChanged(const QString &newContents) +void VersionPage::onFilterTextChanged(const QString& newContents) { m_filterModel->setFilterFixedString(newContents); } diff --git a/launcher/ui/pages/instance/VersionPage.h b/launcher/ui/pages/instance/VersionPage.h index d0087714..45d383f4 100644 --- a/launcher/ui/pages/instance/VersionPage.h +++ b/launcher/ui/pages/instance/VersionPage.h @@ -46,38 +46,27 @@ #include "minecraft/PackProfile.h" #include "ui/pages/BasePage.h" -namespace Ui -{ +namespace Ui { class VersionPage; } -class VersionPage : public QMainWindow, public BasePage -{ +class VersionPage : public QMainWindow, public BasePage { Q_OBJECT -public: - explicit VersionPage(MinecraftInstance *inst, QWidget *parent = 0); + public: + explicit VersionPage(MinecraftInstance* inst, QWidget* parent = 0); virtual ~VersionPage(); - virtual QString displayName() const override - { - return tr("Version"); - } + 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 QString id() const override { return "version"; } + virtual QString helpPage() const override { return "Instance-Version"; } virtual bool shouldDisplay() const override; void retranslate() override; void openedImpl() override; void closedImpl() override; -private slots: + private slots: void on_actionChange_version_triggered(); void on_actionInstall_Forge_triggered(); void on_actionInstall_Fabric_triggered(); @@ -103,36 +92,34 @@ private slots: void updateVersionControls(); -private: + private: ComponentPtr current(); int currentRow(); void updateButtons(int row = -1); void preselect(int row = 0); int doUpdate(); -protected: - QMenu * createPopupMenu() override; + protected: + QMenu* createPopupMenu() override; /// FIXME: this shouldn't be necessary! bool reloadPackProfile(); -private: - Ui::VersionPage *ui; - QSortFilterProxyModel *m_filterModel; + private: + Ui::VersionPage* ui; + QSortFilterProxyModel* m_filterModel; std::shared_ptr m_profile; - MinecraftInstance *m_inst; + MinecraftInstance* m_inst; int currentIdx = 0; - bool controlsEnabled = false; std::shared_ptr m_wide_bar_setting = nullptr; -public slots: - void versionCurrent(const QModelIndex ¤t, const QModelIndex &previous); + public slots: + void versionCurrent(const QModelIndex& current, const QModelIndex& previous); -private slots: - void updateRunningStatus(bool running); + private slots: void onGameUpdateError(QString error); - void packageCurrent(const QModelIndex ¤t, const QModelIndex &previous); - void showContextMenu(const QPoint &pos); - void onFilterTextChanged(const QString & newContents); + void packageCurrent(const QModelIndex& current, const QModelIndex& previous); + void showContextMenu(const QPoint& pos); + void onFilterTextChanged(const QString& newContents); }; -- cgit From 308877aa8f105de408c4c8fe87d3476116b23cf4 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Sun, 9 Jul 2023 23:18:38 +0300 Subject: removed redundant code Signed-off-by: Trial97 --- launcher/ui/pages/instance/VersionPage.cpp | 9 --------- 1 file changed, 9 deletions(-) (limited to 'launcher') diff --git a/launcher/ui/pages/instance/VersionPage.cpp b/launcher/ui/pages/instance/VersionPage.cpp index 7db1b19f..a180c804 100644 --- a/launcher/ui/pages/instance/VersionPage.cpp +++ b/launcher/ui/pages/instance/VersionPage.cpp @@ -229,8 +229,6 @@ void VersionPage::updateVersionControls() // FIXME: this is a dirty hack auto minecraftVersion = Version(m_profile->getComponentVersion("net.minecraft")); - ui->actionInstall_Forge->setEnabled(true); - bool supportsFabric = minecraftVersion >= Version("1.14"); ui->actionInstall_Fabric->setEnabled(supportsFabric); @@ -255,13 +253,6 @@ void VersionPage::updateButtons(int row) ui->actionEdit->setEnabled(patch && patch->isCustom()); ui->actionCustomize->setEnabled(patch && patch->isCustomizable()); ui->actionRevert->setEnabled(patch && patch->isRevertible()); - ui->actionDownload_All->setEnabled(true); - ui->actionAdd_Empty->setEnabled(true); - ui->actionImport_Components->setEnabled(true); - ui->actionReload->setEnabled(true); - ui->actionReplace_Minecraft_jar->setEnabled(true); - ui->actionAdd_to_Minecraft_jar->setEnabled(true); - ui->actionAdd_Agents->setEnabled(true); } bool VersionPage::reloadPackProfile() -- cgit From 99ba02afb6a7af1bc0800552338ab811b027eb9e Mon Sep 17 00:00:00 2001 From: Nathan Date: Mon, 10 Jul 2023 11:26:25 -0700 Subject: Shortcuts on macOS (#1081) Co-authored-by: TheKodeToad --- launcher/FileSystem.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++-- launcher/ui/MainWindow.cpp | 44 +++++++++++++++++++++++++++++----- 2 files changed, 96 insertions(+), 8 deletions(-) (limited to 'launcher') diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index 812d45eb..4538702f 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -778,9 +778,43 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri destination = PathCombine(getDesktopDir(), RemoveInvalidFilenameChars(name)); } #if defined(Q_OS_MACOS) - destination += ".command"; + // Create the Application + QDir applicationDirectory = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) + "/" + BuildConfig.LAUNCHER_NAME + " Instances/"; - QFile f(destination); + if (!applicationDirectory.mkpath(".")) { + qWarning() << "Couldn't create application directory"; + return false; + } + + QDir application = applicationDirectory.path() + "/" + name + ".app/"; + + if (application.exists()) { + qWarning() << "Application already exists!"; + return false; + } + + if (!application.mkpath(".")) { + qWarning() << "Couldn't create application"; + return false; + } + + QDir content = application.path() + "/Contents/"; + QDir resources = content.path() + "/Resources/"; + QDir binaryDir = content.path() + "/MacOS/"; + QFile info = content.path() + "/Info.plist"; + + if (!(content.mkpath(".") && resources.mkpath(".") && binaryDir.mkpath("."))) { + qWarning() << "Couldn't create directories within application"; + return false; + } + info.open(QIODevice::WriteOnly | QIODevice::Text); + + QFile(icon).rename(resources.path() + "/Icon.icns"); + + // Create the Command file + QString exec = binaryDir.path() + "/Run.command"; + + QFile f(exec); f.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream stream(&f); @@ -797,6 +831,28 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther); + // Generate the Info.plist + QTextStream infoStream(&info); + infoStream << " \n" + "" + "\n" + "\n" + " CFBundleExecutable\n" + " Run.command\n" // The path to the executable + " CFBundleIconFile\n" + " Icon.icns\n" + " CFBundleName\n" + " " << name << "\n" // Name of the application + " CFBundlePackageType\n" + " APPL\n" + " CFBundleShortVersionString\n" + " 1.0\n" + " CFBundleVersion\n" + " 1.0\n" + "\n" + ""; + return true; #elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) if (!destination.endsWith(".desktop")) // in case of isFlatpak destination is already populated diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 2f944472..fe364937 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -1536,11 +1536,39 @@ void MainWindow::on_actionCreateInstanceShortcut_triggered() QString iconPath; QStringList args; #if defined(Q_OS_MACOS) - if (appPath.startsWith("/private/var/")) { - QMessageBox::critical(this, tr("Create instance shortcut"), - tr("The launcher is in the folder it was extracted from, therefore it cannot create shortcuts.")); - return; - } + appPath = QApplication::applicationFilePath(); + if (appPath.startsWith("/private/var/")) { + QMessageBox::critical(this, tr("Create instance shortcut"), + tr("The launcher is in the folder it was extracted from, therefore it cannot create shortcuts.")); + return; + } + + auto pIcon = APPLICATION->icons()->icon(m_selectedInstance->iconKey()); + if (pIcon == nullptr) + { + pIcon = APPLICATION->icons()->icon("grass"); + } + + iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "Icon.icns"); + + QFile iconFile(iconPath); + if (!iconFile.open(QFile::WriteOnly)) + { + QMessageBox::critical(this, tr("Create instance Application"), tr("Failed to create icon for Application.")); + return; + } + + QIcon icon = pIcon->icon(); + + bool success = icon.pixmap(1024, 1024).save(iconPath, "ICNS"); + iconFile.close(); + + if (!success) + { + iconFile.remove(); + QMessageBox::critical(this, tr("Create instance Application"), tr("Failed to create icon for Application.")); + return; + } #elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) if (appPath.startsWith("/tmp/.mount_")) { // AppImage! @@ -1623,7 +1651,11 @@ void MainWindow::on_actionCreateInstanceShortcut_triggered() #endif args.append({ "--launch", m_selectedInstance->id() }); if (FS::createShortcut(desktopFilePath, appPath, args, m_selectedInstance->name(), iconPath)) { - QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!")); +#if not defined(Q_OS_MACOS) + QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!")); +#else + QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance!")); +#endif } else { #if not defined(Q_OS_MACOS) iconFile.remove(); -- cgit