Plasma5Support

datasource.cpp
1/*
2 SPDX-FileCopyrightText: 2009 Alan Alpert <alan.alpert@nokia.com>
3 SPDX-FileCopyrightText: 2010 Ménard Alexis <menard@kde.org>
4 SPDX-FileCopyrightText: 2010 Marco Martin <mart@kde.org>
5 SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-or-later
8*/
9
10#include "datasource.h"
11#include <QAbstractItemModel>
12
13namespace Plasma5Support
14{
15DataSource::DataSource(QObject *parent)
16 : QObject(parent)
17 , m_ready(false)
18 , m_interval(0)
19 , m_intervalAlignment(Plasma5Support::Types::NoAlignment)
20{
21 m_models = new QQmlPropertyMap(this);
22 m_data = new QQmlPropertyMap(this);
23 setObjectName(QStringLiteral("DataSource"));
24}
25
26void DataSource::classBegin()
27{
28}
29
30void DataSource::componentComplete()
31{
32 m_ready = true;
33 setupData();
34}
35
36void DataSource::setConnectedSources(const QStringList &sources)
37{
38 bool sourcesChanged = false;
39 for (const QString &source : sources) {
40 if (!m_connectedSources.contains(source)) {
41 sourcesChanged = true;
42 if (m_dataEngine) {
43 m_connectedSources.append(source);
44 m_dataEngine->connectSource(source, this, m_interval, m_intervalAlignment);
45 Q_EMIT sourceConnected(source);
46 }
47 }
48 }
49
50 for (const QString &source : std::as_const(m_connectedSources)) {
51 if (!sources.contains(source)) {
52 m_data->clear(source);
53 sourcesChanged = true;
54 if (m_dataEngine) {
55 m_dataEngine->disconnectSource(source, this);
56 Q_EMIT sourceDisconnected(source);
57 }
58 }
59 }
60
61 if (sourcesChanged) {
62 m_connectedSources = sources;
63 Q_EMIT connectedSourcesChanged();
64 }
65}
66
67void DataSource::setEngine(const QString &e)
68{
69 if (e == m_engine) {
70 return;
71 }
72
73 m_engine = e;
74
75 if (m_engine.isEmpty()) {
76 Q_EMIT engineChanged();
77 return;
78 }
79
80 m_dataEngineConsumer.reset(new Plasma5Support::DataEngineConsumer());
81 Plasma5Support::DataEngine *engine = dataEngine(m_engine);
82 if (!engine) {
83 qWarning() << "DataEngine" << m_engine << "not found";
84 Q_EMIT engineChanged();
85 return;
86 }
87
88 if (m_dataEngine) {
89 m_dataEngine->disconnect(this);
90 // Deleting the consumer triggers the reference counting
91 m_dataEngineConsumer.reset();
92 }
93
94 /*
95 * It is due little explanation why this is a queued connection:
96 * If sourceAdded arrives immediately, in the case we have a datamodel
97 * with items at source level we connect too soon (before setData for
98 * all roles is done), having a dataupdated in the datamodel with only
99 * the first role, killing off the other roles.
100 * Besides causing a model reset more, unfortunately setRoleNames can be done a single time, so is not possible adding new roles after the
101 * first setRoleNames() is called.
102 * This fixes engines that have 1 item per source like the
103 * recommendations engine.
104 */
105 m_dataEngine = engine;
106 connect(m_dataEngine, &DataEngine::sourceAdded, this, &DataSource::updateSources, Qt::QueuedConnection);
107 connect(m_dataEngine, &DataEngine::sourceRemoved, this, &DataSource::updateSources);
108
109 connect(m_dataEngine, &DataEngine::sourceAdded, this, &DataSource::sourceAdded, Qt::QueuedConnection);
110 connect(m_dataEngine, &DataEngine::sourceRemoved, this, &DataSource::removeSource);
111 connect(m_dataEngine, &DataEngine::sourceRemoved, this, &DataSource::sourceRemoved);
112
113 updateSources();
114
115 Q_EMIT engineChanged();
116}
117
118void DataSource::setInterval(const int interval)
119{
120 if (interval == m_interval) {
121 return;
122 }
123
124 m_interval = interval;
125 setupData();
126 Q_EMIT intervalChanged();
127}
128
129void DataSource::setIntervalAlignment(Plasma5Support::Types::IntervalAlignment intervalAlignment)
130{
131 if (intervalAlignment == m_intervalAlignment) {
132 return;
133 }
134
135 m_intervalAlignment = intervalAlignment;
136 setupData();
137 Q_EMIT intervalAlignmentChanged();
138}
139
140void DataSource::setupData()
141{
142 if (!m_ready) {
143 return;
144 }
145
146 // qDebug() << " loading engine " << m_engine;
147 // FIXME: should all services be deleted just because we're changing the interval, etc?
148 qDeleteAll(m_services);
149 m_services.clear();
150
151 for (const QString &source : std::as_const(m_connectedSources)) {
152 m_dataEngine->connectSource(source, this, m_interval, m_intervalAlignment);
153 Q_EMIT sourceConnected(source);
154 }
155}
156
157void DataSource::dataUpdated(const QString &sourceName, const Plasma5Support::DataEngine::Data &data)
158{
159 // it can arrive also data we don't explicitly connected a source
160 if (m_connectedSources.contains(sourceName)) {
161 m_data->insert(sourceName, data);
162 Q_EMIT dataChanged();
163 Q_EMIT newData(sourceName, data);
164 } else if (m_dataEngine) {
165 m_dataEngine->disconnectSource(sourceName, this);
166 }
167}
168
169void DataSource::modelChanged(const QString &sourceName, QAbstractItemModel *model)
170{
171 if (!model) {
172 m_models->clear(sourceName);
173 return;
174 }
175
176 m_models->insert(sourceName, QVariant::fromValue(model));
177 // FIXME: this will break in the case a second model is set
178 connect(model, &QObject::destroyed, m_models, [this, sourceName]() {
179 m_models->clear(sourceName);
180 });
181}
182
183void DataSource::removeSource(const QString &source)
184{
185 m_data->clear(source);
186 m_models->clear(source);
187
188 // TODO: emit those signals as last thing
189 if (m_connectedSources.contains(source)) {
190 m_connectedSources.removeAll(source);
191 Q_EMIT sourceDisconnected(source);
192 Q_EMIT connectedSourcesChanged();
193 }
194
195 if (m_dataEngine) {
196 QHash<QString, Plasma5Support::Service *>::iterator it = m_services.find(source);
197 if (it != m_services.end()) {
198 delete it.value();
199 m_services.erase(it);
200 }
201 }
202}
203
204QObject *DataSource::serviceForSource(const QString &source)
205{
206 if (!m_services.contains(source)) {
207 Plasma5Support::Service *service = m_dataEngine->serviceForSource(source);
208 if (!service) {
209 return nullptr;
210 }
211 m_services[source] = service;
212 }
213
214 return m_services.value(source);
215}
216
217void DataSource::connectSource(const QString &source)
218{
219 if (m_connectedSources.contains(source)) {
220 return;
221 }
222
223 m_connectedSources.append(source);
224 if (m_dataEngine) {
225 m_dataEngine->connectSource(source, this, m_interval, m_intervalAlignment);
226 Q_EMIT sourceConnected(source);
227 Q_EMIT connectedSourcesChanged();
228 }
229}
230
231void DataSource::disconnectSource(const QString &source)
232{
233 if (m_dataEngine && m_connectedSources.contains(source)) {
234 m_connectedSources.removeAll(source);
235 m_dataEngine->disconnectSource(source, this);
236 Q_EMIT sourceDisconnected(source);
237 Q_EMIT connectedSourcesChanged();
238 }
239}
240
241void DataSource::updateSources()
242{
243 QStringList sources;
244 if (m_dataEngine) {
245 sources = m_dataEngine->sources();
246 }
247
248 if (sources != m_sources) {
249 m_sources = sources;
250 Q_EMIT sourcesChanged();
251 }
252}
253
254}
255
256#include "moc_datasource.cpp"
A class that makes it safe and easy to use DataEngines.
Data provider for plasmoids (Plasma plugins)
Definition dataengine.h:45
This class provides a generic API for write access to settings or services.
Definition service.h:78
IntervalAlignment
Possible timing alignments.
Namespace for everything in libplasma.
Definition datamodel.cpp:15
void destroyed(QObject *obj)
QueuedConnection
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QVariant fromValue(T &&value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 16:59:38 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.