summaryrefslogtreecommitdiffstats
path: root/logic/resources/ResourceProxyModel.cpp
blob: 6ff113670a80387621b9486a4ab7d9cca2362671 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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);
}