KIdleTime

kidletime.cpp
1 /* This file is part of the KDE libraries
2  * SPDX-FileCopyrightText: 2009 Dario Freddi <drf at kde.org>
3  *
4  * SPDX-License-Identifier: LGPL-2.0-only
5  */
6 
7 #include "kidletime.h"
8 
9 #include <config-kidletime.h>
10 
11 #include "abstractsystempoller.h"
12 #include "logging.h"
13 
14 #include <QDir>
15 #include <QJsonArray>
16 #include <QGuiApplication>
17 #include <QPluginLoader>
18 #include <QPointer>
19 #include <QSet>
20 
21 class KIdleTimeHelper
22 {
23 public:
24  KIdleTimeHelper() : q(nullptr) {}
25  ~KIdleTimeHelper()
26  {
27  delete q;
28  }
29  KIdleTimeHelper(const KIdleTimeHelper &) = delete;
30  KIdleTimeHelper &operator=(const KIdleTimeHelper &) = delete;
31  KIdleTime *q;
32 };
33 
34 Q_GLOBAL_STATIC(KIdleTimeHelper, s_globalKIdleTime)
35 
36 KIdleTime *KIdleTime::instance()
37 {
38  if (!s_globalKIdleTime()->q) {
39  new KIdleTime;
40  }
41 
42  return s_globalKIdleTime()->q;
43 }
44 
45 class KIdleTimePrivate
46 {
47  Q_DECLARE_PUBLIC(KIdleTime)
48  KIdleTime *q_ptr;
49 public:
50  KIdleTimePrivate() : catchResume(false), currentId(0) {}
51 
52  void loadSystem();
53  void unloadCurrentSystem();
54  void _k_resumingFromIdle();
55  void _k_timeoutReached(int msec);
56 
58  bool catchResume;
59 
60  int currentId;
61  QHash<int, int> associations;
62 };
63 
64 KIdleTime::KIdleTime()
65  : QObject(nullptr)
66  , d_ptr(new KIdleTimePrivate())
67 {
68  Q_ASSERT(!s_globalKIdleTime()->q);
69  s_globalKIdleTime()->q = this;
70 
71  d_ptr->q_ptr = this;
72 
73  Q_D(KIdleTime);
74  d->loadSystem();
75 
76  connect(d->poller.data(), SIGNAL(resumingFromIdle()), this, SLOT(_k_resumingFromIdle()));
77  connect(d->poller.data(), SIGNAL(timeoutReached(int)), this, SLOT(_k_timeoutReached(int)));
78 }
79 
81 {
82  Q_D(KIdleTime);
83  d->unloadCurrentSystem();
84  delete d_ptr;
85 }
86 
88 {
89  Q_D(KIdleTime);
90 
91  if (!d->catchResume && d->poller) {
92  d->catchResume = true;
93  d->poller.data()->catchIdleEvent();
94  }
95 }
96 
98 {
99  Q_D(KIdleTime);
100 
101  if (d->catchResume && d->poller) {
102  d->catchResume = false;
103  d->poller.data()->stopCatchingIdleEvents();
104  }
105 }
106 
108 {
109  Q_D(KIdleTime);
110  if (Q_UNLIKELY(!d->poller)) {
111  return 0;
112  }
113 
114  d->poller.data()->addTimeout(msec);
115 
116  ++d->currentId;
117  d->associations[d->currentId] = msec;
118 
119  return d->currentId;
120 }
121 
122 void KIdleTime::removeIdleTimeout(int identifier)
123 {
124  Q_D(KIdleTime);
125 
126  if (!d->associations.contains(identifier) || !d->poller) {
127  return;
128  }
129 
130  int msec = d->associations[identifier];
131 
132  d->associations.remove(identifier);
133 
134  if (!d->associations.values().contains(msec)) {
135  d->poller.data()->removeTimeout(msec);
136  }
137 }
138 
140 {
141  Q_D(KIdleTime);
142 
143  QHash< int, int >::iterator i = d->associations.begin();
144  QSet< int > removed;
145  removed.reserve(d->associations.size());
146 
147  while (i != d->associations.end()) {
148  int msec = d->associations[i.key()];
149 
150  i = d->associations.erase(i);
151 
152  if (!removed.contains(msec) && d->poller) {
153  d->poller.data()->removeTimeout(msec);
154  removed.insert(msec);
155  }
156  }
157 }
158 
159 static QStringList pluginCandidates()
160 {
161  QStringList ret;
163  for (const QString &path : libPath ) {
164  const QDir pluginDir(path + QLatin1String("/kf5/org.kde.kidletime.platforms"));
165  if (!pluginDir.exists()) {
166  continue;
167  }
168  for (const QString &entry : pluginDir.entryList(QDir::Files | QDir::NoDotAndDotDot)) {
169  ret << pluginDir.absoluteFilePath(entry);
170  }
171  }
172  return ret;
173 }
174 
175 static AbstractSystemPoller *loadPoller()
176 {
177  const QStringList lstPlugins = pluginCandidates();
178  for (const QString &candidate : lstPlugins) {
179  if (!QLibrary::isLibrary(candidate)) {
180  continue;
181  }
182  QPluginLoader loader(candidate);
183  QJsonObject metaData = loader.metaData();
184  const QJsonArray platforms = metaData.value(QStringLiteral("MetaData")).toObject().value(QStringLiteral("platforms")).toArray();
185  for (auto it = platforms.begin(); it != platforms.end(); ++it) {
186  if (QString::compare(QGuiApplication::platformName(), (*it).toString(), Qt::CaseInsensitive) == 0) {
187  AbstractSystemPoller *poller = qobject_cast< AbstractSystemPoller* >(loader.instance());
188  if (poller) {
189  qCDebug(KIDLETIME) << "Trying plugin" << candidate;
190  if (poller->isAvailable()) {
191  qCDebug(KIDLETIME) << "Using" << candidate << "for platform" << QGuiApplication::platformName();
192  return poller;
193  }
194  delete poller;
195  }
196  }
197  }
198  }
199  return nullptr;
200 }
201 
202 void KIdleTimePrivate::loadSystem()
203 {
204  if (!poller.isNull()) {
205  unloadCurrentSystem();
206  }
207 
208  // load plugin
209  poller = loadPoller();
210 
211  if (poller && !poller->isAvailable()) {
212  poller = nullptr;
213  }
214  if (!poller.isNull()) {
215  poller.data()->setUpPoller();
216  }
217 }
218 
219 void KIdleTimePrivate::unloadCurrentSystem()
220 {
221  if (!poller.isNull()) {
222  poller.data()->unloadPoller();
223  poller.data()->deleteLater();
224  }
225 }
226 
227 void KIdleTimePrivate::_k_resumingFromIdle()
228 {
229  Q_Q(KIdleTime);
230 
231  if (catchResume) {
232  emit q->resumingFromIdle();
233  q->stopCatchingResumeEvent();
234  }
235 }
236 
237 void KIdleTimePrivate::_k_timeoutReached(int msec)
238 {
239  Q_Q(KIdleTime);
240 
241  if (associations.values().contains(msec)) {
242  const auto listKeys = associations.keys(msec);
243  for (int key : listKeys) {
244  emit q->timeoutReached(key);
245  emit q->timeoutReached(key, msec);
246  }
247  }
248 }
249 
251 {
252  Q_D(KIdleTime);
253 
254  if (Q_LIKELY(d->poller)) {
255  d->poller.data()->simulateUserActivity();
256  }
257 }
258 
260 {
261  Q_D(const KIdleTime);
262  if (Q_LIKELY(d->poller)) {
263  return d->poller.data()->forcePollRequest();
264  }
265  return 0;
266 }
267 
269 {
270  Q_D(const KIdleTime);
271 
272  return d->associations;
273 }
274 
275 #include "moc_kidletime.cpp"
KIdleTime is a singleton reporting information on idle time.
Definition: kidletime.h:29
void removeAllIdleTimeouts()
Stops catching every set timeout (if any).
Definition: kidletime.cpp:139
QJsonArray::iterator begin()
const Key key(const T &value) const const
void stopCatchingResumeEvent()
Stops listening for resume event.
Definition: kidletime.cpp:97
virtual ~KIdleTime()
The destructor.
Definition: kidletime.cpp:80
QHash::iterator erase(QHash::iterator pos)
QSet::iterator insert(const T &value)
QJsonObject metaData() const const
bool exists() const const
void simulateUserActivity()
Attempts to simulate user activity.
Definition: kidletime.cpp:250
void catchNextResumeEvent()
Catches the next resume from idle event.
Definition: kidletime.cpp:87
QJsonObject toObject() const const
CaseInsensitive
QJsonArray toArray() const const
QHash::iterator begin()
QObject * instance()
QHash< int, int > idleTimeouts() const
Returns the list of timeout identifiers associated with their duration, in milliseconds, the library is currently listening to.
Definition: kidletime.cpp:268
QJsonArray::iterator end()
void removeIdleTimeout(int identifier)
Stops catching the idle timeout identified by the token identifier, if it was registered earlier with...
Definition: kidletime.cpp:122
QStringList libraryPaths()
bool contains(const T &value) const const
int idleTime() const
Retrieves the idle time of the system, in milliseconds.
Definition: kidletime.cpp:259
QStringList entryList(QDir::Filters filters, QDir::SortFlags sort) const const
QString absoluteFilePath(const QString &fileName) const const
void reserve(int size)
QJsonValue value(const QString &key) const const
QHash::iterator end()
int compare(const QString &other, Qt::CaseSensitivity cs) const const
int addIdleTimeout(int msec)
Adds a new timeout to catch.
Definition: kidletime.cpp:107
QString platformName()
bool isLibrary(const QString &fileName)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Jul 8 2020 22:48:13 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.