From c4316e81e64ad4ac63b0b50106b324a73abdc150 Mon Sep 17 00:00:00 2001 From: flow Date: Sun, 26 Jun 2022 14:17:15 -0300 Subject: [PATCH] change: make Mod a QObject used as a pointer Prevents problems when copying it around! Signed-off-by: flow --- launcher/MMCZip.cpp | 30 ++++--- launcher/MMCZip.h | 2 +- launcher/minecraft/MinecraftInstance.cpp | 24 +++--- launcher/minecraft/MinecraftInstance.h | 2 +- launcher/minecraft/mod/Mod.h | 6 +- launcher/minecraft/mod/ModFolderModel.cpp | 76 +++++++++--------- launcher/minecraft/mod/ModFolderModel.h | 16 ++-- .../minecraft/mod/tasks/ModFolderLoadTask.cpp | 32 ++++---- .../minecraft/mod/tasks/ModFolderLoadTask.h | 2 +- launcher/modplatform/CheckUpdateTask.h | 6 +- launcher/modplatform/EnsureMetadataTask.cpp | 80 ++++++++++--------- launcher/modplatform/EnsureMetadataTask.h | 20 ++--- .../modplatform/flame/FlameCheckUpdate.cpp | 34 ++++---- launcher/modplatform/flame/FlameCheckUpdate.h | 2 +- .../modrinth/ModrinthCheckUpdate.cpp | 34 ++++---- .../modrinth/ModrinthCheckUpdate.h | 2 +- launcher/ui/dialogs/ModUpdateDialog.cpp | 59 +++++++------- launcher/ui/dialogs/ModUpdateDialog.h | 16 ++-- launcher/ui/pages/instance/ModFolderPage.cpp | 2 +- 19 files changed, 229 insertions(+), 216 deletions(-) diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index f20d6dff..1627ee07 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -127,7 +127,7 @@ bool MMCZip::compressDirFiles(QString fileCompressed, QString dir, QFileInfoList } // ours -bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const QList& mods) +bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const QList& mods) { QuaZip zipOut(targetJarPath); if (!zipOut.open(QuaZip::mdCreate)) @@ -141,42 +141,40 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const QSet addedFiles; // Modify the jar - QListIterator i(mods); - i.toBack(); - while (i.hasPrevious()) + for (auto i = mods.constEnd(); i != mods.constBegin(); --i) { - const Mod &mod = i.previous(); + const Mod* mod = *i; // do not merge disabled mods. - if (!mod.enabled()) + if (!mod->enabled()) continue; - if (mod.type() == Mod::MOD_ZIPFILE) + if (mod->type() == Mod::MOD_ZIPFILE) { - if (!mergeZipFiles(&zipOut, mod.fileinfo(), addedFiles)) + if (!mergeZipFiles(&zipOut, mod->fileinfo(), addedFiles)) { zipOut.close(); QFile::remove(targetJarPath); - qCritical() << "Failed to add" << mod.fileinfo().fileName() << "to the jar."; + qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar."; return false; } } - else if (mod.type() == Mod::MOD_SINGLEFILE) + else if (mod->type() == Mod::MOD_SINGLEFILE) { // FIXME: buggy - does not work with addedFiles - auto filename = mod.fileinfo(); + auto filename = mod->fileinfo(); if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(), filename.fileName())) { zipOut.close(); QFile::remove(targetJarPath); - qCritical() << "Failed to add" << mod.fileinfo().fileName() << "to the jar."; + qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar."; return false; } addedFiles.insert(filename.fileName()); } - else if (mod.type() == Mod::MOD_FOLDER) + else if (mod->type() == Mod::MOD_FOLDER) { // untested, but seems to be unused / not possible to reach // FIXME: buggy - does not work with addedFiles - auto filename = mod.fileinfo(); + auto filename = mod->fileinfo(); QString what_to_zip = filename.absoluteFilePath(); QDir dir(what_to_zip); dir.cdUp(); @@ -193,7 +191,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const { zipOut.close(); QFile::remove(targetJarPath); - qCritical() << "Failed to add" << mod.fileinfo().fileName() << "to the jar."; + qCritical() << "Failed to add" << mod->fileinfo().fileName() << "to the jar."; return false; } qDebug() << "Adding folder " << filename.fileName() << " from " @@ -204,7 +202,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const // Make sure we do not continue launching when something is missing or undefined... zipOut.close(); QFile::remove(targetJarPath); - qCritical() << "Failed to add unknown mod type" << mod.fileinfo().fileName() << "to the jar."; + qCritical() << "Failed to add unknown mod type" << mod->fileinfo().fileName() << "to the jar."; return false; } } diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h index bf90cd0b..7f43d158 100644 --- a/launcher/MMCZip.h +++ b/launcher/MMCZip.h @@ -75,7 +75,7 @@ namespace MMCZip /** * take a source jar, add mods to it, resulting in target jar */ - bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList& mods); + bool createModdedJar(QString sourceJarPath, QString targetJarPath, const QList& mods); /** * Find a single file in archive by file name (not path) diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index abc022b6..360e754d 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -700,24 +700,24 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr { out << QString("%1:").arg(label); auto modList = model.allMods(); - std::sort(modList.begin(), modList.end(), [](Mod &a, Mod &b) { - auto aName = a.fileinfo().completeBaseName(); - auto bName = b.fileinfo().completeBaseName(); + std::sort(modList.begin(), modList.end(), [](Mod::Ptr a, Mod::Ptr b) { + auto aName = a->fileinfo().completeBaseName(); + auto bName = b->fileinfo().completeBaseName(); return aName.localeAwareCompare(bName) < 0; }); - for(auto & mod: modList) + for(auto mod: modList) { - if(mod.type() == Mod::MOD_FOLDER) + if(mod->type() == Mod::MOD_FOLDER) { - out << u8" [📁] " + mod.fileinfo().completeBaseName() + " (folder)"; + out << u8" [📁] " + mod->fileinfo().completeBaseName() + " (folder)"; continue; } - if(mod.enabled()) { - out << u8" [✔️] " + mod.fileinfo().completeBaseName(); + if(mod->enabled()) { + out << u8" [✔️]" + mod->fileinfo().completeBaseName(); } else { - out << u8" [❌] " + mod.fileinfo().completeBaseName() + " (disabled)"; + out << u8" [❌] " + mod->fileinfo().completeBaseName() + " (disabled)"; } } @@ -1136,16 +1136,16 @@ std::shared_ptr MinecraftInstance::gameOptionsModel() const return m_game_options; } -QList< Mod > MinecraftInstance::getJarMods() const +QList MinecraftInstance::getJarMods() const { auto profile = m_components->getProfile(); - QList mods; + QList mods; for (auto jarmod : profile->getJarMods()) { QStringList jar, temp1, temp2, temp3; jarmod->getApplicableFiles(currentSystem, jar, temp1, temp2, temp3, jarmodsPath().absolutePath()); // QString filePath = jarmodsPath().absoluteFilePath(jarmod->filename(currentSystem)); - mods.push_back(Mod(QFileInfo(jar[0]))); + mods.push_back(new Mod(QFileInfo(jar[0]))); } return mods; } diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index 05450d41..8e1c67f2 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -81,7 +81,7 @@ public: shared_qobject_ptr createLaunchTask(AuthSessionPtr account, MinecraftServerTargetPtr serverToJoin) override; QStringList extraArguments() const override; QStringList verboseDescription(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin) override; - QList getJarMods() const; + QList getJarMods() const; QString createLaunchScript(AuthSessionPtr session, MinecraftServerTargetPtr serverToJoin); /// get arguments passed to java QStringList javaArguments() const; diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index cbbbd362..3d3becd7 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -39,10 +39,12 @@ #include #include +#include "QObjectPtr.h" #include "ModDetails.h" -class Mod +class Mod : public QObject { + Q_OBJECT public: enum ModType { @@ -53,6 +55,8 @@ public: MOD_LITEMOD, //!< The mod is a litemod }; + using Ptr = shared_qobject_ptr; + Mod() = default; Mod(const QFileInfo &file); explicit Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata); diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index d8170067..e0391c01 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -134,7 +134,7 @@ void ModFolderModel::finishUpdate() QSet newSet(newList.begin(), newList.end()); #else QSet currentSet = modsIndex.keys().toSet(); - auto & newMods = m_update->mods; + auto& newMods = m_update->mods; QSet newSet = newMods.keys().toSet(); #endif @@ -142,19 +142,20 @@ void ModFolderModel::finishUpdate() { QSet kept = currentSet; kept.intersect(newSet); - for(auto & keptMod: kept) { - auto & newMod = newMods[keptMod]; + for(auto& keptMod : kept) { + auto* newMod = newMods[keptMod]; auto row = modsIndex[keptMod]; - auto & currentMod = mods[row]; - if(newMod.dateTimeChanged() == currentMod.dateTimeChanged()) { + auto currentMod = mods[row]; + if(newMod->dateTimeChanged() == currentMod->dateTimeChanged()) { // no significant change, ignore... continue; } - auto & oldMod = mods[row]; - if(oldMod.isResolving()) { - activeTickets.remove(oldMod.resolutionTicket()); + auto oldMod = mods[row]; + if(oldMod->isResolving()) { + activeTickets.remove(oldMod->resolutionTicket()); } - oldMod = newMod; + + mods[row] = newMod; resolveMod(mods[row]); emit dataChanged(index(row, 0), index(row, columnCount(QModelIndex()) - 1)); } @@ -173,9 +174,10 @@ void ModFolderModel::finishUpdate() int removedIndex = *iter; beginRemoveRows(QModelIndex(), removedIndex, removedIndex); auto removedIter = mods.begin() + removedIndex; - if(removedIter->isResolving()) { - activeTickets.remove(removedIter->resolutionTicket()); + if((*removedIter)->isResolving()) { + activeTickets.remove((*removedIter)->resolutionTicket()); } + mods.erase(removedIter); endRemoveRows(); } @@ -201,8 +203,8 @@ void ModFolderModel::finishUpdate() { modsIndex.clear(); int idx = 0; - for(auto & mod: mods) { - modsIndex[mod.internal_id()] = idx; + for(auto mod: mods) { + modsIndex[mod->internal_id()] = idx; idx++; } } @@ -217,17 +219,17 @@ void ModFolderModel::finishUpdate() } } -void ModFolderModel::resolveMod(Mod& m) +void ModFolderModel::resolveMod(Mod::Ptr m) { - if(!m.shouldResolve()) { + if(!m->shouldResolve()) { return; } - auto task = new LocalModParseTask(nextResolutionTicket, m.type(), m.fileinfo()); + auto task = new LocalModParseTask(nextResolutionTicket, m->type(), m->fileinfo()); auto result = task->result(); - result->id = m.internal_id(); + result->id = m->internal_id(); activeTickets.insert(nextResolutionTicket, result); - m.setResolving(true, nextResolutionTicket); + m->setResolving(true, nextResolutionTicket); nextResolutionTicket++; QThreadPool *threadPool = QThreadPool::globalInstance(); connect(task, &LocalModParseTask::finished, this, &ModFolderModel::finishModParse); @@ -243,8 +245,8 @@ void ModFolderModel::finishModParse(int token) auto result = *iter; activeTickets.remove(token); int row = modsIndex[result->id]; - auto & mod = mods[row]; - mod.finishResolvingWithDetails(result->details); + auto mod = mods[row]; + mod->finishResolvingWithDetails(result->details); emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1)); } @@ -269,9 +271,9 @@ bool ModFolderModel::isValid() return m_dir.exists() && m_dir.isReadable(); } -auto ModFolderModel::selectedMods(QModelIndexList& indexes) -> std::list +auto ModFolderModel::selectedMods(QModelIndexList& indexes) -> std::list { - std::list selected_mods; + std::list selected_mods; for (auto i : indexes) { if(i.column() != 0) continue; @@ -370,9 +372,9 @@ bool ModFolderModel::uninstallMod(const QString& filename, bool preserve_metadat { for(auto mod : allMods()){ - if(mod.fileinfo().fileName() == filename){ + if(mod->fileinfo().fileName() == filename){ auto index_dir = indexDir(); - mod.destroy(index_dir, preserve_metadata); + mod->destroy(index_dir, preserve_metadata); return true; } } @@ -413,9 +415,9 @@ bool ModFolderModel::deleteMods(const QModelIndexList& indexes) if(i.column() != 0) { continue; } - Mod &m = mods[i.row()]; + auto m = mods[i.row()]; auto index_dir = indexDir(); - m.destroy(index_dir); + m->destroy(index_dir); } return true; } @@ -442,9 +444,9 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const switch (column) { case NameColumn: - return mods[row].name(); + return mods[row]->name(); case VersionColumn: { - switch(mods[row].type()) { + switch(mods[row]->type()) { case Mod::MOD_FOLDER: return tr("Folder"); case Mod::MOD_SINGLEFILE: @@ -452,23 +454,23 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const default: break; } - return mods[row].version(); + return mods[row]->version(); } case DateColumn: - return mods[row].dateTimeChanged(); + return mods[row]->dateTimeChanged(); default: return QVariant(); } case Qt::ToolTipRole: - return mods[row].internal_id(); + return mods[row]->internal_id(); case Qt::CheckStateRole: switch (column) { case ActiveColumn: - return mods[row].enabled() ? Qt::Checked : Qt::Unchecked; + return mods[row]->enabled() ? Qt::Checked : Qt::Unchecked; default: return QVariant(); } @@ -508,20 +510,20 @@ bool ModFolderModel::setModStatus(int row, ModFolderModel::ModStatusAction actio break; case Toggle: default: - desiredStatus = !mod.enabled(); + desiredStatus = !mod->enabled(); break; } - if(desiredStatus == mod.enabled()) { + if(desiredStatus == mod->enabled()) { return true; } // preserve the row, but change its ID - auto oldId = mod.internal_id(); - if(!mod.enable(!mod.enabled())) { + auto oldId = mod->internal_id(); + if(!mod->enable(!mod->enabled())) { return false; } - auto newId = mod.internal_id(); + auto newId = mod->internal_id(); if(modsIndex.contains(newId)) { // NOTE: this could handle a corner case, where we are overwriting a file, because the same 'mod' exists both enabled and disabled // But is it necessary? diff --git a/launcher/minecraft/mod/ModFolderModel.h b/launcher/minecraft/mod/ModFolderModel.h index 10289f8d..04681879 100644 --- a/launcher/minecraft/mod/ModFolderModel.h +++ b/launcher/minecraft/mod/ModFolderModel.h @@ -101,13 +101,13 @@ public: { return size() == 0; } - Mod &operator[](size_t index) + Mod& operator[](size_t index) { - return mods[index]; + return *mods[index]; } - const Mod &at(size_t index) const + const Mod& at(size_t index) const { - return mods.at(index); + return *mods.at(index); } /// Reloads the mod list and returns true if the list changed. @@ -141,12 +141,12 @@ public: return { QString("%1/.index").arg(dir().absolutePath()) }; } - const QList & allMods() + const QList& allMods() { return mods; } - auto selectedMods(QModelIndexList& indexes) -> std::list; + auto selectedMods(QModelIndexList& indexes) -> std::list; public slots: void disableInteraction(bool disabled); @@ -161,7 +161,7 @@ signals: void updateFinished(); private: - void resolveMod(Mod& m); + void resolveMod(Mod::Ptr m); bool setModStatus(int index, ModStatusAction action); protected: @@ -175,5 +175,5 @@ protected: QMap modsIndex; QMap activeTickets; int nextResolutionTicket = 0; - QList mods; + QList mods; }; diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index 4ffb626a..63a6ca90 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -53,33 +53,33 @@ void ModFolderLoadTask::run() // Read JAR files that don't have metadata m_mods_dir.refresh(); for (auto entry : m_mods_dir.entryInfoList()) { - Mod mod(entry); + auto* mod = new Mod(entry); - if (mod.enabled()) { - if (m_result->mods.contains(mod.internal_id())) { - m_result->mods[mod.internal_id()].setStatus(ModStatus::Installed); + if (mod->enabled()) { + if (m_result->mods.contains(mod->internal_id())) { + m_result->mods[mod->internal_id()]->setStatus(ModStatus::Installed); } else { - m_result->mods[mod.internal_id()] = mod; - m_result->mods[mod.internal_id()].setStatus(ModStatus::NoMetadata); + m_result->mods[mod->internal_id()] = mod; + m_result->mods[mod->internal_id()]->setStatus(ModStatus::NoMetadata); } } else { - QString chopped_id = mod.internal_id().chopped(9); + QString chopped_id = mod->internal_id().chopped(9); if (m_result->mods.contains(chopped_id)) { - m_result->mods[mod.internal_id()] = mod; + m_result->mods[mod->internal_id()] = mod; - auto metadata = m_result->mods[chopped_id].metadata(); + auto metadata = m_result->mods[chopped_id]->metadata(); if (metadata) { - mod.setMetadata(*metadata); + mod->setMetadata(*metadata); - m_result->mods[mod.internal_id()].setStatus(ModStatus::Installed); + m_result->mods[mod->internal_id()]->setStatus(ModStatus::Installed); m_result->mods.remove(chopped_id); } } else { - m_result->mods[mod.internal_id()] = mod; - m_result->mods[mod.internal_id()].setStatus(ModStatus::NoMetadata); + m_result->mods[mod->internal_id()] = mod; + m_result->mods[mod->internal_id()]->setStatus(ModStatus::NoMetadata); } } } @@ -97,8 +97,8 @@ void ModFolderLoadTask::getFromMetadata() return; } - Mod mod(m_mods_dir, metadata); - mod.setStatus(ModStatus::NotInstalled); - m_result->mods[mod.internal_id()] = mod; + auto* mod = new Mod(m_mods_dir, metadata); + mod->setStatus(ModStatus::NotInstalled); + m_result->mods[mod->internal_id()] = mod; } } diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.h b/launcher/minecraft/mod/tasks/ModFolderLoadTask.h index 088f873e..7568fdf5 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.h +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.h @@ -48,7 +48,7 @@ class ModFolderLoadTask : public QObject, public QRunnable Q_OBJECT public: struct Result { - QMap mods; + QMap mods; }; using ResultPtr = std::shared_ptr; ResultPtr result() const { diff --git a/launcher/modplatform/CheckUpdateTask.h b/launcher/modplatform/CheckUpdateTask.h index d96fc340..94ee19b3 100644 --- a/launcher/modplatform/CheckUpdateTask.h +++ b/launcher/modplatform/CheckUpdateTask.h @@ -12,7 +12,7 @@ class CheckUpdateTask : public Task { Q_OBJECT public: - CheckUpdateTask(std::list& mods, std::list& mcVersions, ModAPI::ModLoaderTypes loaders, std::shared_ptr mods_folder) + CheckUpdateTask(std::list& mods, std::list& mcVersions, ModAPI::ModLoaderTypes loaders, std::shared_ptr mods_folder) : Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder) {}; struct UpdatableMod { @@ -39,10 +39,10 @@ class CheckUpdateTask : public Task { void executeTask() override = 0; signals: - void checkFailed(Mod failed, QString reason, QUrl recover_url = {}); + void checkFailed(Mod* failed, QString reason, QUrl recover_url = {}); protected: - std::list& m_mods; + std::list& m_mods; std::list& m_game_versions; ModAPI::ModLoaderTypes m_loaders; std::shared_ptr m_mods_folder; diff --git a/launcher/modplatform/EnsureMetadataTask.cpp b/launcher/modplatform/EnsureMetadataTask.cpp index 19e44ce0..7c153511 100644 --- a/launcher/modplatform/EnsureMetadataTask.cpp +++ b/launcher/modplatform/EnsureMetadataTask.cpp @@ -19,7 +19,7 @@ static ModPlatform::ProviderCapabilities ProviderCaps; static ModrinthAPI modrinth_api; static FlameAPI flame_api; -EnsureMetadataTask::EnsureMetadataTask(Mod& mod, QDir dir, ModPlatform::Provider prov) : Task(nullptr), m_index_dir(dir), m_provider(prov) +EnsureMetadataTask::EnsureMetadataTask(Mod* mod, QDir dir, ModPlatform::Provider prov) : Task(nullptr), m_index_dir(dir), m_provider(prov) { auto hash = getHash(mod); if (hash.isEmpty()) @@ -28,11 +28,11 @@ EnsureMetadataTask::EnsureMetadataTask(Mod& mod, QDir dir, ModPlatform::Provider m_mods.insert(hash, mod); } -EnsureMetadataTask::EnsureMetadataTask(std::list& mods, QDir dir, ModPlatform::Provider prov) +EnsureMetadataTask::EnsureMetadataTask(std::list& mods, QDir dir, ModPlatform::Provider prov) : Task(nullptr), m_index_dir(dir), m_provider(prov) { - for (auto& mod : mods) { - if (!mod.valid()) { + for (auto* mod : mods) { + if (!mod->valid()) { emitFail(mod); continue; } @@ -47,14 +47,14 @@ EnsureMetadataTask::EnsureMetadataTask(std::list& mods, QDir dir, ModPlatfo } } -QString EnsureMetadataTask::getHash(Mod& mod) +QString EnsureMetadataTask::getHash(Mod* mod) { /* Here we create a mapping hash -> mod, because we need that relationship to parse the API routes */ QByteArray jar_data; try { - jar_data = FS::read(mod.fileinfo().absoluteFilePath()); + jar_data = FS::read(mod->fileinfo().absoluteFilePath()); } catch (FS::FileSystemException& e) { - qCritical() << QString("Failed to open / read JAR file of %1").arg(mod.name()); + qCritical() << QString("Failed to open / read JAR file of %1").arg(mod->name()); qCritical() << QString("Reason: ") << e.cause(); return {}; @@ -95,19 +95,19 @@ void EnsureMetadataTask::executeTask() { setStatus(tr("Checking if mods have metadata...")); - for (auto mod : m_mods) { - if (!mod.valid()) + for (auto* mod : m_mods) { + if (!mod->valid()) continue; // They already have the right metadata :o - if (mod.status() != ModStatus::NoMetadata && mod.metadata() && mod.metadata()->provider == m_provider) { - qDebug() << "Mod" << mod.name() << "already has metadata!"; + if (mod->status() != ModStatus::NoMetadata && mod->metadata() && mod->metadata()->provider == m_provider) { + qDebug() << "Mod" << mod->name() << "already has metadata!"; emitReady(mod); return; } // Folders don't have metadata - if (mod.type() == Mod::MOD_FOLDER) { + if (mod->type() == Mod::MOD_FOLDER) { emitReady(mod); return; } @@ -125,7 +125,7 @@ void EnsureMetadataTask::executeTask() } auto invalidade_leftover = [this] { - QMutableHashIterator mods_iter(m_mods); + QMutableHashIterator mods_iter(m_mods); while (mods_iter.hasNext()) { auto mod = mods_iter.next(); emitFail(mod.value()); @@ -170,23 +170,23 @@ void EnsureMetadataTask::executeTask() setStatus(tr("Requesting metadata information from %1...").arg(ProviderCaps.readableName(m_provider))); else if (!m_mods.empty()) setStatus(tr("Requesting metadata information from %1 for '%2'...") - .arg(ProviderCaps.readableName(m_provider), m_mods.begin().value().name())); + .arg(ProviderCaps.readableName(m_provider), m_mods.begin().value()->name())); m_current_task = version_task.get(); version_task->start(); } -void EnsureMetadataTask::emitReady(Mod& m) +void EnsureMetadataTask::emitReady(Mod* m) { - qDebug() << QString("Generated metadata for %1").arg(m.name()); + qDebug() << QString("Generated metadata for %1").arg(m->name()); emit metadataReady(m); m_mods.remove(getHash(m)); } -void EnsureMetadataTask::emitFail(Mod& m) +void EnsureMetadataTask::emitFail(Mod* m) { - qDebug() << QString("Failed to generate metadata for %1").arg(m.name()); + qDebug() << QString("Failed to generate metadata for %1").arg(m->name()); emit metadataFailed(m); m_mods.remove(getHash(m)); @@ -224,8 +224,8 @@ NetJob::Ptr EnsureMetadataTask::modrinthVersionsTask() try { auto entry = Json::requireObject(entries, hash); - setStatus(tr("Parsing API response from Modrinth for '%1'...").arg(mod.name())); - qDebug() << "Getting version for" << mod.name() << "from Modrinth"; + setStatus(tr("Parsing API response from Modrinth for '%1'...").arg(mod->name())); + qDebug() << "Getting version for" << mod->name() << "from Modrinth"; m_temp_versions.insert(hash, Modrinth::loadIndexedPackVersion(entry)); } catch (Json::JsonException& e) { @@ -284,17 +284,22 @@ NetJob::Ptr EnsureMetadataTask::modrinthProjectsTask() for (auto entry : entries) { auto entry_obj = Json::requireObject(entry); - auto entry_id = Json::requireString(entry_obj, "id"); - auto hash = addonIds.find(entry_id).value(); + ModPlatform::IndexedPack pack; + Modrinth::loadIndexedPack(pack, entry_obj); - auto mod = m_mods.find(hash).value(); + auto hash = addonIds.find(pack.addonId.toString()).value(); + + auto mod_iter = m_mods.find(hash); + if (mod_iter == m_mods.end()) { + qWarning() << "Invalid project id from the API response."; + continue; + } + + auto* mod = mod_iter.value(); try { - setStatus(tr("Parsing API response from Modrinth for '%1'...").arg(mod.name())); - - ModPlatform::IndexedPack pack; - Modrinth::loadIndexedPack(pack, entry_obj); + setStatus(tr("Parsing API response from Modrinth for '%1'...").arg(mod->name())); modrinthCallback(pack, m_temp_versions.find(hash).value(), mod); } catch (Json::JsonException& e) { @@ -365,7 +370,7 @@ NetJob::Ptr EnsureMetadataTask::flameVersionsTask() continue; } - setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(mod->name())); + setStatus(tr("Parsing API response from CurseForge for '%1'...").arg((*mod)->name())); m_temp_versions.insert(fingerprint, FlameMod::loadIndexedPackVersion(file_obj)); } @@ -385,7 +390,10 @@ NetJob::Ptr EnsureMetadataTask::flameProjectsTask() for (auto const& hash : m_mods.keys()) { if (m_temp_versions.contains(hash)) { auto const& data = m_temp_versions.find(hash).value(); - addonIds.insert(data.addonId.toString(), hash); + + auto id_str = data.addonId.toString(); + if (!id_str.isEmpty()) + addonIds.insert(data.addonId.toString(), hash); } } @@ -429,7 +437,7 @@ NetJob::Ptr EnsureMetadataTask::flameProjectsTask() auto mod = m_mods.find(hash).value(); try { - setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(mod.name())); + setStatus(tr("Parsing API response from CurseForge for '%1'...").arg(mod->name())); ModPlatform::IndexedPack pack; FlameMod::loadIndexedPack(pack, entry_obj); @@ -451,10 +459,10 @@ NetJob::Ptr EnsureMetadataTask::flameProjectsTask() return proj_task; } -void EnsureMetadataTask::modrinthCallback(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, Mod& mod) +void EnsureMetadataTask::modrinthCallback(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, Mod* mod) { // Prevent file name mismatch - ver.fileName = mod.fileinfo().fileName(); + ver.fileName = mod->fileinfo().fileName(); if (ver.fileName.endsWith(".disabled")) ver.fileName.chop(9); @@ -479,16 +487,16 @@ void EnsureMetadataTask::modrinthCallback(ModPlatform::IndexedPack& pack, ModPla return; } - mod.setMetadata(metadata); + mod->setMetadata(metadata); emitReady(mod); } -void EnsureMetadataTask::flameCallback(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, Mod& mod) +void EnsureMetadataTask::flameCallback(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, Mod* mod) { try { // Prevent file name mismatch - ver.fileName = mod.fileinfo().fileName(); + ver.fileName = mod->fileinfo().fileName(); if (ver.fileName.endsWith(".disabled")) ver.fileName.chop(9); @@ -513,7 +521,7 @@ void EnsureMetadataTask::flameCallback(ModPlatform::IndexedPack& pack, ModPlatfo return; } - mod.setMetadata(metadata); + mod->setMetadata(metadata); emitReady(mod); } catch (Json::JsonException& e) { diff --git a/launcher/modplatform/EnsureMetadataTask.h b/launcher/modplatform/EnsureMetadataTask.h index 880503b9..d40a972e 100644 --- a/launcher/modplatform/EnsureMetadataTask.h +++ b/launcher/modplatform/EnsureMetadataTask.h @@ -12,8 +12,8 @@ class EnsureMetadataTask : public Task { Q_OBJECT public: - EnsureMetadataTask(Mod&, QDir, ModPlatform::Provider = ModPlatform::Provider::MODRINTH); - EnsureMetadataTask(std::list&, QDir, ModPlatform::Provider = ModPlatform::Provider::MODRINTH); + EnsureMetadataTask(Mod*, QDir, ModPlatform::Provider = ModPlatform::Provider::MODRINTH); + EnsureMetadataTask(std::list&, QDir, ModPlatform::Provider = ModPlatform::Provider::MODRINTH); ~EnsureMetadataTask() = default; @@ -31,21 +31,21 @@ class EnsureMetadataTask : public Task { auto flameProjectsTask() -> NetJob::Ptr; // Helpers - void emitReady(Mod&); - void emitFail(Mod&); + void emitReady(Mod*); + void emitFail(Mod*); - auto getHash(Mod&) -> QString; + auto getHash(Mod*) -> QString; private slots: - void modrinthCallback(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, Mod&); - void flameCallback(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, Mod&); + void modrinthCallback(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, Mod*); + void flameCallback(ModPlatform::IndexedPack& pack, ModPlatform::IndexedVersion& ver, Mod*); signals: - void metadataReady(Mod&); - void metadataFailed(Mod&); + void metadataReady(Mod*); + void metadataFailed(Mod*); private: - QHash m_mods; + QHash m_mods; QDir m_index_dir; ModPlatform::Provider m_provider; diff --git a/launcher/modplatform/flame/FlameCheckUpdate.cpp b/launcher/modplatform/flame/FlameCheckUpdate.cpp index be12dee3..68a4589b 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.cpp +++ b/launcher/modplatform/flame/FlameCheckUpdate.cpp @@ -117,16 +117,16 @@ void FlameCheckUpdate::executeTask() setStatus(tr("Preparing mods for CurseForge...")); int i = 0; - for (auto mod : m_mods) { - if (!mod.enabled()) { + for (auto* mod : m_mods) { + if (!mod->enabled()) { emit checkFailed(mod, tr("Disabled mods won't be updated, to prevent mod duplication issues!")); continue; } - setStatus(tr("Getting API response from CurseForge for '%1'").arg(mod.name())); + setStatus(tr("Getting API response from CurseForge for '%1'").arg(mod->name())); setProgress(i++, m_mods.size()); - auto latest_ver = api.getLatestVersion({ mod.metadata()->project_id.toString(), m_game_versions, m_loaders }); + auto latest_ver = api.getLatestVersion({ mod->metadata()->project_id.toString(), m_game_versions, m_loaders }); // Check if we were aborted while getting the latest version if (m_was_aborted) { @@ -134,7 +134,7 @@ void FlameCheckUpdate::executeTask() return; } - setStatus(tr("Parsing the API response from CurseForge for '%1'...").arg(mod.name())); + setStatus(tr("Parsing the API response from CurseForge for '%1'...").arg(mod->name())); if (!latest_ver.addonId.isValid()) { emit checkFailed(mod, tr("No valid version found for this mod. It's probably unavailable for the current game " @@ -142,7 +142,7 @@ void FlameCheckUpdate::executeTask() continue; } - if (latest_ver.downloadUrl.isEmpty() && latest_ver.fileId != mod.metadata()->file_id) { + if (latest_ver.downloadUrl.isEmpty() && latest_ver.fileId != mod->metadata()->file_id) { auto pack = getProjectInfo(latest_ver); auto recover_url = QString("%1/download/%2").arg(pack.websiteUrl, latest_ver.fileId.toString()); emit checkFailed(mod, tr("Mod has a new update available, but is opted-out on CurseForge"), recover_url); @@ -150,26 +150,26 @@ void FlameCheckUpdate::executeTask() continue; } - if (!latest_ver.hash.isEmpty() && (mod.metadata()->hash != latest_ver.hash || mod.status() == ModStatus::NotInstalled)) { + if (!latest_ver.hash.isEmpty() && (mod->metadata()->hash != latest_ver.hash || mod->status() == ModStatus::NotInstalled)) { // Fake pack with the necessary info to pass to the download task :) ModPlatform::IndexedPack pack; - pack.name = mod.name(); - pack.slug = mod.metadata()->slug; - pack.addonId = mod.metadata()->project_id; - pack.websiteUrl = mod.homeurl(); - for (auto& author : mod.authors()) + pack.name = mod->name(); + pack.slug = mod->metadata()->slug; + pack.addonId = mod->metadata()->project_id; + pack.websiteUrl = mod->homeurl(); + for (auto& author : mod->authors()) pack.authors.append({ author }); - pack.description = mod.description(); + pack.description = mod->description(); pack.provider = ModPlatform::Provider::FLAME; - auto old_version = mod.version(); - if (old_version.isEmpty() && mod.status() != ModStatus::NotInstalled) { - auto current_ver = getFileInfo(latest_ver.addonId.toInt(), mod.metadata()->file_id.toInt()); + auto old_version = mod->version(); + if (old_version.isEmpty() && mod->status() != ModStatus::NotInstalled) { + auto current_ver = getFileInfo(latest_ver.addonId.toInt(), mod->metadata()->file_id.toInt()); old_version = current_ver.version; } auto download_task = new ModDownloadTask(pack, latest_ver, m_mods_folder); - m_updatable.emplace_back(mod.name(), mod.metadata()->hash, old_version, latest_ver.version, + m_updatable.emplace_back(pack.name, mod->metadata()->hash, old_version, latest_ver.version, api.getModFileChangelog(latest_ver.addonId.toInt(), latest_ver.fileId.toInt()), ModPlatform::Provider::FLAME, download_task); } diff --git a/launcher/modplatform/flame/FlameCheckUpdate.h b/launcher/modplatform/flame/FlameCheckUpdate.h index f068f08f..0891891d 100644 --- a/launcher/modplatform/flame/FlameCheckUpdate.h +++ b/launcher/modplatform/flame/FlameCheckUpdate.h @@ -8,7 +8,7 @@ class FlameCheckUpdate : public CheckUpdateTask { Q_OBJECT public: - FlameCheckUpdate(std::list& mods, std::list& mcVersions, ModAPI::ModLoaderTypes loaders, std::shared_ptr mods_folder) + FlameCheckUpdate(std::list& mods, std::list& mcVersions, ModAPI::ModLoaderTypes loaders, std::shared_ptr mods_folder) : CheckUpdateTask(mods, mcVersions, loaders, mods_folder) {} diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp index 5d936fec..79d8edf7 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.cpp @@ -27,29 +27,29 @@ void ModrinthCheckUpdate::executeTask() setStatus(tr("Preparing mods for Modrinth...")); setProgress(0, 3); - QHash mappings; + QHash mappings; // Create all hashes QStringList hashes; auto best_hash_type = ProviderCaps.hashType(ModPlatform::Provider::MODRINTH).first(); - for (auto mod : m_mods) { - if (!mod.enabled()) { + for (auto* mod : m_mods) { + if (!mod->enabled()) { emit checkFailed(mod, tr("Disabled mods won't be updated, to prevent mod duplication issues!")); continue; } - auto hash = mod.metadata()->hash; + auto hash = mod->metadata()->hash; // Sadly the API can only handle one hash type per call, se we // need to generate a new hash if the current one is innadequate // (though it will rarely happen, if at all) - if (mod.metadata()->hash_format != best_hash_type) { + if (mod->metadata()->hash_format != best_hash_type) { QByteArray jar_data; try { - jar_data = FS::read(mod.fileinfo().absoluteFilePath()); + jar_data = FS::read(mod->fileinfo().absoluteFilePath()); } catch (FS::FileSystemException& e) { - qCritical() << QString("Failed to open / read JAR file of %1").arg(mod.name()); + qCritical() << QString("Failed to open / read JAR file of %1").arg(mod->name()); qCritical() << QString("Reason: ") << e.cause(); failed(e.what()); @@ -90,7 +90,7 @@ void ModrinthCheckUpdate::executeTask() // If the returned project is empty, but we have Modrinth metadata, // it means this specific version is not available if (project_obj.isEmpty()) { - qDebug() << "Mod " << mappings.find(hash).value().name() << " got an empty response."; + qDebug() << "Mod " << mappings.find(hash).value()->name() << " got an empty response."; qDebug() << "Hash: " << hash; emit checkFailed( @@ -134,24 +134,24 @@ void ModrinthCheckUpdate::executeTask() auto mod = *mod_iter; auto key = project_ver.hash; - if ((key != hash && project_ver.is_preferred) || (mod.status() == ModStatus::NotInstalled)) { - if (mod.version() == project_ver.version_number) + if ((key != hash && project_ver.is_preferred) || (mod->status() == ModStatus::NotInstalled)) { + if (mod->version() == project_ver.version_number) continue; // Fake pack with the necessary info to pass to the download task :) ModPlatform::IndexedPack pack; - pack.name = mod.name(); - pack.slug = mod.metadata()->slug; - pack.addonId = mod.metadata()->project_id; - pack.websiteUrl = mod.homeurl(); - for (auto& author : mod.authors()) + pack.name = mod->name(); + pack.slug = mod->metadata()->slug; + pack.addonId = mod->metadata()->project_id; + pack.websiteUrl = mod->homeurl(); + for (auto& author : mod->authors()) pack.authors.append({ author }); - pack.description = mod.description(); + pack.description = mod->description(); pack.provider = ModPlatform::Provider::MODRINTH; auto download_task = new ModDownloadTask(pack, project_ver, m_mods_folder); - m_updatable.emplace_back(mod.name(), hash, mod.version(), project_ver.version_number, project_ver.changelog, + m_updatable.emplace_back(pack.name, hash, mod->version(), project_ver.version_number, project_ver.changelog, ModPlatform::Provider::MODRINTH, download_task); } } diff --git a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h index 7e685a6d..d61667f5 100644 --- a/launcher/modplatform/modrinth/ModrinthCheckUpdate.h +++ b/launcher/modplatform/modrinth/ModrinthCheckUpdate.h @@ -8,7 +8,7 @@ class ModrinthCheckUpdate : public CheckUpdateTask { Q_OBJECT public: - ModrinthCheckUpdate(std::list& mods, std::list& mcVersions, ModAPI::ModLoaderTypes loaders, std::shared_ptr mods_folder) + ModrinthCheckUpdate(std::list& mods, std::list& mcVersions, ModAPI::ModLoaderTypes loaders, std::shared_ptr mods_folder) : CheckUpdateTask(mods, mcVersions, loaders, mods_folder) {} diff --git a/launcher/ui/dialogs/ModUpdateDialog.cpp b/launcher/ui/dialogs/ModUpdateDialog.cpp index 51e37bcf..3dc2a85f 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.cpp +++ b/launcher/ui/dialogs/ModUpdateDialog.cpp @@ -34,7 +34,7 @@ static ModAPI::ModLoaderTypes mcLoaders(BaseInstance* inst) ModUpdateDialog::ModUpdateDialog(QWidget* parent, BaseInstance* instance, const std::shared_ptr mods, - std::list& search_for) + std::list& search_for) : ReviewMessageBox(parent, tr("Confirm mods to update"), "") , m_parent(parent) , m_mod_model(mods) @@ -63,7 +63,7 @@ void ModUpdateDialog::checkCandidates() for (const auto& failed : m_failed_metadata) { const auto& mod = std::get<0>(failed); const auto& reason = std::get<1>(failed); - text += tr("Mod name: %1
File name: %2
Reason: %3

").arg(mod.name(), mod.fileinfo().fileName(), reason); + text += tr("Mod name: %1
File name: %2
Reason: %3

").arg(mod->name(), mod->fileinfo().fileName(), reason); } ScrollMessageBox message_dialog(m_parent, tr("Metadata generation failed"), @@ -86,14 +86,14 @@ void ModUpdateDialog::checkCandidates() if (!m_modrinth_to_update.empty()) { m_modrinth_check_task = new ModrinthCheckUpdate(m_modrinth_to_update, versions, loaders, m_mod_model); connect(m_modrinth_check_task, &CheckUpdateTask::checkFailed, this, - [this](Mod mod, QString reason, QUrl recover_url) { m_failed_check_update.emplace_back(mod, reason, recover_url); }); + [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.emplace_back(mod, reason, recover_url); }); check_task.addTask(m_modrinth_check_task); } if (!m_flame_to_update.empty()) { m_flame_check_task = new FlameCheckUpdate(m_flame_to_update, versions, loaders, m_mod_model); connect(m_flame_check_task, &CheckUpdateTask::checkFailed, this, - [this](Mod mod, QString reason, QUrl recover_url) { m_failed_check_update.emplace_back(mod, reason, recover_url); }); + [this](Mod* mod, QString reason, QUrl recover_url) { m_failed_check_update.emplace_back(mod, reason, recover_url); }); check_task.addTask(m_flame_check_task); } @@ -152,9 +152,9 @@ void ModUpdateDialog::checkCandidates() const auto& reason = std::get<1>(failed); const auto& recover_url = std::get<2>(failed); - qDebug() << mod.name() << " failed to check for updates!"; + qDebug() << mod->name() << " failed to check for updates!"; - text += tr("Mod name: %1").arg(mod.name()) + "
"; + text += tr("Mod name: %1").arg(mod->name()) + "
"; if (!reason.isEmpty()) text += tr("Reason: %1").arg(reason) + "
"; if (!recover_url.isEmpty()) @@ -205,15 +205,15 @@ auto ModUpdateDialog::ensureMetadata() -> bool // A better use of data structures here could remove the need for this QHash QHash should_try_others; - std::list modrinth_tmp; - std::list flame_tmp; + std::list modrinth_tmp; + std::list flame_tmp; bool confirm_rest = false; bool try_others_rest = false; bool skip_rest = false; ModPlatform::Provider provider_rest = ModPlatform::Provider::MODRINTH; - auto addToTmp = [&](Mod& m, ModPlatform::Provider p) { + auto addToTmp = [&](Mod* m, ModPlatform::Provider p) { switch (p) { case ModPlatform::Provider::MODRINTH: modrinth_tmp.push_back(m); @@ -224,9 +224,10 @@ auto ModUpdateDialog::ensureMetadata() -> bool } }; - for (auto& candidate : m_candidates) { - if (candidate.status() != ModStatus::NoMetadata) { - onMetadataEnsured(candidate); + for (auto candidate : m_candidates) { + auto* candidate_ptr = candidate.get(); + if (candidate->status() != ModStatus::NoMetadata) { + onMetadataEnsured(candidate_ptr); continue; } @@ -234,8 +235,8 @@ auto ModUpdateDialog::ensureMetadata() -> bool continue; if (confirm_rest) { - addToTmp(candidate, provider_rest); - should_try_others.insert(candidate.internal_id(), try_others_rest); + addToTmp(candidate_ptr, provider_rest); + should_try_others.insert(candidate->internal_id(), try_others_rest); continue; } @@ -243,7 +244,7 @@ auto ModUpdateDialog::ensureMetadata() -> bool chooser.setDescription(tr("This mod (%1) does not have a metadata yet. We need to create one in order to keep relevant " "information on how to update this " "mod. To do this, please select a mod provider from which we can search for updates for %1.") - .arg(candidate.name())); + .arg(candidate->name())); auto confirmed = chooser.exec() == QDialog::DialogCode::Accepted; auto response = chooser.getResponse(); @@ -256,26 +257,26 @@ auto ModUpdateDialog::ensureMetadata() -> bool try_others_rest = response.try_others; } - should_try_others.insert(candidate.internal_id(), response.try_others); + should_try_others.insert(candidate->internal_id(), response.try_others); if (confirmed) - addToTmp(candidate, response.chosen); + addToTmp(candidate_ptr, response.chosen); } if (!modrinth_tmp.empty()) { auto* modrinth_task = new EnsureMetadataTask(modrinth_tmp, index_dir, ModPlatform::Provider::MODRINTH); - connect(modrinth_task, &EnsureMetadataTask::metadataReady, [this](Mod& candidate) { onMetadataEnsured(candidate); }); - connect(modrinth_task, &EnsureMetadataTask::metadataFailed, [this, &should_try_others](Mod& candidate) { - onMetadataFailed(candidate, should_try_others.find(candidate.internal_id()).value(), ModPlatform::Provider::MODRINTH); + connect(modrinth_task, &EnsureMetadataTask::metadataReady, [this](Mod* candidate) { onMetadataEnsured(candidate); }); + connect(modrinth_task, &EnsureMetadataTask::metadataFailed, [this, &should_try_others](Mod* candidate) { + onMetadataFailed(candidate, should_try_others.find(candidate->internal_id()).value(), ModPlatform::Provider::MODRINTH); }); seq.addTask(modrinth_task); } if (!flame_tmp.empty()) { auto* flame_task = new EnsureMetadataTask(flame_tmp, index_dir, ModPlatform::Provider::FLAME); - connect(flame_task, &EnsureMetadataTask::metadataReady, [this](Mod& candidate) { onMetadataEnsured(candidate); }); - connect(flame_task, &EnsureMetadataTask::metadataFailed, [this, &should_try_others](Mod& candidate) { - onMetadataFailed(candidate, should_try_others.find(candidate.internal_id()).value(), ModPlatform::Provider::FLAME); + connect(flame_task, &EnsureMetadataTask::metadataReady, [this](Mod* candidate) { onMetadataEnsured(candidate); }); + connect(flame_task, &EnsureMetadataTask::metadataFailed, [this, &should_try_others](Mod* candidate) { + onMetadataFailed(candidate, should_try_others.find(candidate->internal_id()).value(), ModPlatform::Provider::FLAME); }); seq.addTask(flame_task); } @@ -290,13 +291,13 @@ auto ModUpdateDialog::ensureMetadata() -> bool return (ret_metadata != QDialog::DialogCode::Rejected); } -void ModUpdateDialog::onMetadataEnsured(Mod& mod) +void ModUpdateDialog::onMetadataEnsured(Mod* mod) { // When the mod is a folder, for instance - if (!mod.metadata()) + if (!mod->metadata()) return; - switch (mod.metadata()->provider) { + switch (mod->metadata()->provider) { case ModPlatform::Provider::MODRINTH: m_modrinth_to_update.push_back(mod); break; @@ -318,14 +319,14 @@ ModPlatform::Provider next(ModPlatform::Provider p) return ModPlatform::Provider::FLAME; } -void ModUpdateDialog::onMetadataFailed(Mod& mod, bool try_others, ModPlatform::Provider first_choice) +void ModUpdateDialog::onMetadataFailed(Mod* mod, bool try_others, ModPlatform::Provider first_choice) { if (try_others) { auto index_dir = indexDir(); auto* task = new EnsureMetadataTask(mod, index_dir, next(first_choice)); - connect(task, &EnsureMetadataTask::metadataReady, [this](Mod& candidate) { onMetadataEnsured(candidate); }); - connect(task, &EnsureMetadataTask::metadataFailed, [this](Mod& candidate) { onMetadataFailed(candidate, false); }); + connect(task, &EnsureMetadataTask::metadataReady, [this](Mod* candidate) { onMetadataEnsured(candidate); }); + connect(task, &EnsureMetadataTask::metadataFailed, [this](Mod* candidate) { onMetadataFailed(candidate, false); }); m_second_try_metadata->addTask(task); } else { diff --git a/launcher/ui/dialogs/ModUpdateDialog.h b/launcher/ui/dialogs/ModUpdateDialog.h index 336fbba2..b598447d 100644 --- a/launcher/ui/dialogs/ModUpdateDialog.h +++ b/launcher/ui/dialogs/ModUpdateDialog.h @@ -18,7 +18,7 @@ class ModUpdateDialog final : public ReviewMessageBox { explicit ModUpdateDialog(QWidget* parent, BaseInstance* instance, const std::shared_ptr mod_model, - std::list& search_for); + std::list& search_for); void checkCandidates(); @@ -34,8 +34,8 @@ class ModUpdateDialog final : public ReviewMessageBox { auto ensureMetadata() -> bool; private slots: - void onMetadataEnsured(Mod&); - void onMetadataFailed(Mod&, bool try_others = false, ModPlatform::Provider first_choice = ModPlatform::Provider::MODRINTH); + void onMetadataEnsured(Mod*); + void onMetadataFailed(Mod*, bool try_others = false, ModPlatform::Provider first_choice = ModPlatform::Provider::MODRINTH); private: QWidget* m_parent; @@ -45,13 +45,13 @@ class ModUpdateDialog final : public ReviewMessageBox { const std::shared_ptr m_mod_model; - std::list& m_candidates; - std::list m_modrinth_to_update; - std::list m_flame_to_update; + std::list& m_candidates; + std::list m_modrinth_to_update; + std::list m_flame_to_update; SequentialTask* m_second_try_metadata; - std::list> m_failed_metadata; - std::list> m_failed_check_update; + std::list> m_failed_metadata; + std::list> m_failed_check_update; QHash m_tasks; BaseInstance* m_instance; diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index a40cef77..c21cdda4 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -192,7 +192,7 @@ void ModFolderPage::updateMods() if (update_dialog.noUpdates()) { CustomMessageBox::selectable(this, tr("Update checker"), (mods_list.size() == 1) - ? tr("'%1' is up-to-date! :)").arg(mods_list.front().name()) + ? tr("'%1' is up-to-date! :)").arg(mods_list.front()->name()) : tr("All %1mods are up-to-date! :)").arg(use_all ? "" : (tr("selected") + " "))) ->exec(); return;