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