refactor: move general code from mod model to its own model

This aims to continue decoupling other types of resources (e.g. resource
packs, shader packs, etc) from mods, so that we don't have to
continuously watch our backs for changes to one of them affecting the
others.

To do so, this creates a more general list model for resources, based on
the mods one, that allows you to extend it with functionality for other
resources.

I had to do some template and preprocessor stuff to get around the
QObject limitation of not allowing templated classes, so that's sadge :c

On the other hand, I tried cleaning up most general-purpose code in the
mod model, and added some documentation, because it looks nice :D

Signed-off-by: flow <flowlnlnln@gmail.com>
This commit is contained in:
flow
2022-08-09 01:58:22 -03:00
parent 3225f514f6
commit ec62d8e973
11 changed files with 779 additions and 456 deletions

View File

@ -44,6 +44,7 @@
#include <QAbstractListModel>
#include "Mod.h"
#include "ResourceFolderModel.h"
#include "minecraft/mod/tasks/ModFolderLoadTask.h"
#include "minecraft/mod/tasks/LocalModParseTask.h"
@ -56,7 +57,7 @@ class QFileSystemWatcher;
* A legacy mod list.
* Backed by a folder.
*/
class ModFolderModel : public QAbstractListModel
class ModFolderModel : public ResourceFolderModel
{
Q_OBJECT
public:
@ -75,48 +76,18 @@ public:
};
ModFolderModel(const QString &dir, bool is_indexed = false);
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::DropActions supportedDropActions() const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
/// flags, mostly to support drag&drop
virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
QStringList mimeTypes() const override;
bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
int columnCount(const QModelIndex &parent) const override;
virtual int rowCount(const QModelIndex &) const override
{
return size();
}
[[nodiscard]] Task* createUpdateTask() override;
[[nodiscard]] Task* createParseTask(Resource const&) override;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
virtual int columnCount(const QModelIndex &parent) const override;
size_t size() const
{
return mods.size();
}
;
bool empty() const
{
return size() == 0;
}
Mod& operator[](size_t index)
{
return *mods[index];
}
const Mod& at(size_t index) const
{
return *mods.at(index);
}
/// Reloads the mod list and returns true if the list changed.
bool update();
/**
* Adds the given mod to the list at the given index - if the list supports custom ordering
*/
bool installMod(const QString& filename);
// Alias for old code, consider those deprecated and don't use in new code :gun:
bool installMod(QString file_path) { return ResourceFolderModel::installResource(file_path); }
void disableInteraction(bool disabled) { ResourceFolderModel::enableInteraction(!disabled); }
bool uninstallMod(const QString& filename, bool preserve_metadata = false);
@ -126,55 +97,27 @@ public:
/// Enable or disable listed mods
bool setModStatus(const QModelIndexList &indexes, ModStatusAction action);
bool isValid();
void startWatching();
void stopWatching();
bool isValid();
QDir& dir()
{
return m_dir;
}
QDir indexDir()
{
return { QString("%1/.index").arg(dir().absolutePath()) };
}
const QList<Mod::Ptr>& allMods()
{
return mods;
}
QDir indexDir() { return { QString("%1/.index").arg(dir().absolutePath()) }; }
auto selectedMods(QModelIndexList& indexes) -> QList<Mod::Ptr>;
auto allMods() -> QList<Mod::Ptr>;
public slots:
void disableInteraction(bool disabled);
RESOURCE_HELPERS(Mod)
private
slots:
void directoryChanged(QString path);
void finishUpdate();
void finishModParse(int token);
signals:
void updateFinished();
void onUpdateSucceeded() override;
void onParseSucceeded(int ticket, QString resource_id) override;
private:
void resolveMod(Mod::Ptr m);
bool setModStatus(int index, ModStatusAction action);
protected:
QFileSystemWatcher *m_watcher;
bool is_watching = false;
ModFolderLoadTask::ResultPtr m_update;
bool scheduled_update = false;
bool interaction_disabled = false;
QDir m_dir;
bool m_is_indexed;
bool m_first_folder_load = true;
QMap<QString, int> modsIndex;
QMap<int, LocalModParseTask::ResultPtr> activeTickets;
int nextResolutionTicket = 0;
QList<Mod::Ptr> mods;
};