Plasma

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

KDE's Doxygen guidelines are available online.