More generalistaion for ResourceFolderModels

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
This commit is contained in:
TheKodeToad 2023-09-01 00:27:05 +01:00
parent 93876e27f8
commit ee48766996
No known key found for this signature in database
GPG key ID: 5E39D70B4C93C38E
13 changed files with 90 additions and 152 deletions

View file

@ -67,12 +67,8 @@ void ResourceDownloadTask::downloadSucceeded()
m_filesNetJob.reset(); m_filesNetJob.reset();
auto name = std::get<0>(to_delete); auto name = std::get<0>(to_delete);
auto filename = std::get<1>(to_delete); auto filename = std::get<1>(to_delete);
if (!name.isEmpty() && filename != m_pack_version.fileName) { if (!name.isEmpty() && filename != m_pack_version.fileName)
if (auto model = dynamic_cast<ModFolderModel*>(m_pack_model.get()); model) m_pack_model->uninstallResource(filename, true);
model->uninstallMod(filename, true);
else
m_pack_model->uninstallResource(filename);
}
} }
void ResourceDownloadTask::downloadFailed(QString reason) void ResourceDownloadTask::downloadFailed(QString reason)

View file

@ -28,37 +28,37 @@ class Mod;
namespace Metadata { namespace Metadata {
using ModStruct = Packwiz::V1::Mod; using ModStruct = Packwiz::V1::Mod;
inline auto create(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> ModStruct inline auto create(const QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> ModStruct
{ {
return Packwiz::V1::createModFormat(index_dir, mod_pack, mod_version); return Packwiz::V1::createModFormat(index_dir, mod_pack, mod_version);
} }
inline auto create(QDir& index_dir, Mod& internal_mod, QString mod_slug) -> ModStruct inline auto create(const QDir& index_dir, Mod& internal_mod, QString mod_slug) -> ModStruct
{ {
return Packwiz::V1::createModFormat(index_dir, internal_mod, std::move(mod_slug)); return Packwiz::V1::createModFormat(index_dir, internal_mod, std::move(mod_slug));
} }
inline void update(QDir& index_dir, ModStruct& mod) inline void update(const QDir& index_dir, ModStruct& mod)
{ {
Packwiz::V1::updateModIndex(index_dir, mod); Packwiz::V1::updateModIndex(index_dir, mod);
} }
inline void remove(QDir& index_dir, QString mod_slug) inline void remove(const QDir& index_dir, QString mod_slug)
{ {
Packwiz::V1::deleteModIndex(index_dir, mod_slug); Packwiz::V1::deleteModIndex(index_dir, mod_slug);
} }
inline void remove(QDir& index_dir, QVariant& mod_id) inline void remove(const QDir& index_dir, QVariant& mod_id)
{ {
Packwiz::V1::deleteModIndex(index_dir, mod_id); Packwiz::V1::deleteModIndex(index_dir, mod_id);
} }
inline auto get(QDir& index_dir, QString mod_slug) -> ModStruct inline auto get(const QDir& index_dir, QString mod_slug) -> ModStruct
{ {
return Packwiz::V1::getIndexForMod(index_dir, std::move(mod_slug)); return Packwiz::V1::getIndexForMod(index_dir, std::move(mod_slug));
} }
inline auto get(QDir& index_dir, QVariant& mod_id) -> ModStruct inline auto get(const QDir& index_dir, QVariant& mod_id) -> ModStruct
{ {
return Packwiz::V1::getIndexForMod(index_dir, mod_id); return Packwiz::V1::getIndexForMod(index_dir, mod_id);
} }

View file

@ -36,7 +36,6 @@
#include "Mod.h" #include "Mod.h"
#include <QDebug>
#include <QDir> #include <QDir>
#include <QRegularExpression> #include <QRegularExpression>
#include <QString> #include <QString>

View file

@ -51,13 +51,9 @@
#include "Application.h" #include "Application.h"
#include "Json.h"
#include "Resource.h" #include "Resource.h"
#include "minecraft/mod/tasks/LocalModParseTask.h" #include "minecraft/mod/tasks/LocalModParseTask.h"
#include "minecraft/mod/tasks/LocalModUpdateTask.h" #include "minecraft/mod/tasks/LocalModUpdateTask.h"
#include "minecraft/mod/tasks/ResourceFolderLoadTask.h"
#include "modplatform/ModIndex.h"
#include "modplatform/flame/FlameAPI.h"
#include "modplatform/flame/FlameModIndex.h" #include "modplatform/flame/FlameModIndex.h"
ModFolderModel::ModFolderModel(const QDir& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent) ModFolderModel::ModFolderModel(const QDir& dir, BaseInstance* instance, bool is_indexed, bool create_dir, QObject* parent)
@ -184,58 +180,11 @@ Task* ModFolderModel::createParseTask(Resource& resource)
return new LocalModParseTask(m_next_resolution_ticket, resource.type(), resource.fileinfo()); return new LocalModParseTask(m_next_resolution_ticket, resource.type(), resource.fileinfo());
} }
bool ModFolderModel::uninstallMod(const QString& filename, bool preserve_metadata)
{
for (auto mod : allMods()) {
if (mod->fileinfo().fileName() == filename) {
auto index_dir = indexDir();
mod->destroy(index_dir, preserve_metadata, false);
update();
return true;
}
}
return false;
}
bool ModFolderModel::deleteMods(const QModelIndexList& indexes)
{
if (indexes.isEmpty())
return true;
for (auto i : indexes) {
if (i.column() != 0) {
continue;
}
auto m = at(i.row());
auto index_dir = indexDir();
m->destroy(index_dir);
}
update();
return true;
}
bool ModFolderModel::isValid() bool ModFolderModel::isValid()
{ {
return m_dir.exists() && m_dir.isReadable(); return m_dir.exists() && m_dir.isReadable();
} }
bool ModFolderModel::startWatching()
{
// Remove orphaned metadata next time
m_first_folder_load = true;
return ResourceFolderModel::startWatching({ m_dir.absolutePath(), indexDir().absolutePath() });
}
bool ModFolderModel::stopWatching()
{
return ResourceFolderModel::stopWatching({ m_dir.absolutePath(), indexDir().absolutePath() });
}
auto ModFolderModel::selectedMods(QModelIndexList& indexes) -> QList<Mod*> auto ModFolderModel::selectedMods(QModelIndexList& indexes) -> QList<Mod*>
{ {
QList<Mod*> selected_resources; QList<Mod*> selected_resources;
@ -280,47 +229,3 @@ void ModFolderModel::onParseSucceeded(int ticket, QString mod_id)
emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1)); emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1));
} }
static const FlameAPI flameAPI;
bool ModFolderModel::installMod(QString file_path, ModPlatform::IndexedVersion& vers)
{
if (vers.addonId.isValid()) {
ModPlatform::IndexedPack pack{
vers.addonId,
ModPlatform::ResourceProvider::FLAME,
};
QEventLoop loop;
auto response = std::make_shared<QByteArray>();
auto job = flameAPI.getProject(vers.addonId.toString(), response);
QObject::connect(job.get(), &Task::failed, [&loop] { loop.quit(); });
QObject::connect(job.get(), &Task::aborted, &loop, &QEventLoop::quit);
QObject::connect(job.get(), &Task::succeeded, [response, this, &vers, &loop, &pack] {
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response for mod info at " << parse_error.offset
<< " reason: " << parse_error.errorString();
qDebug() << *response;
return;
}
try {
auto obj = Json::requireObject(Json::requireObject(doc), "data");
FlameMod::loadIndexedPack(pack, obj);
} catch (const JSONValidationError& e) {
qDebug() << doc;
qWarning() << "Error while reading mod info: " << e.cause();
}
LocalModUpdateTask update_metadata(indexDir(), pack, vers);
QObject::connect(&update_metadata, &Task::finished, &loop, &QEventLoop::quit);
update_metadata.start();
});
job->start();
loop.exec();
}
return ResourceFolderModel::installResource(file_path);
}

View file

@ -74,18 +74,8 @@ class ModFolderModel : public ResourceFolderModel {
[[nodiscard]] Resource* createResource(const QFileInfo& file) override { return new Mod(file); } [[nodiscard]] Resource* createResource(const QFileInfo& file) override { return new Mod(file); }
[[nodiscard]] Task* createParseTask(Resource&) override; [[nodiscard]] Task* createParseTask(Resource&) override;
bool installMod(QString file_path) { return ResourceFolderModel::installResource(file_path); }
bool installMod(QString file_path, ModPlatform::IndexedVersion& vers);
bool uninstallMod(const QString& filename, bool preserve_metadata = false);
/// Deletes all the selected mods
bool deleteMods(const QModelIndexList& indexes);
bool isValid(); bool isValid();
bool startWatching() override;
bool stopWatching() override;
auto selectedMods(QModelIndexList& indexes) -> QList<Mod*>; auto selectedMods(QModelIndexList& indexes) -> QList<Mod*>;
auto allMods() -> QList<Mod*>; auto allMods() -> QList<Mod*>;

View file

@ -172,15 +172,10 @@ bool Resource::enable(EnableAction action)
return true; return true;
} }
bool Resource::destroy(bool attemptTrash) auto Resource::destroy(const QDir& index_dir, bool preserve_metadata, bool attempt_trash) -> bool
{ {
m_type = ResourceType::UNKNOWN; m_type = ResourceType::UNKNOWN;
return (attemptTrash && FS::trash(m_file_info.filePath())) || FS::deletePath(m_file_info.filePath());
}
auto Resource::destroy(QDir& index_dir, bool preserve_metadata, bool attempt_trash) -> bool
{
if (!preserve_metadata) { if (!preserve_metadata) {
qDebug() << QString("Destroying metadata for '%1' on purpose").arg(name()); qDebug() << QString("Destroying metadata for '%1' on purpose").arg(name());
@ -192,7 +187,7 @@ auto Resource::destroy(QDir& index_dir, bool preserve_metadata, bool attempt_tra
} }
} }
return destroy(attempt_trash); return (attempt_trash && FS::trash(m_file_info.filePath())) || FS::deletePath(m_file_info.filePath());
} }
bool Resource::isSymLinkUnder(const QString& instPath) const bool Resource::isSymLinkUnder(const QString& instPath) const

View file

@ -99,8 +99,7 @@ class Resource : public QObject {
} }
// Delete all files of this resource. // Delete all files of this resource.
auto destroy(bool attemptTrash = true) -> bool; auto destroy(const QDir& index_dir, bool preserve_metadata = false, bool attempt_trash = true) -> bool;
auto destroy(QDir& index_dir, bool preserve_metadata = false, bool attempt_trash = true) -> bool;
[[nodiscard]] auto isSymLink() const -> bool { return m_file_info.isSymLink(); } [[nodiscard]] auto isSymLink() const -> bool { return m_file_info.isSymLink(); }

View file

@ -10,6 +10,7 @@
#include <QStyle> #include <QStyle>
#include <QThreadPool> #include <QThreadPool>
#include <QUrl> #include <QUrl>
#include <utility>
#include "Application.h" #include "Application.h"
#include "FileSystem.h" #include "FileSystem.h"
@ -17,6 +18,10 @@
#include "QVariantUtils.h" #include "QVariantUtils.h"
#include "minecraft/mod/tasks/ResourceFolderLoadTask.h" #include "minecraft/mod/tasks/ResourceFolderLoadTask.h"
#include "Json.h"
#include "minecraft/mod/tasks/LocalModUpdateTask.h"
#include "modplatform/flame/FlameAPI.h"
#include "modplatform/flame/FlameModIndex.h"
#include "settings/Setting.h" #include "settings/Setting.h"
#include "tasks/Task.h" #include "tasks/Task.h"
#include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/CustomMessageBox.h"
@ -43,6 +48,9 @@ ResourceFolderModel::~ResourceFolderModel()
bool ResourceFolderModel::startWatching(const QStringList paths) bool ResourceFolderModel::startWatching(const QStringList paths)
{ {
// Remove orphaned metadata next time
m_first_folder_load = true;
if (m_is_watching) if (m_is_watching)
return false; return false;
@ -153,11 +161,55 @@ bool ResourceFolderModel::installResource(QString original_path)
return false; return false;
} }
bool ResourceFolderModel::uninstallResource(QString file_name) bool ResourceFolderModel::installResource(QString path, ModPlatform::IndexedVersion& vers)
{
if (vers.addonId.isValid()) {
ModPlatform::IndexedPack pack{
vers.addonId,
ModPlatform::ResourceProvider::FLAME,
};
QEventLoop loop;
auto response = std::make_shared<QByteArray>();
auto job = FlameAPI().getProject(vers.addonId.toString(), response);
QObject::connect(job.get(), &Task::failed, [&loop] { loop.quit(); });
QObject::connect(job.get(), &Task::aborted, &loop, &QEventLoop::quit);
QObject::connect(job.get(), &Task::succeeded, [response, this, &vers, &loop, &pack] {
QJsonParseError parse_error{};
QJsonDocument doc = QJsonDocument::fromJson(*response, &parse_error);
if (parse_error.error != QJsonParseError::NoError) {
qWarning() << "Error while parsing JSON response for mod info at " << parse_error.offset
<< " reason: " << parse_error.errorString();
qDebug() << *response;
return;
}
try {
auto obj = Json::requireObject(Json::requireObject(doc), "data");
FlameMod::loadIndexedPack(pack, obj);
} catch (const JSONValidationError& e) {
qDebug() << doc;
qWarning() << "Error while reading mod info: " << e.cause();
}
LocalModUpdateTask update_metadata(indexDir(), pack, vers);
QObject::connect(&update_metadata, &Task::finished, &loop, &QEventLoop::quit);
update_metadata.start();
});
job->start();
loop.exec();
}
return installResource(std::move(path));
}
bool ResourceFolderModel::uninstallResource(QString file_name, bool preserve_metadata)
{ {
for (auto& resource : m_resources) { for (auto& resource : m_resources) {
if (resource->fileinfo().fileName() == file_name) { if (resource->fileinfo().fileName() == file_name) {
auto res = resource->destroy(false); auto res = resource->destroy(indexDir(), preserve_metadata, false);
update(); update();
@ -179,7 +231,7 @@ bool ResourceFolderModel::deleteResources(const QModelIndexList& indexes)
auto& resource = m_resources.at(i.row()); auto& resource = m_resources.at(i.row());
resource->destroy(); resource->destroy(indexDir());
} }
update(); update();

View file

@ -49,8 +49,8 @@ class ResourceFolderModel : public QAbstractListModel {
bool stopWatching(const QStringList paths); bool stopWatching(const QStringList paths);
/* Helper methods for subclasses, using a predetermined list of paths. */ /* Helper methods for subclasses, using a predetermined list of paths. */
virtual bool startWatching() { return startWatching({ m_dir.absolutePath() }); } virtual bool startWatching() { return startWatching({ indexDir().absolutePath(), m_dir.absolutePath() }); }
virtual bool stopWatching() { return stopWatching({ m_dir.absolutePath() }); } virtual bool stopWatching() { return stopWatching({ indexDir().absolutePath(), m_dir.absolutePath() }); }
QDir indexDir() { return { QString("%1/.index").arg(dir().absolutePath()) }; } QDir indexDir() { return { QString("%1/.index").arg(dir().absolutePath()) }; }
@ -61,11 +61,13 @@ class ResourceFolderModel : public QAbstractListModel {
*/ */
virtual bool installResource(QString path); virtual bool installResource(QString path);
virtual bool installResource(QString path, ModPlatform::IndexedVersion& vers);
/** Uninstall (i.e. remove all data about it) a resource, given its file name. /** Uninstall (i.e. remove all data about it) a resource, given its file name.
* *
* Returns whether the removal was successful. * Returns whether the removal was successful.
*/ */
virtual bool uninstallResource(QString file_name); virtual bool uninstallResource(QString file_name, bool preserve_metadata = false);
virtual bool deleteResources(const QModelIndexList&); virtual bool deleteResources(const QModelIndexList&);
/** Applies the given 'action' to the resources in 'indexes'. /** Applies the given 'action' to the resources in 'indexes'.

View file

@ -32,7 +32,7 @@
namespace Packwiz { namespace Packwiz {
auto getRealIndexName(QDir& index_dir, QString normalized_fname, bool should_find_match) -> QString auto getRealIndexName(const QDir& index_dir, QString normalized_fname, bool should_find_match) -> QString
{ {
QFile index_file(index_dir.absoluteFilePath(normalized_fname)); QFile index_file(index_dir.absoluteFilePath(normalized_fname));
@ -89,7 +89,7 @@ auto intEntry(toml::table table, QString entry_name) -> int
return node.value_or(0); return node.value_or(0);
} }
auto V1::createModFormat([[maybe_unused]] QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) auto V1::createModFormat([[maybe_unused]] const QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version)
-> Mod -> Mod
{ {
Mod mod; Mod mod;
@ -115,7 +115,7 @@ auto V1::createModFormat([[maybe_unused]] QDir& index_dir, ModPlatform::IndexedP
return mod; return mod;
} }
auto V1::createModFormat(QDir& index_dir, [[maybe_unused]] ::Mod& internal_mod, QString slug) -> Mod auto V1::createModFormat(const QDir& index_dir, [[maybe_unused]] ::Mod& internal_mod, QString slug) -> Mod
{ {
// Try getting metadata if it exists // Try getting metadata if it exists
Mod mod{ getIndexForMod(index_dir, slug) }; Mod mod{ getIndexForMod(index_dir, slug) };
@ -127,7 +127,7 @@ auto V1::createModFormat(QDir& index_dir, [[maybe_unused]] ::Mod& internal_mod,
return {}; return {};
} }
void V1::updateModIndex(QDir& index_dir, Mod& mod) void V1::updateModIndex(const QDir& index_dir, Mod& mod)
{ {
if (!mod.isValid()) { if (!mod.isValid()) {
qCritical() << QString("Tried to update metadata of an invalid mod!"); qCritical() << QString("Tried to update metadata of an invalid mod!");
@ -192,7 +192,7 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod)
index_file.close(); index_file.close();
} }
void V1::deleteModIndex(QDir& index_dir, QString& mod_slug) void V1::deleteModIndex(const QDir& index_dir, QString& mod_slug)
{ {
auto normalized_fname = indexFileName(mod_slug); auto normalized_fname = indexFileName(mod_slug);
auto real_fname = getRealIndexName(index_dir, normalized_fname); auto real_fname = getRealIndexName(index_dir, normalized_fname);
@ -211,7 +211,7 @@ void V1::deleteModIndex(QDir& index_dir, QString& mod_slug)
} }
} }
void V1::deleteModIndex(QDir& index_dir, QVariant& mod_id) void V1::deleteModIndex(const QDir& index_dir, QVariant& mod_id)
{ {
for (auto& file_name : index_dir.entryList(QDir::Filter::Files)) { for (auto& file_name : index_dir.entryList(QDir::Filter::Files)) {
auto mod = getIndexForMod(index_dir, file_name); auto mod = getIndexForMod(index_dir, file_name);
@ -223,7 +223,7 @@ void V1::deleteModIndex(QDir& index_dir, QVariant& mod_id)
} }
} }
auto V1::getIndexForMod(QDir& index_dir, QString slug) -> Mod auto V1::getIndexForMod(const QDir& index_dir, QString slug) -> Mod
{ {
Mod mod; Mod mod;
@ -301,7 +301,7 @@ auto V1::getIndexForMod(QDir& index_dir, QString slug) -> Mod
return mod; return mod;
} }
auto V1::getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod auto V1::getIndexForMod(const QDir& index_dir, QVariant& mod_id) -> Mod
{ {
for (auto& file_name : index_dir.entryList(QDir::Filter::Files)) { for (auto& file_name : index_dir.entryList(QDir::Filter::Files)) {
auto mod = getIndexForMod(index_dir, file_name); auto mod = getIndexForMod(index_dir, file_name);

View file

@ -31,7 +31,7 @@ class Mod;
namespace Packwiz { namespace Packwiz {
auto getRealIndexName(QDir& index_dir, QString normalized_index_name, bool should_match = false) -> QString; auto getRealIndexName(const QDir& index_dir, QString normalized_index_name, bool should_match = false) -> QString;
class V1 { class V1 {
public: public:
@ -67,33 +67,33 @@ class V1 {
/* Generates the object representing the information in a mod.pw.toml file via /* Generates the object representing the information in a mod.pw.toml file via
* its common representation in the launcher, when downloading mods. * its common representation in the launcher, when downloading mods.
* */ * */
static auto createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod; static auto createModFormat(const QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod;
/* Generates the object representing the information in a mod.pw.toml file via /* Generates the object representing the information in a mod.pw.toml file via
* its common representation in the launcher, plus a necessary slug. * its common representation in the launcher, plus a necessary slug.
* */ * */
static auto createModFormat(QDir& index_dir, ::Mod& internal_mod, QString slug) -> Mod; static auto createModFormat(const QDir& index_dir, ::Mod& internal_mod, QString slug) -> Mod;
/* Updates the mod index for the provided mod. /* Updates the mod index for the provided mod.
* This creates a new index if one does not exist already * This creates a new index if one does not exist already
* TODO: Ask the user if they want to override, and delete the old mod's files, or keep the old one. * TODO: Ask the user if they want to override, and delete the old mod's files, or keep the old one.
* */ * */
static void updateModIndex(QDir& index_dir, Mod& mod); static void updateModIndex(const QDir& index_dir, Mod& mod);
/* Deletes the metadata for the mod with the given slug. If the metadata doesn't exist, it does nothing. */ /* Deletes the metadata for the mod with the given slug. If the metadata doesn't exist, it does nothing. */
static void deleteModIndex(QDir& index_dir, QString& mod_slug); static void deleteModIndex(const QDir& index_dir, QString& mod_slug);
/* Deletes the metadata for the mod with the given id. If the metadata doesn't exist, it does nothing. */ /* Deletes the metadata for the mod with the given id. If the metadata doesn't exist, it does nothing. */
static void deleteModIndex(QDir& index_dir, QVariant& mod_id); static void deleteModIndex(const QDir& index_dir, QVariant& mod_id);
/* Gets the metadata for a mod with a particular file name. /* Gets the metadata for a mod with a particular file name.
* If the mod doesn't have a metadata, it simply returns an empty Mod object. * If the mod doesn't have a metadata, it simply returns an empty Mod object.
* */ * */
static auto getIndexForMod(QDir& index_dir, QString slug) -> Mod; static auto getIndexForMod(const QDir& index_dir, QString slug) -> Mod;
/* Gets the metadata for a mod with a particular id. /* Gets the metadata for a mod with a particular id.
* If the mod doesn't have a metadata, it simply returns an empty Mod object. * If the mod doesn't have a metadata, it simply returns an empty Mod object.
* */ * */
static auto getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod; static auto getIndexForMod(const QDir& index_dir, QVariant& mod_id) -> Mod;
}; };
} // namespace Packwiz } // namespace Packwiz

View file

@ -1048,7 +1048,7 @@ void MainWindow::processURLs(QList<QUrl> urls)
qWarning() << "Importing of Data Packs not supported at this time. Ignoring" << localFileName; qWarning() << "Importing of Data Packs not supported at this time. Ignoring" << localFileName;
break; break;
case PackedResourceType::Mod: case PackedResourceType::Mod:
minecraftInst->loaderModList()->installMod(localFileName, version); minecraftInst->loaderModList()->installResource(localFileName, version);
break; break;
case PackedResourceType::ShaderPack: case PackedResourceType::ShaderPack:
minecraftInst->shaderPackList()->installResource(localFileName); minecraftInst->shaderPackList()->installResource(localFileName);

View file

@ -150,7 +150,7 @@ void ModFolderPage::removeItems(const QItemSelection& selection)
if (response != QMessageBox::Yes) if (response != QMessageBox::Yes)
return; return;
} }
m_model->deleteMods(selection.indexes()); m_model->deleteResources(selection.indexes());
} }
void ModFolderPage::installMods() void ModFolderPage::installMods()