From 5909af9878d67f2900c92e8d1dd3eec7a53a840a Mon Sep 17 00:00:00 2001 From: Rachel Powers <508861+Ryex@users.noreply.github.com> Date: Fri, 11 Nov 2022 14:10:45 -0700 Subject: [PATCH] drag&drop + add folder to watch Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com> --- .../flame/FlameInstanceCreationTask.cpp | 8 +- .../modpacksch/FTBPackInstallTask.cpp | 6 +- launcher/ui/dialogs/BlockedModsDialog.cpp | 82 +++++++++++++++++-- launcher/ui/dialogs/BlockedModsDialog.h | 8 ++ 4 files changed, 92 insertions(+), 12 deletions(-) diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp index f0fbdc96..eff729eb 100644 --- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp +++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp @@ -393,8 +393,12 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop) qWarning() << "Blocked mods found, displaying mod list"; auto message_dialog = new BlockedModsDialog(m_parent, tr("Blocked mods found"), - tr("The following mods were blocked on third party launchers.
" - "You will need to manually download them and add them to the modpack"), + tr("The following files are not available for download in third party launchers.
" + "You will need to manually download them and add them to the instance.

" + "Your configured global mods folder and default downloads folder
" + "are automatically checked for the downloaded mods.
" + "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."), blocked_mods); message_dialog->setModal(true); diff --git a/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp b/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp index 40aee82b..d74faf08 100644 --- a/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp +++ b/launcher/modplatform/modpacksch/FTBPackInstallTask.cpp @@ -212,7 +212,11 @@ void PackInstallTask::onResolveModsSucceeded() auto message_dialog = new BlockedModsDialog(m_parent, tr("Blocked files found"), tr("The following files are not available for download in third party launchers.
" - "You will need to manually download them and add them to the instance."), + "You will need to manually download them and add them to the instance.

" + "Your configured global mods folder and default downloads folder
" + "are automatically checked for the downloaded mods.
" + "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."), m_blocked_mods); if (message_dialog->exec() == QDialog::Accepted) { diff --git a/launcher/ui/dialogs/BlockedModsDialog.cpp b/launcher/ui/dialogs/BlockedModsDialog.cpp index 2cf94250..ca757cbc 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.cpp +++ b/launcher/ui/dialogs/BlockedModsDialog.cpp @@ -5,20 +5,29 @@ #include "Application.h" #include "ui_BlockedModsDialog.h" + #include #include +#include +#include +#include BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList& mods) : QDialog(parent), ui(new Ui::BlockedModsDialog), mods(mods) { + hashing_task = shared_qobject_ptr(new ConcurrentTask(this, "MakeHashesTask", 10)); + ui->setupUi(this); auto openAllButton = ui->buttonBox->addButton(tr("Open All"), QDialogButtonBox::ActionRole); connect(openAllButton, &QPushButton::clicked, this, &BlockedModsDialog::openAll); + auto downloadFolderButton = ui->buttonBox->addButton(tr("Add Download Folder"), QDialogButtonBox::ActionRole); + connect(downloadFolderButton, &QPushButton::clicked, this, &BlockedModsDialog::addDownloadFolder); + connect(&watcher, &QFileSystemWatcher::directoryChanged, this, &BlockedModsDialog::directoryChanged); - hashing_task = shared_qobject_ptr(new ConcurrentTask(this, "MakeHashesTask", 10)); + qDebug() << "Mods List: " << mods; @@ -28,6 +37,9 @@ BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, cons this->setWindowTitle(title); ui->label->setText(text); ui->labelModsFound->setText(tr("Please download the missing mods.")); + + setAcceptDrops(true); + update(); } @@ -36,6 +48,22 @@ BlockedModsDialog::~BlockedModsDialog() delete ui; } +void BlockedModsDialog::dragEnterEvent(QDragEnterEvent *e) { + if (e->mimeData()->hasUrls()) { + e->acceptProposedAction(); + } +} + +void BlockedModsDialog::dropEvent(QDropEvent *e) +{ + foreach (const QUrl &url, e->mimeData()->urls()) { + QString file = url.toLocalFile(); + qDebug() << "Dropped file:" << file; + addHashTask(file); + } + hashing_task->start(); +} + void BlockedModsDialog::openAll() { for (auto& mod : mods) { @@ -43,6 +71,16 @@ void BlockedModsDialog::openAll() } } +void BlockedModsDialog::addDownloadFolder() { + QString dir = QFileDialog::getExistingDirectory( + this, + tr("Select directory where you downloaded the mods"), + QStandardPaths::writableLocation(QStandardPaths::DownloadLocation), + QFileDialog::ShowDirsOnly); + watcher.addPath(dir); + scanPath(dir); +} + /// @brief update UI with current status of the blocked mod detection void BlockedModsDialog::update() { @@ -74,6 +112,7 @@ void BlockedModsDialog::update() void BlockedModsDialog::directoryChanged(QString path) { qDebug() << "Directory changed: " << path; + validateMatchedMods(); scanPath(path); } @@ -108,19 +147,26 @@ void BlockedModsDialog::scanPath(QString path) continue; } - auto hash_task = Hashing::createBlockedModHasher(file, ModPlatform::Provider::FLAME, "sha1"); - - qDebug() << "Creating Hash task for path: " << file; - - connect(hash_task.get(), &Task::succeeded, [this, hash_task, file] { checkMatchHash(hash_task->getResult(), file); }); - connect(hash_task.get(), &Task::failed, [file] { qDebug() << "Failed to hash path: " << file; }); - - hashing_task->addTask(hash_task); + addHashTask(file); } hashing_task->start(); } +/// @brief add a hashing task for the file located at path and connect it to check that hash against +/// our blocked mods list +/// @param path the path to the local file being hashed +void BlockedModsDialog::addHashTask(QString path) { + auto hash_task = Hashing::createBlockedModHasher(path, ModPlatform::Provider::FLAME, "sha1"); + + qDebug() << "Creating Hash task for path: " << path; + + connect(hash_task.get(), &Task::succeeded, [this, hash_task, path] { checkMatchHash(hash_task->getResult(), path); }); + connect(hash_task.get(), &Task::failed, [path] { qDebug() << "Failed to hash path: " << path; }); + + hashing_task->addTask(hash_task); +} + /// @brief check if the computed hash for the provided path matches a blocked /// mod we are looking for /// @param hash the computed hash for the provided path @@ -174,6 +220,24 @@ bool BlockedModsDialog::allModsMatched() return std::all_of(mods.begin(), mods.end(), [](auto const& mod) { return mod.matched; }); } +/// @brief ensure matched file paths still exist +void BlockedModsDialog::validateMatchedMods() { + bool changed = false; + for (auto& mod : mods) { + if (mod.matched) { + QFileInfo file = QFileInfo(mod.localPath); + if (!file.exists() || !file.isFile()) { + mod.localPath = ""; + mod.matched = false; + changed = true; + } + } + } + if (changed) { + update(); + } +} + /// qDebug print support for the BlockedMod struct QDebug operator<<(QDebug debug, const BlockedMod& m) { diff --git a/launcher/ui/dialogs/BlockedModsDialog.h b/launcher/ui/dialogs/BlockedModsDialog.h index 0a5c90db..d683c54d 100644 --- a/launcher/ui/dialogs/BlockedModsDialog.h +++ b/launcher/ui/dialogs/BlockedModsDialog.h @@ -31,6 +31,11 @@ public: ~BlockedModsDialog() override; +protected: + void dragEnterEvent(QDragEnterEvent *event) override; + // void dragMoveEvent(QDragMoveEvent *event) override; + // void dragLeaveEvent(QDragLeaveEvent *event) override; + void dropEvent(QDropEvent *event) override; private: Ui::BlockedModsDialog *ui; @@ -39,12 +44,15 @@ private: shared_qobject_ptr hashing_task; void openAll(); + void addDownloadFolder(); void update(); void directoryChanged(QString path); void setupWatch(); void scanPaths(); void scanPath(QString path); + void addHashTask(QString path); void checkMatchHash(QString hash, QString path); + void validateMatchedMods(); bool checkValidPath(QString path); bool allModsMatched();