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>
2022-08-09 05:58:22 +01:00
|
|
|
#pragma once
|
|
|
|
|
2023-05-25 04:15:34 +01:00
|
|
|
#include <QHeaderView>
|
|
|
|
#include <QAction>
|
|
|
|
#include <QTreeView>
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
#include <QAbstractListModel>
|
|
|
|
#include <QDir>
|
|
|
|
#include <QFileSystemWatcher>
|
|
|
|
#include <QMutex>
|
|
|
|
#include <QSet>
|
2022-08-10 18:42:24 +01:00
|
|
|
#include <QSortFilterProxyModel>
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
|
|
|
#include "Resource.h"
|
|
|
|
|
2023-04-30 03:38:51 +01:00
|
|
|
#include "BaseInstance.h"
|
|
|
|
|
2022-12-15 16:51:07 +00:00
|
|
|
#include "tasks/ConcurrentTask.h"
|
2023-06-21 19:34:40 +01:00
|
|
|
#include "tasks/Task.h"
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
2022-08-10 18:42:24 +01:00
|
|
|
class QSortFilterProxyModel;
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
|
|
|
/** A basic model for external resources.
|
|
|
|
*
|
2022-08-11 22:24:26 +01:00
|
|
|
* This model manages a list of resources. As such, external users of such resources do not own them,
|
|
|
|
* and the resource's lifetime is contingent on the model's lifetime.
|
|
|
|
*
|
|
|
|
* TODO: Make the resources unique pointers accessible through weak pointers.
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
*/
|
|
|
|
class ResourceFolderModel : public QAbstractListModel {
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
2023-05-28 10:15:39 +01:00
|
|
|
ResourceFolderModel(QDir, BaseInstance* instance, QObject* parent = nullptr, bool create_dir = true);
|
2022-09-03 17:25:05 +01:00
|
|
|
~ResourceFolderModel() override;
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
2023-05-25 04:15:34 +01:00
|
|
|
virtual QString id() const { return "resource"; }
|
|
|
|
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
/** Starts watching the paths for changes.
|
|
|
|
*
|
|
|
|
* Returns whether starting to watch all the paths was successful.
|
|
|
|
* If one or more fails, it returns false.
|
|
|
|
*/
|
|
|
|
bool startWatching(const QStringList paths);
|
|
|
|
|
|
|
|
/** Stops watching the paths for changes.
|
|
|
|
*
|
|
|
|
* Returns whether stopping to watch all the paths was successful.
|
|
|
|
* If one or more fails, it returns false.
|
|
|
|
*/
|
|
|
|
bool stopWatching(const QStringList paths);
|
|
|
|
|
2022-08-10 18:42:24 +01:00
|
|
|
/* Helper methods for subclasses, using a predetermined list of paths. */
|
|
|
|
virtual bool startWatching() { return startWatching({ m_dir.absolutePath() }); };
|
|
|
|
virtual bool stopWatching() { return stopWatching({ m_dir.absolutePath() }); };
|
|
|
|
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
/** Given a path in the system, install that resource, moving it to its place in the
|
|
|
|
* instance file hierarchy.
|
|
|
|
*
|
|
|
|
* Returns whether the installation was succcessful.
|
|
|
|
*/
|
|
|
|
virtual bool installResource(QString path);
|
|
|
|
|
|
|
|
/** Uninstall (i.e. remove all data about it) a resource, given its file name.
|
|
|
|
*
|
|
|
|
* Returns whether the removal was successful.
|
|
|
|
*/
|
|
|
|
virtual bool uninstallResource(QString file_name);
|
|
|
|
virtual bool deleteResources(const QModelIndexList&);
|
|
|
|
|
2022-08-13 15:58:39 +01:00
|
|
|
/** Applies the given 'action' to the resources in 'indexes'.
|
|
|
|
*
|
|
|
|
* Returns whether the action was successfully applied to all resources.
|
|
|
|
*/
|
|
|
|
virtual bool setResourceEnabled(const QModelIndexList& indexes, EnableAction action);
|
|
|
|
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
/** Creates a new update task and start it. Returns false if no update was done, like when an update is already underway. */
|
|
|
|
virtual bool update();
|
|
|
|
|
|
|
|
/** Creates a new parse task, if needed, for 'res' and start it.*/
|
2022-09-17 00:00:36 +01:00
|
|
|
virtual void resolveResource(Resource* res);
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
|
|
|
[[nodiscard]] size_t size() const { return m_resources.size(); };
|
|
|
|
[[nodiscard]] bool empty() const { return size() == 0; }
|
2022-08-13 15:58:39 +01:00
|
|
|
[[nodiscard]] Resource& at(int index) { return *m_resources.at(index); }
|
2022-08-10 18:42:24 +01:00
|
|
|
[[nodiscard]] Resource const& at(int index) const { return *m_resources.at(index); }
|
|
|
|
[[nodiscard]] QList<Resource::Ptr> const& all() const { return m_resources; }
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
|
|
|
[[nodiscard]] QDir const& dir() const { return m_dir; }
|
|
|
|
|
2022-08-12 21:09:56 +01:00
|
|
|
/** Checks whether there's any parse tasks being done.
|
|
|
|
*
|
|
|
|
* Since they can be quite expensive, and are usually done in a separate thread, if we were to destroy the model while having
|
|
|
|
* such tasks would introduce an undefined behavior, most likely resulting in a crash.
|
|
|
|
*/
|
|
|
|
[[nodiscard]] bool hasPendingParseTasks() const;
|
|
|
|
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
/* Qt behavior */
|
|
|
|
|
2022-08-10 18:42:24 +01:00
|
|
|
/* Basic columns */
|
2022-08-13 15:58:39 +01:00
|
|
|
enum Columns { ACTIVE_COLUMN = 0, NAME_COLUMN, DATE_COLUMN, NUM_COLUMNS };
|
2023-05-28 21:00:08 +01:00
|
|
|
QStringList columnNames(bool translated = true) const { return translated ? m_column_names_translated : m_column_names; };
|
2022-08-10 18:42:24 +01:00
|
|
|
|
2022-11-13 14:35:55 +00:00
|
|
|
[[nodiscard]] int rowCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : static_cast<int>(size()); }
|
|
|
|
[[nodiscard]] int columnCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : NUM_COLUMNS; };
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
|
|
|
[[nodiscard]] Qt::DropActions supportedDropActions() const override;
|
|
|
|
|
|
|
|
/// flags, mostly to support drag&drop
|
|
|
|
[[nodiscard]] Qt::ItemFlags flags(const QModelIndex& index) const override;
|
|
|
|
[[nodiscard]] QStringList mimeTypes() const override;
|
|
|
|
bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override;
|
|
|
|
|
|
|
|
[[nodiscard]] bool validateIndex(const QModelIndex& index) const;
|
|
|
|
|
2022-08-10 18:42:24 +01:00
|
|
|
[[nodiscard]] QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
2022-08-13 15:58:39 +01:00
|
|
|
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
2022-08-10 18:42:24 +01:00
|
|
|
[[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
|
|
|
|
2023-05-25 04:15:34 +01:00
|
|
|
void setupHeaderAction(QAction* act, int column);
|
|
|
|
void saveHiddenColumn(int column, bool hidden);
|
|
|
|
void loadHiddenColumns(QTreeView* tree);
|
2023-05-28 22:53:15 +01:00
|
|
|
QMenu* createHeaderContextMenu(QTreeView* tree);
|
2023-05-25 04:15:34 +01:00
|
|
|
|
2022-08-10 18:42:24 +01:00
|
|
|
/** This creates a proxy model to filter / sort the model for a UI.
|
|
|
|
*
|
|
|
|
* The actual comparisons and filtering are done directly by the Resource, so to modify behavior go there instead!
|
|
|
|
*/
|
|
|
|
QSortFilterProxyModel* createFilterProxyModel(QObject* parent = nullptr);
|
|
|
|
|
|
|
|
[[nodiscard]] SortType columnToSortKey(size_t column) const;
|
2023-05-25 04:15:34 +01:00
|
|
|
[[nodiscard]] QList<QHeaderView::ResizeMode> columnResizeModes() const { return m_column_resize_modes; }
|
2022-08-10 18:42:24 +01:00
|
|
|
|
|
|
|
class ProxyModel : public QSortFilterProxyModel {
|
|
|
|
public:
|
|
|
|
explicit ProxyModel(QObject* parent = nullptr) : QSortFilterProxyModel(parent) {}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
[[nodiscard]] bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override;
|
|
|
|
[[nodiscard]] bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override;
|
|
|
|
};
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
2023-02-12 09:44:39 +00:00
|
|
|
QString instDirPath() const;
|
|
|
|
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
signals:
|
|
|
|
void updateFinished();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/** This creates a new update task to be executed by update().
|
|
|
|
*
|
|
|
|
* The task should load and parse all resources necessary, and provide a way of accessing such results.
|
|
|
|
*
|
|
|
|
* This Task is normally executed when opening a page, so it shouldn't contain much heavy work.
|
|
|
|
* If such work is needed, try using it in the Task create by createParseTask() instead!
|
|
|
|
*/
|
|
|
|
[[nodiscard]] virtual Task* createUpdateTask();
|
|
|
|
|
|
|
|
/** This creates a new parse task to be executed by onUpdateSucceeded().
|
|
|
|
*
|
|
|
|
* This task should load and parse all heavy info needed by a resource, such as parsing a manifest. It gets executed
|
|
|
|
* in the background, so it slowly updates the UI as tasks get done.
|
|
|
|
*/
|
2022-08-29 02:33:44 +01:00
|
|
|
[[nodiscard]] virtual Task* createParseTask(Resource&) { return nullptr; };
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
|
|
|
/** Standard implementation of the model update logic.
|
|
|
|
*
|
|
|
|
* It uses set operations to find differences between the current state and the updated state,
|
|
|
|
* to act only on those disparities.
|
|
|
|
*
|
|
|
|
* The implementation is at the end of this header.
|
|
|
|
*/
|
|
|
|
template <typename T>
|
|
|
|
void applyUpdates(QSet<QString>& current_set, QSet<QString>& new_set, QMap<QString, T>& new_resources);
|
|
|
|
|
|
|
|
protected slots:
|
|
|
|
void directoryChanged(QString);
|
|
|
|
|
|
|
|
/** Called when the update task is successful.
|
|
|
|
*
|
|
|
|
* This usually calls static_cast on the specific Task type returned by createUpdateTask,
|
|
|
|
* so care must be taken in such cases.
|
2022-08-11 22:24:26 +01:00
|
|
|
* TODO: Figure out a way to express this relationship better without templated classes (Q_OBJECT macro disallows that).
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
*/
|
|
|
|
virtual void onUpdateSucceeded();
|
|
|
|
virtual void onUpdateFailed() {}
|
|
|
|
|
|
|
|
/** Called when the parse task with the given ticket is successful.
|
|
|
|
*
|
|
|
|
* This is just a simple reference implementation. You probably want to override it with your own logic in a subclass
|
|
|
|
* if the resource is complex and has more stuff to parse.
|
|
|
|
*/
|
|
|
|
virtual void onParseSucceeded(int ticket, QString resource_id);
|
2023-06-21 19:34:40 +01:00
|
|
|
virtual void onParseFailed(int ticket, QString resource_id)
|
|
|
|
{
|
|
|
|
Q_UNUSED(ticket);
|
|
|
|
Q_UNUSED(resource_id);
|
|
|
|
}
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
|
|
|
protected:
|
2022-08-10 18:42:24 +01:00
|
|
|
// Represents the relationship between a column's index (represented by the list index), and it's sorting key.
|
|
|
|
// As such, the order in with they appear is very important!
|
2022-08-13 15:58:39 +01:00
|
|
|
QList<SortType> m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE };
|
2023-05-28 21:00:08 +01:00
|
|
|
QStringList m_column_names = {"Enable", "Name", "Last Modified"};
|
|
|
|
QStringList m_column_names_translated = {tr("Enable"), tr("Name"), tr("Last Modified")};
|
2023-06-21 10:31:40 +01:00
|
|
|
QList<QHeaderView::ResizeMode> m_column_resize_modes = { QHeaderView::ResizeToContents, QHeaderView::Stretch, QHeaderView::ResizeToContents };
|
2023-07-07 16:36:57 +01:00
|
|
|
QList<bool> m_columnsHideable = { false, false, true };
|
2022-08-10 18:42:24 +01:00
|
|
|
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
QDir m_dir;
|
2023-05-28 10:15:39 +01:00
|
|
|
BaseInstance* m_instance;
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
QFileSystemWatcher m_watcher;
|
|
|
|
bool m_is_watching = false;
|
|
|
|
|
|
|
|
Task::Ptr m_current_update_task = nullptr;
|
|
|
|
bool m_scheduled_update = false;
|
|
|
|
|
|
|
|
QList<Resource::Ptr> m_resources;
|
|
|
|
|
|
|
|
// Represents the relationship between a resource's internal ID and it's row position on the model.
|
|
|
|
QMap<QString, int> m_resources_index;
|
|
|
|
|
2022-12-15 16:51:07 +00:00
|
|
|
ConcurrentTask m_helper_thread_task;
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
QMap<int, Task::Ptr> m_active_parse_tasks;
|
2022-09-03 17:25:05 +01:00
|
|
|
std::atomic<int> m_next_resolution_ticket = 0;
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/* A macro to define useful functions to handle Resource* -> T* more easily on derived classes */
|
2022-08-11 22:24:26 +01:00
|
|
|
#define RESOURCE_HELPERS(T) \
|
|
|
|
[[nodiscard]] T* operator[](size_t index) \
|
|
|
|
{ \
|
|
|
|
return static_cast<T*>(m_resources[index].get()); \
|
|
|
|
} \
|
|
|
|
[[nodiscard]] T* at(size_t index) \
|
|
|
|
{ \
|
|
|
|
return static_cast<T*>(m_resources[index].get()); \
|
|
|
|
} \
|
|
|
|
[[nodiscard]] const T* at(size_t index) const \
|
|
|
|
{ \
|
|
|
|
return static_cast<const T*>(m_resources.at(index).get()); \
|
|
|
|
} \
|
|
|
|
[[nodiscard]] T* first() \
|
|
|
|
{ \
|
|
|
|
return static_cast<T*>(m_resources.first().get()); \
|
|
|
|
} \
|
|
|
|
[[nodiscard]] T* last() \
|
|
|
|
{ \
|
|
|
|
return static_cast<T*>(m_resources.last().get()); \
|
|
|
|
} \
|
|
|
|
[[nodiscard]] T* find(QString id) \
|
|
|
|
{ \
|
|
|
|
auto iter = std::find_if(m_resources.constBegin(), m_resources.constEnd(), \
|
|
|
|
[&](Resource::Ptr const& r) { return r->internal_id() == id; }); \
|
|
|
|
if (iter == m_resources.constEnd()) \
|
|
|
|
return nullptr; \
|
|
|
|
return static_cast<T*>((*iter).get()); \
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Template definition to avoid some code duplication */
|
|
|
|
template <typename T>
|
|
|
|
void ResourceFolderModel::applyUpdates(QSet<QString>& current_set, QSet<QString>& new_set, QMap<QString, T>& new_resources)
|
|
|
|
{
|
|
|
|
// see if the kept resources changed in some way
|
|
|
|
{
|
|
|
|
QSet<QString> kept_set = current_set;
|
|
|
|
kept_set.intersect(new_set);
|
|
|
|
|
2022-08-12 21:09:56 +01:00
|
|
|
for (auto const& kept : kept_set) {
|
|
|
|
auto row_it = m_resources_index.constFind(kept);
|
|
|
|
Q_ASSERT(row_it != m_resources_index.constEnd());
|
|
|
|
auto row = row_it.value();
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
2022-08-12 21:09:56 +01:00
|
|
|
auto& new_resource = new_resources[kept];
|
2022-09-17 00:02:21 +01:00
|
|
|
auto const& current_resource = m_resources.at(row);
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
|
|
|
|
if (new_resource->dateTimeChanged() == current_resource->dateTimeChanged()) {
|
|
|
|
// no significant change, ignore...
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the resource is resolving, but something about it changed, we don't want to
|
|
|
|
// continue the resolving.
|
|
|
|
if (current_resource->isResolving()) {
|
2022-09-03 17:26:06 +01:00
|
|
|
auto ticket = current_resource->resolutionTicket();
|
|
|
|
if (m_active_parse_tasks.contains(ticket)) {
|
|
|
|
auto task = (*m_active_parse_tasks.find(ticket)).get();
|
|
|
|
task->abort();
|
|
|
|
}
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
}
|
|
|
|
|
2022-08-12 21:09:56 +01:00
|
|
|
m_resources[row].reset(new_resource);
|
2022-09-17 00:02:21 +01:00
|
|
|
resolveResource(m_resources.at(row).get());
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
emit dataChanged(index(row, 0), index(row, columnCount(QModelIndex()) - 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove resources no longer present
|
|
|
|
{
|
|
|
|
QSet<QString> removed_set = current_set;
|
|
|
|
removed_set.subtract(new_set);
|
|
|
|
|
|
|
|
QList<int> removed_rows;
|
|
|
|
for (auto& removed : removed_set)
|
|
|
|
removed_rows.append(m_resources_index[removed]);
|
|
|
|
|
2022-08-12 21:09:56 +01:00
|
|
|
std::sort(removed_rows.begin(), removed_rows.end(), std::greater<int>());
|
2022-08-10 18:48:34 +01:00
|
|
|
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
for (auto& removed_index : removed_rows) {
|
|
|
|
auto removed_it = m_resources.begin() + removed_index;
|
2022-08-12 21:09:56 +01:00
|
|
|
|
|
|
|
Q_ASSERT(removed_it != m_resources.end());
|
|
|
|
Q_ASSERT(removed_set.contains(removed_it->get()->internal_id()));
|
|
|
|
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
if ((*removed_it)->isResolving()) {
|
2022-09-03 17:26:06 +01:00
|
|
|
auto ticket = (*removed_it)->resolutionTicket();
|
|
|
|
if (m_active_parse_tasks.contains(ticket)) {
|
|
|
|
auto task = (*m_active_parse_tasks.find(ticket)).get();
|
|
|
|
task->abort();
|
|
|
|
}
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
}
|
|
|
|
|
2022-08-12 21:09:56 +01:00
|
|
|
beginRemoveRows(QModelIndex(), removed_index, removed_index);
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
m_resources.erase(removed_it);
|
|
|
|
endRemoveRows();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add new resources to the end
|
|
|
|
{
|
|
|
|
QSet<QString> added_set = new_set;
|
|
|
|
added_set.subtract(current_set);
|
|
|
|
|
|
|
|
// When you have a Qt build with assertions turned on, proceeding here will abort the application
|
|
|
|
if (added_set.size() > 0) {
|
|
|
|
beginInsertRows(QModelIndex(), m_resources.size(), m_resources.size() + added_set.size() - 1);
|
|
|
|
|
|
|
|
for (auto& added : added_set) {
|
|
|
|
auto res = new_resources[added];
|
|
|
|
m_resources.append(res);
|
2022-09-17 00:00:36 +01:00
|
|
|
resolveResource(m_resources.last().get());
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
endInsertRows();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// update index
|
|
|
|
{
|
|
|
|
m_resources_index.clear();
|
|
|
|
int idx = 0;
|
2022-09-17 00:02:21 +01:00
|
|
|
for (auto const& mod : qAsConst(m_resources)) {
|
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>
2022-08-09 05:58:22 +01:00
|
|
|
m_resources_index[mod->internal_id()] = idx;
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|