Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into Fix_Assert

This commit is contained in:
Trial97
2023-05-14 14:20:04 +03:00
82 changed files with 1702 additions and 413 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -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;
};

View File

@ -2,26 +2,129 @@
<ui version="4.0">
<class>ProgressDialog</class>
<widget class="QDialog" name="ProgressDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>480</width>
<height>210</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<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">
<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="minimumSize">
<size>
<width>0</width>
<height>24</height>
</size>
</property>
<property name="value">
<number>24</number>
</property>
</widget>
</item>
<item>
<widget class="QScrollArea" name="taskProgressScrollArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<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>
<widget class="QPushButton" name="skipButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -31,49 +134,6 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="globalStatusLabel">
<property name="text">
<string>Global Task Status...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="statusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Task Status...</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QProgressBar" name="taskProgressBar">
<property name="value">
<number>24</number>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QProgressBar" name="globalProgressBar">
<property name="enabled">
<bool>true</bool>
</property>
<property name="value">
<number>24</number>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>