diff options
Diffstat (limited to 'launcher/ui/dialogs')
-rw-r--r-- | launcher/ui/dialogs/BlockedModsDialog.cpp | 90 | ||||
-rw-r--r-- | launcher/ui/dialogs/BlockedModsDialog.h | 63 | ||||
-rw-r--r-- | launcher/ui/dialogs/BlockedModsDialog.ui | 38 | ||||
-rw-r--r-- | launcher/ui/dialogs/ImportResourcePackDialog.cpp | 66 | ||||
-rw-r--r-- | launcher/ui/dialogs/ImportResourcePackDialog.h | 27 | ||||
-rw-r--r-- | launcher/ui/dialogs/ImportResourcePackDialog.ui | 74 | ||||
-rw-r--r-- | launcher/ui/dialogs/ProgressDialog.cpp | 3 |
7 files changed, 295 insertions, 66 deletions
diff --git a/launcher/ui/dialogs/BlockedModsDialog.cpp b/launcher/ui/dialogs/BlockedModsDialog.cpp index edb4ff7d..8b49bd1a 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.cpp +++ b/launcher/ui/dialogs/BlockedModsDialog.cpp @@ -1,14 +1,41 @@ +// SPDX-FileCopyrightText: 2022 Sefa Eyeoglu <contact@scrumplex.net> +// SPDX-FileCopyrightText: 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> +// SPDX-FileCopyrightText: 2022 kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> + * Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> + * Copyright (C) 2022 kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + #include "BlockedModsDialog.h" -#include <QDesktopServices> -#include <QDialogButtonBox> -#include <QPushButton> -#include "Application.h" #include "ui_BlockedModsDialog.h" +#include "Application.h" +#include "modplatform/helpers/HashUtils.h" + #include <QDebug> +#include <QDesktopServices> +#include <QDialogButtonBox> #include <QDragEnterEvent> #include <QFileDialog> #include <QFileInfo> +#include <QPushButton> #include <QStandardPaths> BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList<BlockedMod>& mods) @@ -19,8 +46,8 @@ BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, cons ui->setupUi(this); - auto openAllButton = ui->buttonBox->addButton(tr("Open All"), QDialogButtonBox::ActionRole); - connect(openAllButton, &QPushButton::clicked, this, &BlockedModsDialog::openAll); + m_openMissingButton = ui->buttonBox->addButton(tr("Open Missing"), QDialogButtonBox::ActionRole); + connect(m_openMissingButton, &QPushButton::clicked, this, [this]() { openAll(true); }); auto downloadFolderButton = ui->buttonBox->addButton(tr("Add Download Folder"), QDialogButtonBox::ActionRole); connect(downloadFolderButton, &QPushButton::clicked, this, &BlockedModsDialog::addDownloadFolder); @@ -34,15 +61,8 @@ BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, cons this->setWindowTitle(title); ui->labelDescription->setText(text); - ui->labelExplain->setText( - QString(tr("Your configured global mods folder and default downloads folder " - "are automatically checked for the downloaded mods and they will be copied to the instance if found.<br/>" - "Optionally, you may drag and drop the downloaded mods onto this dialog or add a folder to watch " - "if you did not download the mods to a default location.")) - .arg(APPLICATION->settings()->get("CentralModsDir").toString(), - QStandardPaths::writableLocation(QStandardPaths::DownloadLocation))); - - // force all URL handeling as external + + // force all URL handling as external connect(ui->textBrowserWatched, &QTextBrowser::anchorClicked, this, [](const QUrl url) { QDesktopServices::openUrl(url); }); setAcceptDrops(true); @@ -64,7 +84,15 @@ void BlockedModsDialog::dragEnterEvent(QDragEnterEvent* e) void BlockedModsDialog::dropEvent(QDropEvent* e) { - for (const QUrl& url : e->mimeData()->urls()) { + for (QUrl& url : e->mimeData()->urls()) { + if (url.scheme().isEmpty()) { // ensure isLocalFile() works correctly + url.setScheme("file"); + } + + if (!url.isLocalFile()) { // can't drop external files here. + continue; + } + QString filePath = url.toLocalFile(); qDebug() << "[Blocked Mods Dialog] Dropped file:" << filePath; addHashTask(filePath); @@ -79,10 +107,18 @@ void BlockedModsDialog::dropEvent(QDropEvent* e) update(); } -void BlockedModsDialog::openAll() +void BlockedModsDialog::done(int r) +{ + QDialog::done(r); + disconnect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &BlockedModsDialog::directoryChanged); +} + +void BlockedModsDialog::openAll(bool missingOnly) { for (auto& mod : m_mods) { - QDesktopServices::openUrl(mod.websiteUrl); + if (!missingOnly || !mod.matched) { + QDesktopServices::openUrl(mod.websiteUrl); + } } } @@ -125,8 +161,10 @@ void BlockedModsDialog::update() if (allModsMatched()) { ui->labelModsFound->setText("<span style=\"color:green\">✔</span>" + tr("All mods found")); + m_openMissingButton->setDisabled(true); } else { ui->labelModsFound->setText(tr("Please download the missing mods.")); + m_openMissingButton->setDisabled(false); } } @@ -237,14 +275,24 @@ void BlockedModsDialog::checkMatchHash(QString hash, QString path) /// @return boolean: did the path match the name of a blocked mod? bool BlockedModsDialog::checkValidPath(QString path) { - QFileInfo file = QFileInfo(path); - QString filename = file.fileName(); + 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; + }; for (auto& mod : m_mods) { - if (mod.name.compare(filename, Qt::CaseInsensitive) == 0) { + if (compare(filename, mod.name)) { qDebug() << "[Blocked Mods Dialog] Name match found:" << mod.name << "| From path:" << path; return true; } + if (compare(laxFilename, mod.name)) { + qDebug() << "[Blocked Mods Dialog] Lax name match found:" << mod.name << "| From path:" << path; + return true; + } } return false; diff --git a/launcher/ui/dialogs/BlockedModsDialog.h b/launcher/ui/dialogs/BlockedModsDialog.h index dac43cba..014f488a 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.h +++ b/launcher/ui/dialogs/BlockedModsDialog.h @@ -1,49 +1,80 @@ +// SPDX-FileCopyrightText: 2022 Sefa Eyeoglu <contact@scrumplex.net> +// SPDX-FileCopyrightText: 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> +// SPDX-FileCopyrightText: 2022 kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> +// +// SPDX-License-Identifier: GPL-3.0-only + +/* + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> + * Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com> + * Copyright (C) 2022 kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + #pragma once #include <QDialog> -#include <QString> #include <QList> +#include <QString> #include <QFileSystemWatcher> -#include "modplatform/helpers/HashUtils.h" - #include "tasks/ConcurrentTask.h" +class QPushButton; + struct BlockedMod { QString name; QString websiteUrl; QString hash; bool matched; QString localPath; - + QString targetFolder; }; QT_BEGIN_NAMESPACE -namespace Ui { class BlockedModsDialog; } +namespace Ui { +class BlockedModsDialog; +} QT_END_NAMESPACE class BlockedModsDialog : public QDialog { -Q_OBJECT + Q_OBJECT -public: - BlockedModsDialog(QWidget *parent, const QString &title, const QString &text, QList<BlockedMod> &mods); + public: + BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList<BlockedMod>& mods); ~BlockedModsDialog() override; -protected: - void dragEnterEvent(QDragEnterEvent *event) override; - void dropEvent(QDropEvent *event) override; + protected: + void dragEnterEvent(QDragEnterEvent* event) override; + void dropEvent(QDropEvent* event) override; + + protected slots: + void done(int r) override; -private: - Ui::BlockedModsDialog *ui; - QList<BlockedMod> &m_mods; + private: + Ui::BlockedModsDialog* ui; + QList<BlockedMod>& m_mods; QFileSystemWatcher m_watcher; shared_qobject_ptr<ConcurrentTask> m_hashing_task; QSet<QString> m_pending_hash_paths; bool m_rehash_pending; + QPushButton* m_openMissingButton; - void openAll(); + void openAll(bool missingOnly); void addDownloadFolder(); void update(); void directoryChanged(QString path); @@ -61,4 +92,4 @@ private: bool allModsMatched(); }; -QDebug operator<<(QDebug debug, const BlockedMod &m); +QDebug operator<<(QDebug debug, const BlockedMod& m); diff --git a/launcher/ui/dialogs/BlockedModsDialog.ui b/launcher/ui/dialogs/BlockedModsDialog.ui index 88105178..2292b99c 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.ui +++ b/launcher/ui/dialogs/BlockedModsDialog.ui @@ -7,17 +7,23 @@ <x>0</x> <y>0</y> <width>400</width> - <height>455</height> + <height>400</height> </rect> </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>350</height> + </size> + </property> <property name="windowTitle"> <string notr="true">BlockedModsDialog</string> </property> - <layout class="QVBoxLayout" name="verticalLayout"> + <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,3,0,1,0"> <item> <widget class="QLabel" name="labelDescription"> <property name="text"> - <string notr="true"/> + <string notr="true">Placeholder description</string> </property> <property name="textFormat"> <enum>Qt::RichText</enum> @@ -30,7 +36,7 @@ <item> <widget class="QLabel" name="labelExplain"> <property name="text"> - <string/> + <string><html><head/><body><p>Your configured global mods folder and default downloads folder are automatically checked for the downloaded mods and they will be copied to the instance if found.</p><p>Optionally, you may drag and drop the downloaded mods onto this dialog or add a folder to watch if you did not download the mods to a default location.</p></body></html></string> </property> <property name="wordWrap"> <bool>true</bool> @@ -42,12 +48,6 @@ </item> <item> <widget class="QTextBrowser" name="textBrowserModsListing"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>165</height> - </size> - </property> <property name="acceptRichText"> <bool>true</bool> </property> @@ -58,12 +58,6 @@ </item> <item> <widget class="QLabel" name="labelWatched"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> <property name="text"> <string>Watched Folders:</string> </property> @@ -71,18 +65,6 @@ </item> <item> <widget class="QTextBrowser" name="textBrowserWatched"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>16</height> - </size> - </property> <property name="baseSize"> <size> <width>0</width> diff --git a/launcher/ui/dialogs/ImportResourcePackDialog.cpp b/launcher/ui/dialogs/ImportResourcePackDialog.cpp new file mode 100644 index 00000000..e807e926 --- /dev/null +++ b/launcher/ui/dialogs/ImportResourcePackDialog.cpp @@ -0,0 +1,66 @@ +#include "ImportResourcePackDialog.h" +#include "ui_ImportResourcePackDialog.h" + +#include <QFileDialog> +#include <QPushButton> + +#include "Application.h" +#include "InstanceList.h" + +#include <InstanceList.h> +#include "ui/instanceview/InstanceProxyModel.h" +#include "ui/instanceview/InstanceDelegate.h" + +ImportResourcePackDialog::ImportResourcePackDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ImportResourcePackDialog) +{ + ui->setupUi(this); + setWindowModality(Qt::WindowModal); + + auto contentsWidget = ui->instanceView; + contentsWidget->setViewMode(QListView::ListMode); + contentsWidget->setFlow(QListView::LeftToRight); + contentsWidget->setIconSize(QSize(48, 48)); + contentsWidget->setMovement(QListView::Static); + contentsWidget->setResizeMode(QListView::Adjust); + contentsWidget->setSelectionMode(QAbstractItemView::SingleSelection); + contentsWidget->setSpacing(5); + contentsWidget->setWordWrap(true); + contentsWidget->setWrapping(true); + // NOTE: We can't have uniform sizes because the text may wrap if it's too long. If we set this, it will cut off the wrapped text. + contentsWidget->setUniformItemSizes(false); + contentsWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + contentsWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + contentsWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + contentsWidget->setItemDelegate(new ListViewDelegate()); + + proxyModel = new InstanceProxyModel(this); + proxyModel->setSourceModel(APPLICATION->instances().get()); + proxyModel->sort(0); + contentsWidget->setModel(proxyModel); + + connect(contentsWidget, SIGNAL(doubleClicked(QModelIndex)), SLOT(activated(QModelIndex))); + connect(contentsWidget->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + SLOT(selectionChanged(QItemSelection, QItemSelection))); +} + +void ImportResourcePackDialog::activated(QModelIndex index) +{ + selectedInstanceKey = index.data(InstanceList::InstanceIDRole).toString(); + accept(); +} + +void ImportResourcePackDialog::selectionChanged(QItemSelection selected, QItemSelection deselected) +{ + if (selected.empty()) + return; + + QString key = selected.first().indexes().first().data(InstanceList::InstanceIDRole).toString(); + if (!key.isEmpty()) { + selectedInstanceKey = key; + } +} + +ImportResourcePackDialog::~ImportResourcePackDialog() +{ + delete ui; +} diff --git a/launcher/ui/dialogs/ImportResourcePackDialog.h b/launcher/ui/dialogs/ImportResourcePackDialog.h new file mode 100644 index 00000000..8356f204 --- /dev/null +++ b/launcher/ui/dialogs/ImportResourcePackDialog.h @@ -0,0 +1,27 @@ +#pragma once + +#include <QDialog> +#include <QItemSelection> + +#include "ui/instanceview/InstanceProxyModel.h" + +namespace Ui { +class ImportResourcePackDialog; +} + +class ImportResourcePackDialog : public QDialog { + Q_OBJECT + + public: + explicit ImportResourcePackDialog(QWidget* parent = 0); + ~ImportResourcePackDialog(); + InstanceProxyModel* proxyModel; + QString selectedInstanceKey; + + private: + Ui::ImportResourcePackDialog* ui; + + private slots: + void selectionChanged(QItemSelection, QItemSelection); + void activated(QModelIndex); +}; diff --git a/launcher/ui/dialogs/ImportResourcePackDialog.ui b/launcher/ui/dialogs/ImportResourcePackDialog.ui new file mode 100644 index 00000000..20cb9177 --- /dev/null +++ b/launcher/ui/dialogs/ImportResourcePackDialog.ui @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ImportResourcePackDialog</class> + <widget class="QDialog" name="ImportResourcePackDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>676</width> + <height>555</height> + </rect> + </property> + <property name="windowTitle"> + <string>Choose instance to import</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Choose the instance you would like to import this resource pack to.</string> + </property> + </widget> + </item> + <item> + <widget class="QListView" name="instanceView"/> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>ImportResourcePackDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>ImportResourcePackDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/launcher/ui/dialogs/ProgressDialog.cpp b/launcher/ui/dialogs/ProgressDialog.cpp index 05269f62..da73a449 100644 --- a/launcher/ui/dialogs/ProgressDialog.cpp +++ b/launcher/ui/dialogs/ProgressDialog.cpp @@ -44,7 +44,8 @@ void ProgressDialog::setSkipButton(bool present, QString label) void ProgressDialog::on_skipButton_clicked(bool checked) { Q_UNUSED(checked); - task->abort(); + if (ui->skipButton->isEnabled()) // prevent other triggers from aborting + task->abort(); } ProgressDialog::~ProgressDialog() |