summaryrefslogtreecommitdiffstats
path: root/logic/resources/Resource.cpp
blob: 16ed3d2d8bfb95a4b33e7dd7948c231899301368 (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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "Resource.h"

#include <QDebug>

#include "WebResourceHandler.h"
#include "IconResourceHandler.h"
#include "ResourceObserver.h"

QMap<QString, std::function<std::shared_ptr<ResourceHandler>(const QString &)>> Resource::m_handlers;
QMap<QPair<int, int>, std::function<QVariant(QVariant)>> Resource::m_transfomers;
QMap<QString, std::weak_ptr<Resource>> Resource::m_resources;

Resource::Resource(const QString &resource)
{
	if (!m_handlers.contains("web"))
	{
		registerHandler<WebResourceHandler>("web");
	}
	if (!m_handlers.contains("icon"))
	{
		registerHandler<IconResourceHandler>("icon");
	}

	Q_ASSERT(resource.contains(':'));
	const QString resourceId = resource.left(resource.indexOf(':'));
	Q_ASSERT(m_handlers.contains(resourceId));
	m_handler = m_handlers.value(resourceId)(resource.mid(resource.indexOf(':') + 1));
	m_handler->init(m_handler);
	m_handler->setResource(this);
	Q_ASSERT(m_handler);
}
Resource::~Resource()
{
	qDeleteAll(m_observers);
}

Resource::Ptr Resource::create(const QString &resource)
{
	Resource::Ptr ptr = m_resources.contains(resource)
			? m_resources.value(resource).lock()
			: nullptr;
	if (!ptr)
	{
		struct ConstructableResource : public Resource
		{
			explicit ConstructableResource(const QString &resource)
				: Resource(resource) {}
		};
		ptr = std::make_shared<ConstructableResource>(resource);
		m_resources.insert(resource, ptr);
	}
	return ptr;
}

Resource::Ptr Resource::applyTo(ResourceObserver *observer)
{
	m_observers.append(observer);
	observer->setSource(shared_from_this()); // give the observer a shared_ptr for us so we don't get deleted
	observer->resourceUpdated();
	return shared_from_this();
}
Resource::Ptr Resource::applyTo(QObject *target, const char *property)
{
	// the cast to ResourceObserver* is required to ensure the right overload gets choosen
	return applyTo(static_cast<ResourceObserver *>(new QObjectResourceObserver(target, property)));
}

Resource::Ptr Resource::placeholder(Resource::Ptr other)
{
	m_placeholder = other;
	for (ResourceObserver *observer : m_observers)
	{
		observer->resourceUpdated();
	}
	return shared_from_this();
}

QVariant Resource::getResourceInternal(const int typeId) const
{
	if (m_handler->result().isNull() && m_placeholder)
	{
		return m_placeholder->getResourceInternal(typeId);
	}
	const QVariant variant = m_handler->result();
	const auto typePair = qMakePair(int(variant.type()), typeId);
	if (m_transfomers.contains(typePair))
	{
		return m_transfomers.value(typePair)(variant);
	}
	else
	{
		return variant;
	}
}

void Resource::reportResult()
{
	for (ResourceObserver *observer : m_observers)
	{
		observer->resourceUpdated();
	}
}
void Resource::reportFailure(const QString &reason)
{
	for (ResourceObserver *observer : m_observers)
	{
		observer->setFailure(reason);
	}
}
void Resource::reportProgress(const int progress)
{
	for (ResourceObserver *observer : m_observers)
	{
		observer->setProgress(progress);
	}
}

void Resource::notifyObserverDeleted(ResourceObserver *observer)
{
	m_observers.removeAll(observer);
}