From 47e37635f50c09b4f9a9ee7699e3120bab3e4088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 10 Apr 2016 04:29:29 +0200 Subject: NOISSUE split GUI stuff from logic library --- libraries/logic/resources/ResourceProxyModel.cpp | 89 ++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 libraries/logic/resources/ResourceProxyModel.cpp (limited to 'libraries/logic/resources/ResourceProxyModel.cpp') diff --git a/libraries/logic/resources/ResourceProxyModel.cpp b/libraries/logic/resources/ResourceProxyModel.cpp new file mode 100644 index 00000000..f026d9a9 --- /dev/null +++ b/libraries/logic/resources/ResourceProxyModel.cpp @@ -0,0 +1,89 @@ +#include "ResourceProxyModel.h" + +#include + +#include "Resource.h" +#include "ResourceObserver.h" + +class ModelResourceObserver : public ResourceObserver +{ +public: + explicit ModelResourceObserver(const QModelIndex &index, const int role) + : m_index(index), m_role(role) + { + qRegisterMetaType>("QVector"); + } + + void resourceUpdated() override + { + if (m_index.isValid()) + { + // the resource changed, pretend to be the model and notify the views of the update. they will re-poll the model which will return the new resource value + QMetaObject::invokeMethod(const_cast(m_index.model()), + "dataChanged", Qt::QueuedConnection, + Q_ARG(QModelIndex, m_index), Q_ARG(QModelIndex, m_index), Q_ARG(QVector, QVector() << 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); + // valid cell that's a Qt::DecorationRole and that contains a non-empty string + if (mapped.isValid() && role == Qt::DecorationRole && !mapToSource(proxyIndex).data(role).toString().isEmpty()) + { + // do we already have a resource for this index? + if (!m_resources.contains(mapped)) + { + Resource::Ptr placeholder; + const QVariant placeholderIdentifier = mapped.data(PlaceholderRole); + if (!placeholderIdentifier.isNull() && placeholderIdentifier.type() == QVariant::String) + { + placeholder = Resource::create(placeholderIdentifier.toString()); + } + + // create the Resource and apply the observer for models + Resource::Ptr res = Resource::create(mapToSource(proxyIndex).data(role).toString(), placeholder) + ->applyTo(new ModelResourceObserver(proxyIndex, role)); + + m_resources.insert(mapped, res); + } + + return m_resources.value(mapped)->getResourceInternal(m_resultTypeId); + } + // otherwise fall back to the source model + 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 &roles) + { + // invalidate resources so that they will be re-created + if (roles.contains(Qt::DecorationRole) || roles.contains(PlaceholderRole) || roles.isEmpty()) + { + const QItemSelectionRange range(tl, br); + for (const QModelIndex &index : range.indexes()) + { + m_resources.remove(index); + } + } + }); + } + QIdentityProxyModel::setSourceModel(model); +} -- cgit v1.2.3