summaryrefslogtreecommitdiffstats
path: root/logic/resources/ResourceProxyModel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'logic/resources/ResourceProxyModel.cpp')
-rw-r--r--logic/resources/ResourceProxyModel.cpp103
1 files changed, 103 insertions, 0 deletions
diff --git a/logic/resources/ResourceProxyModel.cpp b/logic/resources/ResourceProxyModel.cpp
new file mode 100644
index 00000000..6ff11367
--- /dev/null
+++ b/logic/resources/ResourceProxyModel.cpp
@@ -0,0 +1,103 @@
+#include "ResourceProxyModel.h"
+
+#include <QItemSelectionRange>
+
+#include "Resource.h"
+#include "ResourceObserver.h"
+
+//Q_DECLARE_METATYPE(QVector<int>)
+
+class ModelResourceObserver : public ResourceObserver
+{
+public:
+ explicit ModelResourceObserver(const QModelIndex &index, const int role)
+ : m_index(index), m_role(role)
+ {
+ qRegisterMetaType<QVector<int>>("QVector<int>");
+ }
+
+ void resourceUpdated() override
+ {
+ if (m_index.isValid())
+ {
+ QMetaObject::invokeMethod(const_cast<QAbstractItemModel *>(m_index.model()),
+ "dataChanged", Qt::QueuedConnection,
+ Q_ARG(QModelIndex, m_index), Q_ARG(QModelIndex, m_index), Q_ARG(QVector<int>, QVector<int>() << m_role));
+ }
+ }
+
+private:
+ QPersistentModelIndex m_index;
+ int m_role;
+};
+
+ResourceProxyModel::ResourceProxyModel(const int resultTypeId, QObject *parent)
+ : QIdentityProxyModel(parent), m_resultTypeId(resultTypeId)
+{
+}
+
+QVariant ResourceProxyModel::data(const QModelIndex &proxyIndex, int role) const
+{
+ const QModelIndex mapped = mapToSource(proxyIndex);
+ if (mapped.isValid() && role == Qt::DecorationRole && !mapToSource(proxyIndex).data(role).toString().isEmpty())
+ {
+ if (!m_resources.contains(mapped))
+ {
+ Resource::Ptr res = Resource::create(mapToSource(proxyIndex).data(role).toString())
+ ->applyTo(new ModelResourceObserver(proxyIndex, role));
+
+ const QVariant placeholder = mapped.data(PlaceholderRole);
+ if (!placeholder.isNull() && placeholder.type() == QVariant::String)
+ {
+ res->placeholder(Resource::create(placeholder.toString()));
+ }
+
+ m_resources.insert(mapped, res);
+ }
+
+ return m_resources.value(mapped)->getResourceInternal(m_resultTypeId);
+ }
+ return mapped.data(role);
+}
+
+void ResourceProxyModel::setSourceModel(QAbstractItemModel *model)
+{
+ if (sourceModel())
+ {
+ disconnect(sourceModel(), 0, this, 0);
+ }
+ if (model)
+ {
+ connect(model, &QAbstractItemModel::dataChanged, this, [this](const QModelIndex &tl, const QModelIndex &br, const QVector<int> &roles)
+ {
+ if (roles.contains(Qt::DecorationRole) || roles.isEmpty())
+ {
+ const QItemSelectionRange range(tl, br);
+ for (const QModelIndex &index : range.indexes())
+ {
+ m_resources.remove(index);
+ }
+ }
+ else if (roles.contains(PlaceholderRole))
+ {
+ const QItemSelectionRange range(tl, br);
+ for (const QModelIndex &index : range.indexes())
+ {
+ if (m_resources.contains(index))
+ {
+ const QVariant placeholder = index.data(PlaceholderRole);
+ if (!placeholder.isNull() && placeholder.type() == QVariant::String)
+ {
+ m_resources.value(index)->placeholder(Resource::create(placeholder.toString()));
+ }
+ else
+ {
+ m_resources.value(index)->placeholder(nullptr);
+ }
+ }
+ }
+ }
+ });
+ }
+ QIdentityProxyModel::setSourceModel(model);
+}