1 /*
2 SPDX-FileCopyrightText: 2006-2007 Aaron Seigo <aseigo@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7 #include "datacontainer_p.h" //krazy:exclude=includes
8
9 namespace Plasma
10 {
signalRelay(const DataContainer * dc,QObject * visualization,uint pollingInterval,Plasma::Types::IntervalAlignment align,bool immediateUpdate)11 SignalRelay *DataContainerPrivate::signalRelay(const DataContainer *dc,
12 QObject *visualization,
13 uint pollingInterval,
14 Plasma::Types::IntervalAlignment align,
15 bool immediateUpdate)
16 {
17 QMap<uint, SignalRelay *>::const_iterator relayIt = relays.constFind(pollingInterval);
18 SignalRelay *relay = nullptr;
19
20 // FIXME what if we have two applets with the same interval and different alignment?
21 if (relayIt == relays.constEnd()) {
22 relay = new SignalRelay(const_cast<DataContainer *>(dc), this, pollingInterval, align, immediateUpdate);
23 relays[pollingInterval] = relay;
24 } else {
25 relay = relayIt.value();
26 }
27
28 relayObjects[visualization] = relay;
29 return relay;
30 }
31
hasUpdates()32 bool DataContainerPrivate::hasUpdates()
33 {
34 if (cached) {
35 // SignalRelay needs us to pretend we did an update
36 cached = false;
37 return true;
38 }
39
40 return dirty;
41 }
42
SignalRelay(DataContainer * parent,DataContainerPrivate * data,uint ival,Plasma::Types::IntervalAlignment align,bool immediateUpdate)43 SignalRelay::SignalRelay(DataContainer *parent, DataContainerPrivate *data, uint ival, Plasma::Types::IntervalAlignment align, bool immediateUpdate)
44 : QObject(parent)
45 , dc(parent)
46 , d(data)
47 , m_interval(ival)
48 , m_align(align)
49 , m_resetTimer(true)
50 , m_queued(true)
51 {
52 // qCDebug(LOG_PLASMA) << "signal relay with time of" << m_timerId << "being set up";
53 m_timerId = startTimer(immediateUpdate ? 0 : m_interval);
54 if (m_align != Plasma::Types::NoAlignment) {
55 checkAlignment();
56 }
57 }
58
receiverCount() const59 int SignalRelay::receiverCount() const
60 {
61 return receivers(SIGNAL(dataUpdated(QString, Plasma::DataEngine::Data)));
62 }
63
isUnused() const64 bool SignalRelay::isUnused() const
65 {
66 return receivers(SIGNAL(dataUpdated(QString, Plasma::DataEngine::Data))) < 1;
67 }
68
checkAlignment()69 void SignalRelay::checkAlignment()
70 {
71 int newTime = 0;
72
73 QTime t = QTime::currentTime();
74 if (m_align == Plasma::Types::AlignToMinute) {
75 int seconds = t.second();
76 newTime = ((60 - seconds) * 1000) + 500;
77 } else if (m_align == Plasma::Types::AlignToHour) {
78 int minutes = t.minute();
79 int seconds = t.second();
80 if (minutes > 1 || seconds > 10) {
81 newTime = ((60 - minutes) * 1000 * 60) + ((60 - seconds) * 1000) + 500;
82 }
83 }
84
85 if (newTime) {
86 killTimer(m_timerId);
87 m_timerId = startTimer(newTime);
88 m_resetTimer = true;
89 }
90 }
91
checkQueueing()92 void SignalRelay::checkQueueing()
93 {
94 // qCDebug(LOG_PLASMA) << m_queued;
95 if (m_queued) {
96 Q_EMIT dataUpdated(dc->objectName(), d->data);
97 m_queued = false;
98 // TODO: should we re-align our timer at this point, to avoid
99 // constant queueing due to more-or-less constant time
100 // async update time? this might make sense for
101 // staggered accesses to the same source by multiple
102 // visualizations causing a minimumPollingInterval violation.
103 // it may not make sense for purely async-and-takes-a-while
104 // type operations (e.g. network fetching).
105 // we need more real world data before making such a change
106 // change
107 //
108 // killTimer(m_timerId);
109 // m_timerId = startTime(m_interval);
110 }
111 }
112
forceImmediateUpdate()113 void SignalRelay::forceImmediateUpdate()
114 {
115 Q_EMIT dataUpdated(dc->objectName(), d->data);
116 }
117
timerEvent(QTimerEvent * event)118 void SignalRelay::timerEvent(QTimerEvent *event)
119 {
120 if (event->timerId() != m_timerId) {
121 QObject::timerEvent(event);
122 return;
123 }
124
125 if (m_resetTimer) {
126 killTimer(m_timerId);
127 m_timerId = startTimer(m_interval);
128 m_resetTimer = false;
129 }
130
131 if (m_align != Plasma::Types::NoAlignment) {
132 checkAlignment();
133 }
134
135 Q_EMIT dc->updateRequested(dc);
136 if (d->hasUpdates()) {
137 // qCDebug(LOG_PLASMA) << "emitting data updated directly" << d->data;
138 Q_EMIT dataUpdated(dc->objectName(), d->data);
139 m_queued = false;
140 } else {
141 // the source wasn't actually updated; so let's put ourselves in the queue
142 // so we get a dataUpdated() call when the data does arrive
143 // qCDebug(LOG_PLASMA) << "queued";
144 m_queued = true;
145 }
146 }
147
148 } // Plasma namespace
149
150 #include "moc_datacontainer_p.cpp"
151