diff options
Diffstat (limited to 'launcher/ui/dialogs')
-rw-r--r-- | launcher/ui/dialogs/BlockedModsDialog.cpp | 39 | ||||
-rw-r--r-- | launcher/ui/dialogs/NewInstanceDialog.cpp | 2 | ||||
-rw-r--r-- | launcher/ui/dialogs/ProgressDialog.cpp | 136 | ||||
-rw-r--r-- | launcher/ui/dialogs/ProgressDialog.h | 54 | ||||
-rw-r--r-- | launcher/ui/dialogs/ProgressDialog.ui | 150 | ||||
-rw-r--r-- | launcher/ui/dialogs/ResourceDownloadDialog.cpp | 2 |
6 files changed, 291 insertions, 92 deletions
diff --git a/launcher/ui/dialogs/BlockedModsDialog.cpp b/launcher/ui/dialogs/BlockedModsDialog.cpp index ba453df6..fdfae597 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.cpp +++ b/launcher/ui/dialogs/BlockedModsDialog.cpp @@ -195,7 +195,7 @@ void BlockedModsDialog::watchPath(QString path, bool watch_recursive) auto to_watch = QFileInfo(path); auto to_watch_path = to_watch.canonicalFilePath(); if (m_watcher.directories().contains(to_watch_path)) - return; // don't watch the same path twice (no loops!) + return; // don't watch the same path twice (no loops!) qDebug() << "[Blocked Mods Dialog] Adding Watch Path:" << path; m_watcher.addPath(to_watch_path); @@ -203,10 +203,9 @@ void BlockedModsDialog::watchPath(QString path, bool watch_recursive) if (!to_watch.isDir() || !watch_recursive) return; - QDirIterator it(to_watch_path, QDir::Filter::Dirs | QDir::Filter::NoDotAndDotDot, QDirIterator::NoIteratorFlags); while (it.hasNext()) { - QString watch_dir = QDir(it.next()).canonicalPath(); // resolve symlinks and relative paths + QString watch_dir = QDir(it.next()).canonicalPath(); // resolve symlinks and relative paths watchPath(watch_dir, watch_recursive); } } @@ -302,11 +301,35 @@ bool BlockedModsDialog::checkValidPath(QString path) { const QFileInfo file = QFileInfo(path); const QString filename = file.fileName(); - QString laxFilename(filename); - laxFilename.replace('+', ' '); - auto compare = [](QString fsfilename, QString metadataFilename) { - return metadataFilename.compare(fsfilename, Qt::CaseInsensitive) == 0; + auto compare = [](QString fsFilename, QString metadataFilename) { + return metadataFilename.compare(fsFilename, Qt::CaseInsensitive) == 0; + }; + + // super lax compare (but not fuzzy) + // convert to lowercase + // convert all speratores to whitespace + // simplify sequence of internal whitespace to a single space + // efectivly compare two strings ignoring all separators and case + auto laxCompare = [](QString fsfilename, QString metadataFilename) { + // allowed character seperators + QList<QChar> allowedSeperators = { '-', '+', '.' , '_'}; + + // copy in lowercase + auto fsName = fsfilename.toLower(); + auto metaName = metadataFilename.toLower(); + + // replace all potential allowed seperatores with whitespace + for (auto sep : allowedSeperators) { + fsName = fsName.replace(sep, ' '); + metaName = metaName.replace(sep, ' '); + } + + // remove extraneous whitespace + fsName = fsName.simplified(); + metaName = metaName.simplified(); + + return fsName.compare(metaName) == 0; }; for (auto& mod : m_mods) { @@ -314,7 +337,7 @@ bool BlockedModsDialog::checkValidPath(QString path) qDebug() << "[Blocked Mods Dialog] Name match found:" << mod.name << "| From path:" << path; return true; } - if (compare(laxFilename, mod.name)) { + if (laxCompare(filename, mod.name)) { qDebug() << "[Blocked Mods Dialog] Lax name match found:" << mod.name << "| From path:" << path; return true; } 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/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index da73a449..246a0fd4 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -1,29 +1,69 @@ -/* 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 <https://www.gnu.org/licenses/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include "ProgressDialog.h" #include "ui_ProgressDialog.h" +#include <limits> #include <QDebug> #include <QKeyEvent> #include "tasks/Task.h" +#include "ui/widgets/SubTaskProgressBar.h" + + +// map a value in a numeric range of an arbitrary type to between 0 and INT_MAX +// for getting the best precision out of the qt progress bar +template<typename T, std::enable_if_t<std::is_arithmetic_v<T>, bool> = true> +std::tuple<int, int> map_int_zero_max(T current, T range_max, T range_min) +{ + int int_max = std::numeric_limits<int>::max(); + + auto type_range = range_max - range_min; + double percentage = static_cast<double>(current - range_min) / static_cast<double>(type_range); + int mapped_current = percentage * int_max; + + return {mapped_current, int_max}; +} + + ProgressDialog::ProgressDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ProgressDialog) { ui->setupUi(this); + ui->taskProgressScrollArea->setHidden(true); this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint); setAttribute(Qt::WidgetAttribute::WA_QuitOnClose, true); setSkipButton(false); @@ -54,10 +94,24 @@ ProgressDialog::~ProgressDialog() } void ProgressDialog::updateSize() -{ +{ + QSize lastSize = this->size(); QSize qSize = QSize(480, minimumSizeHint().height()); - resize(qSize); - setFixedSize(qSize); + + // if the current window is too small + if ((lastSize != qSize) && (lastSize.height() < qSize.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 + ); + } + + setMinimumSize(qSize); + } int ProgressDialog::execWithTask(Task* task) @@ -79,17 +133,15 @@ 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::details, this, &ProgressDialog::changeStatus); + connect(task, &Task::stepProgress, this, &ProgressDialog::changeStepProgress); connect(task, &Task::progress, this, &ProgressDialog::changeProgress); - connect(task, &Task::aborted, this, &ProgressDialog::hide); connect(task, &Task::abortStatusChanged, ui->skipButton, &QPushButton::setEnabled); m_is_multi_step = task->isMultiStep(); - if (!m_is_multi_step) { - ui->globalStatusLabel->setHidden(true); - ui->globalProgressBar->setHidden(true); - } + ui->taskProgressScrollArea->setHidden(!m_is_multi_step); + updateSize(); // It's a good idea to start the task after we entered the dialog's event loop :^) if (!task->isRunning()) { @@ -149,23 +201,53 @@ void ProgressDialog::onTaskSucceeded() void ProgressDialog::changeStatus(const QString& status) { ui->globalStatusLabel->setText(task->getStatus()); - ui->statusLabel->setText(task->getStepStatus()); + ui->globalStatusDetailsLabel->setText(task->getDetails()); updateSize(); } +void ProgressDialog::addTaskProgress(TaskStepProgress const& progress) +{ + SubTaskProgressBar* task_bar = new SubTaskProgressBar(this); + taskProgress.insert(progress.uid, task_bar); + ui->taskProgressLayout->addWidget(task_bar); +} + +void ProgressDialog::changeStepProgress(TaskStepProgress const& task_progress) +{ + m_is_multi_step = true; + if(ui->taskProgressScrollArea->isHidden()) { + ui->taskProgressScrollArea->setHidden(false); + updateSize(); + } + + if (!taskProgress.contains(task_progress.uid)) + addTaskProgress(task_progress); + auto task_bar = taskProgress.value(task_progress.uid); + + + auto const [mapped_current, mapped_total] = map_int_zero_max<qint64>(task_progress.current, task_progress.total, 0); + if (task_progress.total <= 0) { + task_bar->setRange(0, 0); + } else { + task_bar->setRange(0, mapped_total); + } + + task_bar->setValue(mapped_current); + task_bar->setStatus(task_progress.status); + task_bar->setDetails(task_progress.details); + + if (task_progress.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()); - } } void ProgressDialog::keyPressEvent(QKeyEvent* e) diff --git a/launcher/ui/dialogs/ProgressDialog.h b/launcher/ui/dialogs/ProgressDialog.h index 0b4b78a4..fc9a0fbc 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 <https://www.gnu.org/licenses/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + #pragma once #include <QDialog> #include <memory> +#include <QHash> +#include <QUuid> + +#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(TaskStepProgress const& task_progress); private @@ -64,6 +93,7 @@ protected: private: bool handleImmediateResult(QDialog::DialogCode &result); + void addTaskProgress(TaskStepProgress const& progress); private: Ui::ProgressDialog *ui; @@ -71,4 +101,8 @@ private: Task *task; bool m_is_multi_step = false; + QHash<QUuid, SubTaskProgressBar*> taskProgress; + + }; + diff --git a/launcher/ui/dialogs/ProgressDialog.ui b/launcher/ui/dialogs/ProgressDialog.ui index 34ab71e3..a4d08124 100644 --- a/launcher/ui/dialogs/ProgressDialog.ui +++ b/launcher/ui/dialogs/ProgressDialog.ui @@ -2,75 +2,135 @@ <ui version="4.0"> <class>ProgressDialog</class> <widget class="QDialog" name="ProgressDialog"> - <property name="minimumSize"> - <size> - <width>400</width> - <height>0</height> - </size> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>480</width> + <height>210</height> + </rect> </property> - <property name="maximumSize"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>1</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> <size> - <width>600</width> - <height>16777215</height> + <width>480</width> + <height>210</height> </size> </property> <property name="windowTitle"> <string>Please wait...</string> </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="4" column="0"> - <widget class="QPushButton" name="skipButton"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0"> + <item> + <widget class="QLabel" name="globalStatusLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>15</height> + </size> + </property> + <property name="text"> + <string>Global Task Status...</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="globalStatusDetailsLabel"> + <property name="text"> + <string>Global Status Details...</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QProgressBar" name="globalProgressBar"> + <property name="enabled"> + <bool>true</bool> </property> - <property name="text"> - <string>Skip</string> + <property name="minimumSize"> + <size> + <width>0</width> + <height>24</height> + </size> </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="globalStatusLabel"> - <property name="text"> - <string>Global Task Status...</string> + <property name="value"> + <number>24</number> </property> </widget> </item> - <item row="2" column="0"> - <widget class="QLabel" name="statusLabel"> + <item> + <widget class="QScrollArea" name="taskProgressScrollArea"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding"> + <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="text"> - <string>Task Status...</string> + <property name="minimumSize"> + <size> + <width>0</width> + <height>100</height> + </size> </property> - <property name="wordWrap"> - <bool>true</bool> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QProgressBar" name="taskProgressBar"> - <property name="value"> - <number>24</number> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAsNeeded</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> </property> - <property name="textVisible"> - <bool>false</bool> + <property name="widgetResizable"> + <bool>true</bool> </property> + <widget class="QWidget" name="taskProgressContainer"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>464</width> + <height>96</height> + </rect> + </property> + <layout class="QVBoxLayout" name="taskProgressLayout"> + <property name="spacing"> + <number>2</number> + </property> + </layout> + </widget> </widget> </item> - <item row="1" column="0"> - <widget class="QProgressBar" name="globalProgressBar"> - <property name="enabled"> - <bool>true</bool> + <item> + <widget class="QPushButton" name="skipButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - <property name="value"> - <number>24</number> + <property name="text"> + <string>Skip</string> </property> </widget> </item> 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); |