Merge pull request #304 from Ryex/move-downloads
Fixes https://github.com/PrismLauncher/PrismLauncher/issues/222
This commit is contained in:
commit
64576f4c4c
@ -149,6 +149,9 @@ bool ensureFolderPathExists(QString foldernamepath)
|
||||
return success;
|
||||
}
|
||||
|
||||
/// @brief Copies a directory and it's contents from src to dest
|
||||
/// @param offset subdirectory form src to copy to dest
|
||||
/// @return if there was an error during the filecopy
|
||||
bool copy::operator()(const QString& offset)
|
||||
{
|
||||
using copy_opts = fs::copy_options;
|
||||
|
@ -75,6 +75,7 @@ bool ensureFilePathExists(QString filenamepath);
|
||||
*/
|
||||
bool ensureFolderPathExists(QString filenamepath);
|
||||
|
||||
/// @brief Copies a directory and it's contents from src to dest
|
||||
class copy {
|
||||
public:
|
||||
copy(const QString& src, const QString& dst)
|
||||
|
@ -372,13 +372,20 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop)
|
||||
auto results = m_mod_id_resolver->getResults();
|
||||
|
||||
// first check for blocked mods
|
||||
QString text;
|
||||
QList<QUrl> urls;
|
||||
QList<BlockedMod> blocked_mods;
|
||||
auto anyBlocked = false;
|
||||
for (const auto& result : results.files.values()) {
|
||||
if (!result.resolved || result.url.isEmpty()) {
|
||||
text += QString("%1: <a href='%2'>%2</a><br/>").arg(result.fileName, result.websiteUrl);
|
||||
urls.append(QUrl(result.websiteUrl));
|
||||
|
||||
BlockedMod blocked_mod;
|
||||
blocked_mod.name = result.fileName;
|
||||
blocked_mod.websiteUrl = result.websiteUrl;
|
||||
blocked_mod.hash = result.hash;
|
||||
blocked_mod.matched = false;
|
||||
blocked_mod.localPath = "";
|
||||
|
||||
blocked_mods.append(blocked_mod);
|
||||
|
||||
anyBlocked = true;
|
||||
}
|
||||
}
|
||||
@ -388,11 +395,12 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop)
|
||||
auto message_dialog = new BlockedModsDialog(m_parent, tr("Blocked mods found"),
|
||||
tr("The following mods were blocked on third party launchers.<br/>"
|
||||
"You will need to manually download them and add them to the modpack"),
|
||||
text,
|
||||
urls);
|
||||
blocked_mods);
|
||||
message_dialog->setModal(true);
|
||||
|
||||
if (message_dialog->exec()) {
|
||||
qDebug() << "Post dialog blocked mods list: " << blocked_mods;
|
||||
copyBlockedMods(blocked_mods);
|
||||
setupDownloadJob(loop);
|
||||
} else {
|
||||
m_mod_id_resolver.reset();
|
||||
@ -404,6 +412,38 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop)
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief copy the matched blocked mods to the instance staging area
|
||||
/// @param blocked_mods list of the blocked mods and their matched paths
|
||||
void FlameCreationTask::copyBlockedMods(QList<BlockedMod> const& blocked_mods)
|
||||
{
|
||||
setStatus(tr("Copying Blocked Mods..."));
|
||||
setAbortable(false);
|
||||
int i = 0;
|
||||
int total = blocked_mods.length();
|
||||
setProgress(i, total);
|
||||
for (auto const& mod : blocked_mods) {
|
||||
if (!mod.matched) {
|
||||
qDebug() << mod.name << "was not matched to a local file, skipping copy";
|
||||
continue;
|
||||
}
|
||||
|
||||
auto dest_path = FS::PathCombine(m_stagingPath, "minecraft", "mods", mod.name);
|
||||
|
||||
setStatus(tr("Copying Blocked Mods (%1 out of %2 are done)").arg(QString::number(i), QString::number(total)));
|
||||
|
||||
qDebug() << "Will try to copy" << mod.localPath << "to" << dest_path;
|
||||
|
||||
if (!FS::copy(mod.localPath, dest_path)()) {
|
||||
qDebug() << "Copy of" << mod.localPath << "to" << dest_path << "Failed";
|
||||
}
|
||||
|
||||
i++;
|
||||
setProgress(i, total);
|
||||
}
|
||||
|
||||
setAbortable(true);
|
||||
}
|
||||
|
||||
void FlameCreationTask::setupDownloadJob(QEventLoop& loop)
|
||||
{
|
||||
m_files_job = new NetJob(tr("Mod download"), APPLICATION->network());
|
||||
@ -449,7 +489,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop)
|
||||
m_files_job.reset();
|
||||
setError(reason);
|
||||
});
|
||||
connect(m_files_job.get(), &NetJob::progress, [&](qint64 current, qint64 total) { setProgress(current, total); });
|
||||
connect(m_files_job.get(), &NetJob::progress, this, &FlameCreationTask::setProgress);
|
||||
connect(m_files_job.get(), &NetJob::finished, &loop, &QEventLoop::quit);
|
||||
|
||||
setStatus(tr("Downloading mods..."));
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "net/NetJob.h"
|
||||
|
||||
#include "ui/dialogs/BlockedModsDialog.h"
|
||||
|
||||
class FlameCreationTask final : public InstanceCreationTask {
|
||||
Q_OBJECT
|
||||
|
||||
@ -29,6 +31,7 @@ class FlameCreationTask final : public InstanceCreationTask {
|
||||
private slots:
|
||||
void idResolverSucceeded(QEventLoop&);
|
||||
void setupDownloadJob(QEventLoop&);
|
||||
void copyBlockedMods(QList<BlockedMod> const& blocked_mods);
|
||||
|
||||
private:
|
||||
QWidget* m_parent = nullptr;
|
||||
|
@ -36,6 +36,18 @@ Hasher::Ptr createFlameHasher(QString file_path)
|
||||
return new FlameHasher(file_path);
|
||||
}
|
||||
|
||||
Hasher::Ptr createBlockedModHasher(QString file_path, ModPlatform::Provider provider)
|
||||
{
|
||||
return new BlockedModHasher(file_path, provider);
|
||||
}
|
||||
|
||||
Hasher::Ptr createBlockedModHasher(QString file_path, ModPlatform::Provider provider, QString type)
|
||||
{
|
||||
auto hasher = new BlockedModHasher(file_path, provider);
|
||||
hasher->useHashType(type);
|
||||
return hasher;
|
||||
}
|
||||
|
||||
void ModrinthHasher::executeTask()
|
||||
{
|
||||
QFile file(m_path);
|
||||
@ -79,4 +91,50 @@ void FlameHasher::executeTask()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BlockedModHasher::BlockedModHasher(QString file_path, ModPlatform::Provider provider)
|
||||
: Hasher(file_path), provider(provider) {
|
||||
setObjectName(QString("BlockedModHasher: %1").arg(file_path));
|
||||
hash_type = ProviderCaps.hashType(provider).first();
|
||||
}
|
||||
|
||||
void BlockedModHasher::executeTask()
|
||||
{
|
||||
QFile file(m_path);
|
||||
|
||||
try {
|
||||
file.open(QFile::ReadOnly);
|
||||
} catch (FS::FileSystemException& e) {
|
||||
qCritical() << QString("Failed to open JAR file in %1").arg(m_path);
|
||||
qCritical() << QString("Reason: ") << e.cause();
|
||||
|
||||
emitFailed("Failed to open file for hashing.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_hash = ProviderCaps.hash(provider, &file, hash_type);
|
||||
|
||||
file.close();
|
||||
|
||||
if (m_hash.isEmpty()) {
|
||||
emitFailed("Empty hash!");
|
||||
} else {
|
||||
emitSucceeded();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList BlockedModHasher::getHashTypes() {
|
||||
return ProviderCaps.hashType(provider);
|
||||
}
|
||||
|
||||
bool BlockedModHasher::useHashType(QString type) {
|
||||
auto types = ProviderCaps.hashType(provider);
|
||||
if (types.contains(type)) {
|
||||
hash_type = type;
|
||||
return true;
|
||||
}
|
||||
qDebug() << "Bad hash type " << type << " for provider";
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Hashing
|
||||
|
@ -40,8 +40,23 @@ class ModrinthHasher : public Hasher {
|
||||
void executeTask() override;
|
||||
};
|
||||
|
||||
class BlockedModHasher : public Hasher {
|
||||
public:
|
||||
BlockedModHasher(QString file_path, ModPlatform::Provider provider);
|
||||
|
||||
void executeTask() override;
|
||||
|
||||
QStringList getHashTypes();
|
||||
bool useHashType(QString type);
|
||||
private:
|
||||
ModPlatform::Provider provider;
|
||||
QString hash_type;
|
||||
};
|
||||
|
||||
Hasher::Ptr createHasher(QString file_path, ModPlatform::Provider provider);
|
||||
Hasher::Ptr createFlameHasher(QString file_path);
|
||||
Hasher::Ptr createModrinthHasher(QString file_path);
|
||||
Hasher::Ptr createBlockedModHasher(QString file_path, ModPlatform::Provider provider);
|
||||
Hasher::Ptr createBlockedModHasher(QString file_path, ModPlatform::Provider provider, QString type);
|
||||
|
||||
} // namespace Hashing
|
||||
|
@ -176,8 +176,6 @@ void PackInstallTask::resolveMods()
|
||||
|
||||
void PackInstallTask::onResolveModsSucceeded()
|
||||
{
|
||||
QString text;
|
||||
QList<QUrl> urls;
|
||||
auto anyBlocked = false;
|
||||
|
||||
Flame::Manifest results = m_mod_id_resolver_task->getResults();
|
||||
@ -191,11 +189,16 @@ void PackInstallTask::onResolveModsSucceeded()
|
||||
|
||||
// First check for blocked mods
|
||||
if (!results_file.resolved || results_file.url.isEmpty()) {
|
||||
QString type(local_file.type);
|
||||
|
||||
type[0] = type[0].toUpper();
|
||||
text += QString("%1: %2 - <a href='%3'>%3</a><br/>").arg(type, local_file.name, results_file.websiteUrl);
|
||||
urls.append(QUrl(results_file.websiteUrl));
|
||||
BlockedMod blocked_mod;
|
||||
blocked_mod.name = local_file.name;
|
||||
blocked_mod.websiteUrl = results_file.websiteUrl;
|
||||
blocked_mod.hash = results_file.hash;
|
||||
blocked_mod.matched = false;
|
||||
blocked_mod.localPath = "";
|
||||
|
||||
m_blocked_mods.append(blocked_mod);
|
||||
|
||||
anyBlocked = true;
|
||||
} else {
|
||||
local_file.url = results_file.url.toString();
|
||||
@ -210,13 +213,16 @@ 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.<br/>"
|
||||
"You will need to manually download them and add them to the instance."),
|
||||
text,
|
||||
urls);
|
||||
m_blocked_mods);
|
||||
|
||||
if (message_dialog->exec() == QDialog::Accepted)
|
||||
if (message_dialog->exec() == QDialog::Accepted) {
|
||||
qDebug() << "Post dialog blocked mods list: " << m_blocked_mods;
|
||||
createInstance();
|
||||
else
|
||||
}
|
||||
else {
|
||||
abort();
|
||||
}
|
||||
|
||||
} else {
|
||||
createInstance();
|
||||
}
|
||||
@ -320,6 +326,9 @@ void PackInstallTask::downloadPack()
|
||||
void PackInstallTask::onModDownloadSucceeded()
|
||||
{
|
||||
m_net_job.reset();
|
||||
if (!m_blocked_mods.isEmpty()) {
|
||||
copyBlockedMods();
|
||||
}
|
||||
emitSucceeded();
|
||||
}
|
||||
|
||||
@ -343,4 +352,35 @@ void PackInstallTask::onModDownloadFailed(QString reason)
|
||||
emitFailed(reason);
|
||||
}
|
||||
|
||||
/// @brief copy the matched blocked mods to the instance staging area
|
||||
void PackInstallTask::copyBlockedMods()
|
||||
{
|
||||
setStatus(tr("Copying Blocked Mods..."));
|
||||
setAbortable(false);
|
||||
int i = 0;
|
||||
int total = m_blocked_mods.length();
|
||||
setProgress(i, total);
|
||||
for (auto const& mod : m_blocked_mods) {
|
||||
if (!mod.matched) {
|
||||
qDebug() << mod.name << "was not matched to a local file, skipping copy";
|
||||
continue;
|
||||
}
|
||||
|
||||
auto dest_path = FS::PathCombine(m_stagingPath, ".minecraft", "mods", mod.name);
|
||||
|
||||
setStatus(tr("Copying Blocked Mods (%1 out of %2 are done)").arg(QString::number(i), QString::number(total)));
|
||||
|
||||
qDebug() << "Will try to copy" << mod.localPath << "to" << dest_path;
|
||||
|
||||
if (!FS::copy(mod.localPath, dest_path)()) {
|
||||
qDebug() << "Copy of" << mod.localPath << "to" << dest_path << "Failed";
|
||||
}
|
||||
|
||||
i++;
|
||||
setProgress(i, total);
|
||||
}
|
||||
|
||||
setAbortable(true);
|
||||
}
|
||||
|
||||
} // namespace ModpacksCH
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "QObjectPtr.h"
|
||||
#include "modplatform/flame/FileResolvingTask.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "ui/dialogs/BlockedModsDialog.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
@ -76,6 +77,7 @@ private:
|
||||
void resolveMods();
|
||||
void createInstance();
|
||||
void downloadPack();
|
||||
void copyBlockedMods();
|
||||
|
||||
private:
|
||||
NetJob::Ptr m_net_job = nullptr;
|
||||
@ -90,6 +92,7 @@ private:
|
||||
Version m_version;
|
||||
|
||||
QMap<QString, QString> m_files_to_copy;
|
||||
QList<BlockedMod> m_blocked_mods;
|
||||
|
||||
//FIXME: nuke
|
||||
QWidget* m_parent;
|
||||
|
@ -1,28 +1,186 @@
|
||||
#include "BlockedModsDialog.h"
|
||||
#include "ui_BlockedModsDialog.h"
|
||||
#include <QPushButton>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDesktopServices>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include "Application.h"
|
||||
#include "ui_BlockedModsDialog.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStandardPaths>
|
||||
|
||||
BlockedModsDialog::BlockedModsDialog(QWidget *parent, const QString &title, const QString &text, const QString &body, const QList<QUrl> &urls) :
|
||||
QDialog(parent), ui(new Ui::BlockedModsDialog), urls(urls) {
|
||||
BlockedModsDialog::BlockedModsDialog(QWidget* parent, const QString& title, const QString& text, QList<BlockedMod>& mods)
|
||||
: QDialog(parent), ui(new Ui::BlockedModsDialog), mods(mods)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
auto openAllButton = ui->buttonBox->addButton(tr("Open All"), QDialogButtonBox::ActionRole);
|
||||
connect(openAllButton, &QPushButton::clicked, this, &BlockedModsDialog::openAll);
|
||||
|
||||
connect(&watcher, &QFileSystemWatcher::directoryChanged, this, &BlockedModsDialog::directoryChanged);
|
||||
|
||||
hashing_task = shared_qobject_ptr<ConcurrentTask>(new ConcurrentTask(this, "MakeHashesTask", 10));
|
||||
|
||||
qDebug() << "Mods List: " << mods;
|
||||
|
||||
setupWatch();
|
||||
scanPaths();
|
||||
|
||||
this->setWindowTitle(title);
|
||||
ui->label->setText(text);
|
||||
ui->textBrowser->setText(body);
|
||||
ui->labelModsFound->setText(tr("Please download the missing mods."));
|
||||
update();
|
||||
}
|
||||
|
||||
BlockedModsDialog::~BlockedModsDialog() {
|
||||
BlockedModsDialog::~BlockedModsDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void BlockedModsDialog::openAll() {
|
||||
for(auto &url : urls) {
|
||||
QDesktopServices::openUrl(url);
|
||||
void BlockedModsDialog::openAll()
|
||||
{
|
||||
for (auto& mod : mods) {
|
||||
QDesktopServices::openUrl(mod.websiteUrl);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief update UI with current status of the blocked mod detection
|
||||
void BlockedModsDialog::update()
|
||||
{
|
||||
QString text;
|
||||
QString span;
|
||||
|
||||
for (auto& mod : mods) {
|
||||
if (mod.matched) {
|
||||
// ✔ -> html for HEAVY CHECK MARK : ✔
|
||||
span = QString(tr("<span style=\"color:green\"> ✔ Found at %1 </span>")).arg(mod.localPath);
|
||||
} else {
|
||||
// ✘ -> html for HEAVY BALLOT X : ✘
|
||||
span = QString(tr("<span style=\"color:red\"> ✘ Not Found </span>"));
|
||||
}
|
||||
text += QString(tr("%1: <a href='%2'>%2</a> <p>Hash: %3 %4</p> <br/>")).arg(mod.name, mod.websiteUrl, mod.hash, span);
|
||||
}
|
||||
|
||||
ui->textBrowser->setText(text);
|
||||
|
||||
if (allModsMatched()) {
|
||||
ui->labelModsFound->setText(tr("All mods found ✔"));
|
||||
} else {
|
||||
ui->labelModsFound->setText(tr("Please download the missing mods."));
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Signal fired when a watched direcotry has changed
|
||||
/// @param path the path to the changed directory
|
||||
void BlockedModsDialog::directoryChanged(QString path)
|
||||
{
|
||||
qDebug() << "Directory changed: " << path;
|
||||
scanPath(path);
|
||||
}
|
||||
|
||||
/// @brief add the user downloads folder and the global mods folder to the filesystem watcher
|
||||
void BlockedModsDialog::setupWatch()
|
||||
{
|
||||
const QString downloadsFolder = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
||||
const QString modsFolder = APPLICATION->settings()->get("CentralModsDir").toString();
|
||||
watcher.addPath(downloadsFolder);
|
||||
watcher.addPath(modsFolder);
|
||||
}
|
||||
|
||||
/// @brief scan all watched folder
|
||||
void BlockedModsDialog::scanPaths()
|
||||
{
|
||||
for (auto& dir : watcher.directories()) {
|
||||
scanPath(dir);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Scan the directory at path, skip paths that do not contain a file name
|
||||
/// of a blocked mod we are looking for
|
||||
/// @param path the directory to scan
|
||||
void BlockedModsDialog::scanPath(QString path)
|
||||
{
|
||||
QDir scan_dir(path);
|
||||
QDirIterator scan_it(path, QDir::Filter::Files | QDir::Filter::Hidden, QDirIterator::NoIteratorFlags);
|
||||
while (scan_it.hasNext()) {
|
||||
QString file = scan_it.next();
|
||||
|
||||
if (!checkValidPath(file)) {
|
||||
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);
|
||||
}
|
||||
|
||||
hashing_task->start();
|
||||
}
|
||||
|
||||
/// @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
|
||||
/// @param path the path to the local file being compared
|
||||
void BlockedModsDialog::checkMatchHash(QString hash, QString path)
|
||||
{
|
||||
bool match = false;
|
||||
|
||||
qDebug() << "Checking for match on hash: " << hash << "| From path:" << path;
|
||||
|
||||
for (auto& mod : mods) {
|
||||
if (mod.matched) {
|
||||
continue;
|
||||
}
|
||||
if (mod.hash.compare(hash, Qt::CaseInsensitive) == 0) {
|
||||
mod.matched = true;
|
||||
mod.localPath = path;
|
||||
match = true;
|
||||
|
||||
qDebug() << "Hash match found:" << mod.name << hash << "| From path:" << path;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Check if the name of the file at path matches the name of a blocked mod we are searching for
|
||||
/// @param path the path to check
|
||||
/// @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();
|
||||
|
||||
for (auto& mod : mods) {
|
||||
if (mod.name.compare(filename, Qt::CaseInsensitive) == 0) {
|
||||
qDebug() << "Name match found:" << mod.name << "| From path:" << path;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BlockedModsDialog::allModsMatched()
|
||||
{
|
||||
return std::all_of(mods.begin(), mods.end(), [](auto const& mod) { return mod.matched; });
|
||||
}
|
||||
|
||||
/// qDebug print support for the BlockedMod struct
|
||||
QDebug operator<<(QDebug debug, const BlockedMod& m)
|
||||
{
|
||||
QDebugStateSaver saver(debug);
|
||||
|
||||
debug.nospace() << "{ name: " << m.name << ", websiteUrl: " << m.websiteUrl << ", hash: " << m.hash << ", matched: " << m.matched
|
||||
<< ", localPath: " << m.localPath << "}";
|
||||
|
||||
return debug;
|
||||
}
|
||||
|
@ -1,7 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
#include <QFileSystemWatcher>
|
||||
|
||||
#include "modplatform/helpers/HashUtils.h"
|
||||
|
||||
#include "tasks/ConcurrentTask.h"
|
||||
|
||||
struct BlockedMod {
|
||||
QString name;
|
||||
QString websiteUrl;
|
||||
QString hash;
|
||||
bool matched;
|
||||
QString localPath;
|
||||
|
||||
};
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui { class BlockedModsDialog; }
|
||||
@ -11,12 +27,27 @@ class BlockedModsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BlockedModsDialog(QWidget *parent, const QString &title, const QString &text, const QString &body, const QList<QUrl> &urls);
|
||||
BlockedModsDialog(QWidget *parent, const QString &title, const QString &text, QList<BlockedMod> &mods);
|
||||
|
||||
~BlockedModsDialog() override;
|
||||
|
||||
|
||||
private:
|
||||
Ui::BlockedModsDialog *ui;
|
||||
const QList<QUrl> &urls;
|
||||
QList<BlockedMod> &mods;
|
||||
QFileSystemWatcher watcher;
|
||||
shared_qobject_ptr<ConcurrentTask> hashing_task;
|
||||
|
||||
void openAll();
|
||||
void update();
|
||||
void directoryChanged(QString path);
|
||||
void setupWatch();
|
||||
void scanPaths();
|
||||
void scanPath(QString path);
|
||||
void checkMatchHash(QString hash, QString path);
|
||||
|
||||
bool checkValidPath(QString path);
|
||||
bool allModsMatched();
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug debug, const BlockedMod &m);
|
||||
|
@ -13,8 +13,8 @@
|
||||
<property name="windowTitle">
|
||||
<string notr="true">BlockedModsDialog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
@ -24,17 +24,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<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>
|
||||
<item row="1" column="0">
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textBrowser">
|
||||
<property name="acceptRichText">
|
||||
<bool>true</bool>
|
||||
@ -44,6 +34,27 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="bottomBoxH">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelModsFound">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
Loading…
Reference in New Issue
Block a user