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/ui/dialogs/ExportMrPackDialog.cpp | 31 ++++++++++++ launcher/ui/dialogs/ExportMrPackDialog.h | 38 +++++++++++++++ launcher/ui/dialogs/ExportMrPackDialog.ui | 77 ++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) 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/ui/dialogs') 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 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/ui/dialogs') 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/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 ++- 5 files changed, 41 insertions(+), 301 deletions(-) (limited to 'launcher/ui/dialogs') 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/ui/dialogs') 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/ui/dialogs') 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/ui/dialogs') 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/ui/dialogs/ExportMrPackDialog.cpp | 72 ++++-------------------------- launcher/ui/dialogs/ExportMrPackDialog.h | 3 +- 2 files changed, 10 insertions(+), 65 deletions(-) (limited to 'launcher/ui/dialogs') 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 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 --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 32 +++++++++++++----------------- launcher/ui/dialogs/ExportMrPackDialog.h | 2 -- 2 files changed, 14 insertions(+), 20 deletions(-) (limited to 'launcher/ui/dialogs') 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 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/ui/dialogs') 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 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/ui/dialogs/ExportMrPackDialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'launcher/ui/dialogs') 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/ui/dialogs/ExportInstanceDialog.cpp | 2 +- launcher/ui/dialogs/ExportInstanceDialog.h | 4 ++-- launcher/ui/dialogs/ExportMrPackDialog.cpp | 9 ++++----- launcher/ui/dialogs/ExportMrPackDialog.h | 4 ++-- 4 files changed, 9 insertions(+), 10 deletions(-) (limited to 'launcher/ui/dialogs') 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 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/ui/dialogs/ExportMrPackDialog.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'launcher/ui/dialogs') 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 --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'launcher/ui/dialogs') 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/ui/dialogs') 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 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/ui/dialogs') 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 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 --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'launcher/ui/dialogs') 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 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 --- launcher/ui/dialogs/ExportMrPackDialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'launcher/ui/dialogs') 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 f997529cd4fb077b06d05da9c6ff0c23b85b4ebb Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Thu, 30 Mar 2023 11:22:55 -0700 Subject: feat: better task tracking Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- launcher/ui/dialogs/ProgressDialog.cpp | 109 +++++++++++++++++++++++++++------ launcher/ui/dialogs/ProgressDialog.h | 54 +++++++++++++--- launcher/ui/dialogs/ProgressDialog.ui | 61 +++++++++--------- 3 files changed, 163 insertions(+), 61 deletions(-) (limited to 'launcher/ui/dialogs') diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index da73a449..da627af3 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -1,26 +1,66 @@ -/* Copyright 2013-2021 MultiMC Contributors +/// SPDX-License-Identifier: GPL-3.0-only +/* + * PrismLaucher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> * - * 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 "ProgressDialog.h" #include "ui_ProgressDialog.h" +#include #include #include #include "tasks/Task.h" +#include "ui/widgets/SubTaskProgressBar.h" + + +template +int map_int_range(T value) +{ + auto type_min = std::numeric_limits::min(); + auto type_max = std::numeric_limits::max(); + + auto int_min = std::numeric_limits::min(); + auto int_max = std::numeric_limits::max(); + + auto type_range = type_max - type_min; + auto int_range = int_max - int_min; + + return static_cast((value - type_min) * int_range / type_range + int_min); +} + + ProgressDialog::ProgressDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ProgressDialog) { ui->setupUi(this); @@ -79,7 +119,7 @@ int ProgressDialog::execWithTask(Task* task) connect(task, &Task::failed, this, &ProgressDialog::onTaskFailed); connect(task, &Task::succeeded, this, &ProgressDialog::onTaskSucceeded); connect(task, &Task::status, this, &ProgressDialog::changeStatus); - connect(task, &Task::stepStatus, this, &ProgressDialog::changeStatus); + connect(task, &Task::stepProgress, this, &ProgressDialog::changeStepProgress); connect(task, &Task::progress, this, &ProgressDialog::changeProgress); connect(task, &Task::aborted, this, &ProgressDialog::hide); @@ -149,23 +189,54 @@ void ProgressDialog::onTaskSucceeded() void ProgressDialog::changeStatus(const QString& status) { ui->globalStatusLabel->setText(task->getStatus()); - ui->statusLabel->setText(task->getStepStatus()); + // ui->statusLabel->setText(task->getStepStatus()); updateSize(); } +void ProgressDialog::addTaskProgress(TaskStepProgress progress) +{ + SubTaskProgressBar* task_bar = new SubTaskProgressBar(this); + taskProgress.insert(progress.uid, task_bar); + ui->taskProgressLayout->addWidget(task_bar); +} + +void ProgressDialog::changeStepProgress(QList task_progress) +{ + for (auto tp : task_progress) { + if (!taskProgress.contains(tp.uid)) + addTaskProgress(tp); + auto task_bar = taskProgress.value(tp.uid); + + if (tp.total < 0) { + task_bar->setRange(0, 0); + } else { + task_bar->setRange(0, map_int_range(tp.total)); + } + + task_bar->setValue(map_int_range(tp.current)); + task_bar->setStatus(tp.status); + task_bar->setDetails(tp.details); + + if (tp.isDone()) { + task_bar->setVisible(false); + } + + } +} + void ProgressDialog::changeProgress(qint64 current, qint64 total) { ui->globalProgressBar->setMaximum(total); ui->globalProgressBar->setValue(current); - if (!m_is_multi_step) { - ui->taskProgressBar->setMaximum(total); - ui->taskProgressBar->setValue(current); - } else { - ui->taskProgressBar->setMaximum(task->getStepProgress()); - ui->taskProgressBar->setValue(task->getStepTotalProgress()); - } + // if (!m_is_multi_step) { + // ui->taskProgressBar->setMaximum(total); + // ui->taskProgressBar->setValue(current); + // } else { + // ui->taskProgressBar->setMaximum(task->getStepProgress()); + // ui->taskProgressBar->setValue(task->getStepTotalProgress()); + // } } void ProgressDialog::keyPressEvent(QKeyEvent* e) diff --git a/launcher/ui/dialogs/ProgressDialog.h b/launcher/ui/dialogs/ProgressDialog.h index 0b4b78a4..a7e203fb 100644 --- a/launcher/ui/dialogs/ProgressDialog.h +++ b/launcher/ui/dialogs/ProgressDialog.h @@ -1,22 +1,50 @@ -/* Copyright 2013-2021 MultiMC Contributors +/// SPDX-License-Identifier: GPL-3.0-only +/* + * PrismLaucher - Minecraft Launcher + * Copyright (C) 2023 Rachel Powers <508861+Ryex@users.noreply.github.com> * - * 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 + +#include "QObjectPtr.h" +#include "tasks/Task.h" + +#include "ui/widgets/SubTaskProgressBar.h" class Task; class SequentialTask; @@ -52,6 +80,7 @@ slots: void changeStatus(const QString &status); void changeProgress(qint64 current, qint64 total); + void changeStepProgress(QList task_progress); private @@ -64,6 +93,7 @@ protected: private: bool handleImmediateResult(QDialog::DialogCode &result); + void addTaskProgress(TaskStepProgress progress); private: Ui::ProgressDialog *ui; @@ -71,4 +101,8 @@ private: Task *task; bool m_is_multi_step = false; + QHash taskProgress; + + }; + diff --git a/launcher/ui/dialogs/ProgressDialog.ui b/launcher/ui/dialogs/ProgressDialog.ui index 34ab71e3..0a998987 100644 --- a/launcher/ui/dialogs/ProgressDialog.ui +++ b/launcher/ui/dialogs/ProgressDialog.ui @@ -2,6 +2,20 @@ ProgressDialog