Changeset View
Changeset View
Standalone View
Standalone View
libnotificationmanager/settings.cpp
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | * Copyright 2019 Kai Uwe Broulik <kde@privat.broulik.de> | ||||
3 | * | ||||
4 | * This library is free software; you can redistribute it and/or | ||||
5 | * modify it under the terms of the GNU Lesser General Public | ||||
6 | * License as published by the Free Software Foundation; either | ||||
7 | * version 2.1 of the License, or (at your option) version 3, or any | ||||
8 | * later version accepted by the membership of KDE e.V. (or its | ||||
9 | * successor approved by the membership of KDE e.V.), which shall | ||||
10 | * act as a proxy defined in Section 6 of version 3 of the license. | ||||
11 | * | ||||
12 | * This library is distributed in the hope that it will be useful, | ||||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
15 | * Lesser General Public License for more details. | ||||
16 | * | ||||
17 | * You should have received a copy of the GNU Lesser General Public | ||||
18 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||||
19 | */ | ||||
20 | | ||||
21 | #include "settings.h" | ||||
22 | | ||||
23 | #include <QDebug> | ||||
24 | | ||||
25 | #include <KConfigWatcher> | ||||
26 | #include <KService> | ||||
27 | | ||||
28 | #include "server.h" | ||||
29 | #include "debug.h" | ||||
30 | | ||||
31 | // Settings | ||||
32 | #include "donotdisturbsettings.h" | ||||
33 | #include "notificationsettings.h" | ||||
34 | #include "jobsettings.h" | ||||
35 | #include "badgesettings.h" | ||||
36 | | ||||
37 | using namespace NotificationManager; | ||||
38 | | ||||
39 | class Q_DECL_HIDDEN Settings::Private | ||||
40 | { | ||||
41 | public: | ||||
42 | explicit Private(Settings *q); | ||||
43 | ~Private(); | ||||
44 | | ||||
45 | void setDirty(bool dirty); | ||||
46 | | ||||
47 | Settings::NotificationBehaviors groupBehavior(const KConfigGroup &group) const; | ||||
48 | void setGroupBehavior(KConfigGroup &group, const Settings::NotificationBehaviors &behavior); | ||||
49 | | ||||
50 | KConfigGroup servicesGroup() const; | ||||
51 | KConfigGroup applicationsGroup() const; | ||||
52 | | ||||
53 | QStringList behaviorMatchesList(const KConfigGroup &group, Settings::NotificationBehavior behavior, bool on) const; | ||||
54 | | ||||
55 | Settings *q; | ||||
56 | | ||||
57 | KSharedConfig::Ptr config; | ||||
58 | | ||||
59 | KConfigWatcher::Ptr watcher; | ||||
60 | QMetaObject::Connection watcherConnection; | ||||
61 | | ||||
62 | bool live = false; // set to true initially in constructor | ||||
63 | bool dirty = false; | ||||
64 | | ||||
65 | }; | ||||
66 | | ||||
67 | Settings::Private::Private(Settings *q) | ||||
68 | : q(q) | ||||
69 | { | ||||
70 | | ||||
71 | } | ||||
72 | | ||||
73 | Settings::Private::~Private() = default; | ||||
74 | | ||||
75 | void Settings::Private::setDirty(bool dirty) | ||||
76 | { | ||||
77 | if (this->dirty != dirty) { | ||||
78 | this->dirty = dirty; | ||||
79 | emit q->dirtyChanged(); | ||||
80 | } | ||||
81 | } | ||||
82 | | ||||
83 | Settings::NotificationBehaviors Settings::Private::groupBehavior(const KConfigGroup &group) const | ||||
84 | { | ||||
85 | Settings::NotificationBehaviors behaviors; | ||||
86 | behaviors.setFlag(Settings::ShowPopups, group.readEntry("ShowPopups", true)); | ||||
87 | // show popups in dnd mode implies the show popups | ||||
88 | behaviors.setFlag(Settings::ShowPopupsInDoNotDisturbMode, behaviors.testFlag(Settings::ShowPopups) && group.readEntry("ShowPopupsInDndMode", false)); | ||||
89 | behaviors.setFlag(Settings::ShowInHistory, group.readEntry("ShowInHistory", true)); | ||||
90 | behaviors.setFlag(Settings::ShowBadges, group.readEntry("ShowBadges", true)); | ||||
91 | return behaviors; | ||||
92 | } | ||||
93 | | ||||
94 | void Settings::Private::setGroupBehavior(KConfigGroup &group, const Settings::NotificationBehaviors &behavior) | ||||
95 | { | ||||
96 | if (groupBehavior(group) == behavior) { | ||||
97 | return; | ||||
98 | } | ||||
99 | | ||||
100 | const bool showPopups = behavior.testFlag(Settings::ShowPopups); | ||||
101 | if (showPopups && !group.hasDefault("ShowPopups")) { | ||||
102 | group.revertToDefault("ShowPopups", KConfigBase::Notify); | ||||
103 | } else { | ||||
104 | group.writeEntry("ShowPopups", showPopups, KConfigBase::Notify); | ||||
105 | } | ||||
106 | | ||||
107 | const bool showPopupsInDndMode = behavior.testFlag(Settings::ShowPopupsInDoNotDisturbMode); | ||||
108 | if (!showPopupsInDndMode && !group.hasDefault("ShowPopups")) { | ||||
109 | group.revertToDefault("ShowPopupsInDndMode", KConfigBase::Notify); | ||||
110 | } else { | ||||
111 | group.writeEntry("ShowPopupsInDndMode", showPopupsInDndMode, KConfigBase::Notify); | ||||
112 | } | ||||
113 | | ||||
114 | const bool showInHistory = behavior.testFlag(Settings::ShowInHistory); | ||||
115 | if (showInHistory && !group.hasDefault("ShowInHistory")) { | ||||
116 | group.revertToDefault("ShowInHistory", KConfig::Notify); | ||||
117 | } else { | ||||
118 | group.writeEntry("ShowInHistory", showInHistory, KConfigBase::Notify); | ||||
119 | } | ||||
120 | | ||||
121 | const bool showBadges = behavior.testFlag(Settings::ShowBadges); | ||||
122 | if (showBadges && !group.hasDefault("ShowBadges")) { | ||||
123 | group.revertToDefault("ShowBadges", KConfigBase::Notify); | ||||
124 | } else { | ||||
125 | group.writeEntry("ShowBadges", showBadges, KConfigBase::Notify); | ||||
126 | } | ||||
127 | | ||||
128 | setDirty(true); | ||||
129 | } | ||||
130 | | ||||
131 | KConfigGroup Settings::Private::servicesGroup() const | ||||
132 | { | ||||
133 | return config->group("Services"); | ||||
134 | } | ||||
135 | | ||||
136 | KConfigGroup Settings::Private::applicationsGroup() const | ||||
137 | { | ||||
138 | return config->group("Applications"); | ||||
139 | } | ||||
140 | | ||||
141 | QStringList Settings::Private::behaviorMatchesList(const KConfigGroup &group, Settings::NotificationBehavior behavior, bool on) const | ||||
142 | { | ||||
143 | QStringList matches; | ||||
144 | | ||||
145 | const QStringList apps = group.groupList(); | ||||
146 | for (const QString &app : apps) { | ||||
147 | if (groupBehavior(group.group(app)).testFlag(behavior) == on) { | ||||
148 | matches.append(app); | ||||
149 | } | ||||
150 | } | ||||
151 | | ||||
152 | return matches; | ||||
153 | } | ||||
154 | | ||||
155 | Settings::Settings(QObject *parent) | ||||
156 | // FIXME static thing for config file name | ||||
157 | : Settings(KSharedConfig::openConfig(QStringLiteral("plasmanotifyrc")), parent) | ||||
158 | { | ||||
159 | | ||||
160 | } | ||||
161 | | ||||
162 | Settings::Settings(const KSharedConfig::Ptr &config, QObject *parent) | ||||
163 | : QObject(parent) | ||||
164 | , d(new Private(this)) | ||||
165 | { | ||||
166 | d->config = config; | ||||
167 | | ||||
168 | static bool s_settingsInited = false; | ||||
169 | if (!s_settingsInited) { | ||||
170 | DoNotDisturbSettings::instance(config); | ||||
171 | NotificationSettings::instance(config); | ||||
172 | JobSettings::instance(config); | ||||
173 | BadgeSettings::instance(config); | ||||
174 | s_settingsInited = true; | ||||
175 | } | ||||
176 | | ||||
177 | setLive(true); | ||||
178 | | ||||
179 | connect(&Server::self(), &Server::inhibitedChanged, | ||||
180 | this, &Settings::notificationsInhibitedByApplicationChanged); | ||||
181 | connect(&Server::self(), &Server::inhibitionApplicationsChanged, | ||||
182 | this, &Settings::notificationInhibitionApplicationsChanged); | ||||
183 | } | ||||
184 | | ||||
185 | Settings::~Settings() = default; | ||||
186 | | ||||
187 | Settings::NotificationBehaviors Settings::applicationBehavior(const QString &desktopEntry) const | ||||
188 | { | ||||
189 | return d->groupBehavior(d->applicationsGroup().group(desktopEntry)); | ||||
190 | } | ||||
191 | | ||||
192 | void Settings::setApplicationBehavior(const QString &desktopEntry, NotificationBehaviors behaviors) | ||||
193 | { | ||||
194 | KConfigGroup group(d->applicationsGroup().group(desktopEntry)); | ||||
195 | d->setGroupBehavior(group, behaviors); | ||||
196 | } | ||||
197 | | ||||
198 | Settings::NotificationBehaviors Settings::serviceBehavior(const QString ¬ifyRcName) const | ||||
199 | { | ||||
200 | return d->groupBehavior(d->servicesGroup().group(notifyRcName)); | ||||
201 | } | ||||
202 | | ||||
203 | void Settings::setServiceBehavior(const QString ¬ifyRcName, NotificationBehaviors behaviors) | ||||
204 | { | ||||
205 | KConfigGroup group(d->servicesGroup().group(notifyRcName)); | ||||
206 | d->setGroupBehavior(group, behaviors); | ||||
207 | } | ||||
208 | | ||||
209 | void Settings::registerKnownApplication(const QString &desktopEntry) | ||||
210 | { | ||||
211 | KService::Ptr service = KService::serviceByDesktopName(desktopEntry); | ||||
212 | if (!service) { | ||||
213 | qCDebug(NOTIFICATIONMANAGER) << "Application" << desktopEntry << "cannot be registered as seen application since there is no service for it"; | ||||
214 | return; | ||||
215 | } | ||||
216 | | ||||
217 | if (service->noDisplay()) { | ||||
218 | qCDebug(NOTIFICATIONMANAGER) << "Application" << desktopEntry << "will not be registered as seen application since it's marked as NoDisplay"; | ||||
219 | return; | ||||
220 | } | ||||
221 | | ||||
222 | if (knownApplications().contains(desktopEntry)) { | ||||
223 | return; | ||||
224 | } | ||||
225 | | ||||
226 | d->applicationsGroup().group(desktopEntry).writeEntry("Seen", true); | ||||
227 | | ||||
228 | emit knownApplicationsChanged(); | ||||
229 | } | ||||
230 | | ||||
231 | void Settings::forgetKnownApplication(const QString &desktopEntry) | ||||
232 | { | ||||
233 | if (!knownApplications().contains(desktopEntry)) { | ||||
234 | return; | ||||
235 | } | ||||
236 | | ||||
237 | // Only remove applications that were added through registerKnownApplication | ||||
238 | if (!d->applicationsGroup().group(desktopEntry).readEntry("Seen", false)) { | ||||
239 | qCDebug(NOTIFICATIONMANAGER) << "Application" << desktopEntry << "will not be removed from seen applications since it wasn't one."; | ||||
240 | return; | ||||
241 | } | ||||
242 | | ||||
243 | d->applicationsGroup().deleteGroup(desktopEntry); | ||||
244 | | ||||
245 | emit knownApplicationsChanged(); | ||||
246 | } | ||||
247 | | ||||
248 | void Settings::load() | ||||
249 | { | ||||
250 | DoNotDisturbSettings::self()->load(); | ||||
251 | NotificationSettings::self()->load(); | ||||
252 | JobSettings::self()->load(); | ||||
253 | BadgeSettings::self()->load(); | ||||
254 | emit settingsChanged(); | ||||
255 | d->setDirty(false); | ||||
256 | } | ||||
257 | | ||||
258 | void Settings::save() | ||||
259 | { | ||||
260 | DoNotDisturbSettings::self()->save(); | ||||
261 | NotificationSettings::self()->save(); | ||||
262 | JobSettings::self()->save(); | ||||
263 | BadgeSettings::self()->save(); | ||||
264 | | ||||
265 | d->config->sync(); | ||||
266 | d->setDirty(false); | ||||
267 | } | ||||
268 | | ||||
269 | void Settings::defaults() | ||||
270 | { | ||||
271 | DoNotDisturbSettings::self()->setDefaults(); | ||||
272 | NotificationSettings::self()->setDefaults(); | ||||
273 | JobSettings::self()->setDefaults(); | ||||
274 | BadgeSettings::self()->setDefaults(); | ||||
275 | } | ||||
276 | | ||||
277 | bool Settings::live() const | ||||
278 | { | ||||
279 | return d->live; | ||||
280 | } | ||||
281 | | ||||
282 | void Settings::setLive(bool live) | ||||
283 | { | ||||
284 | if (live == d->live) { | ||||
285 | return; | ||||
286 | } | ||||
287 | | ||||
288 | d->live = live; | ||||
289 | | ||||
290 | if (live) { | ||||
291 | d->watcher = KConfigWatcher::create(d->config); | ||||
292 | d->watcherConnection = connect(d->watcher.data(), &KConfigWatcher::configChanged, this, | ||||
293 | [this](const KConfigGroup &group, const QByteArrayList &names) { | ||||
294 | Q_UNUSED(names); | ||||
295 | | ||||
296 | if (group.name() == QLatin1String("DoNotDisturb")) { | ||||
297 | DoNotDisturbSettings::self()->load(); | ||||
298 | } else if (group.name() == QLatin1String("Notifications")) { | ||||
299 | NotificationSettings::self()->load(); | ||||
300 | } else if (group.name() == QLatin1String("Jobs")) { | ||||
301 | JobSettings::self()->load(); | ||||
302 | } else if (group.name() == QLatin1String("Badges")) { | ||||
303 | BadgeSettings::self()->load(); | ||||
304 | } | ||||
305 | | ||||
306 | emit settingsChanged(); | ||||
307 | }); | ||||
308 | } else { | ||||
309 | disconnect(d->watcherConnection); | ||||
310 | d->watcherConnection = QMetaObject::Connection(); | ||||
311 | d->watcher.reset(); | ||||
312 | } | ||||
313 | | ||||
314 | emit liveChanged(); | ||||
315 | } | ||||
316 | | ||||
317 | bool Settings::dirty() const | ||||
318 | { | ||||
319 | // KConfigSkeleton doesn't write into the KConfig until calling save() | ||||
320 | // so we need to track d->config->isDirty() manually | ||||
321 | return d->dirty; | ||||
322 | } | ||||
323 | | ||||
324 | bool Settings::keepCriticalAlwaysOnTop() const | ||||
325 | { | ||||
326 | return NotificationSettings::criticalAlwaysOnTop(); | ||||
327 | } | ||||
328 | | ||||
329 | void Settings::setKeepCriticalAlwaysOnTop(bool enable) | ||||
330 | { | ||||
331 | if (this->keepCriticalAlwaysOnTop() == enable) { | ||||
332 | return; | ||||
333 | } | ||||
334 | NotificationSettings::setCriticalAlwaysOnTop(enable); | ||||
335 | d->setDirty(true); | ||||
336 | } | ||||
337 | | ||||
338 | bool Settings::criticalPopupsInDoNotDisturbMode() const | ||||
339 | { | ||||
340 | return NotificationSettings::criticalInDndMode(); | ||||
341 | } | ||||
342 | | ||||
343 | void Settings::setCriticalPopupsInDoNotDisturbMode(bool enable) | ||||
344 | { | ||||
345 | if (this->criticalPopupsInDoNotDisturbMode() == enable) { | ||||
346 | return; | ||||
347 | } | ||||
348 | NotificationSettings::setCriticalInDndMode(enable); | ||||
349 | d->setDirty(true); | ||||
350 | } | ||||
351 | | ||||
352 | bool Settings::lowPriorityPopups() const | ||||
353 | { | ||||
354 | return NotificationSettings::lowPriorityPopups(); | ||||
355 | } | ||||
356 | | ||||
357 | void Settings::setLowPriorityPopups(bool enable) | ||||
358 | { | ||||
359 | if (this->lowPriorityPopups() == enable) { | ||||
360 | return; | ||||
361 | } | ||||
362 | NotificationSettings::setLowPriorityPopups(enable); | ||||
363 | d->setDirty(true); | ||||
364 | } | ||||
365 | | ||||
366 | bool Settings::lowPriorityHistory() const | ||||
367 | { | ||||
368 | return NotificationSettings::lowPriorityHistory(); | ||||
369 | } | ||||
370 | | ||||
371 | void Settings::setLowPriorityHistory(bool enable) | ||||
372 | { | ||||
373 | if (this->lowPriorityHistory() == enable) { | ||||
374 | return; | ||||
375 | } | ||||
376 | NotificationSettings::setLowPriorityHistory(enable); | ||||
377 | d->setDirty(true); | ||||
378 | } | ||||
379 | | ||||
380 | Settings::PopupPosition Settings::popupPosition() const | ||||
381 | { | ||||
382 | return NotificationSettings::popupPosition(); | ||||
383 | } | ||||
384 | | ||||
385 | void Settings::setPopupPosition(Settings::PopupPosition position) | ||||
386 | { | ||||
387 | if (this->popupPosition() == position) { | ||||
388 | return; | ||||
389 | } | ||||
390 | NotificationSettings::setPopupPosition(position); | ||||
391 | d->setDirty(true); | ||||
392 | } | ||||
393 | | ||||
394 | int Settings::popupTimeout() const | ||||
395 | { | ||||
396 | return NotificationSettings::popupTimeout(); | ||||
397 | } | ||||
398 | | ||||
399 | void Settings::setPopupTimeout(int timeout) | ||||
400 | { | ||||
401 | if (this->popupTimeout() == timeout) { | ||||
402 | return; | ||||
403 | } | ||||
404 | NotificationSettings::setPopupTimeout(timeout); | ||||
405 | d->setDirty(true); | ||||
406 | } | ||||
407 | | ||||
408 | void Settings::resetPopupTimeout() | ||||
409 | { | ||||
410 | setPopupTimeout(NotificationSettings::defaultPopupTimeoutValue()); | ||||
411 | } | ||||
412 | | ||||
413 | bool Settings::jobsInTaskManager() const | ||||
414 | { | ||||
415 | return JobSettings::inTaskManager(); | ||||
416 | } | ||||
417 | | ||||
418 | void Settings::setJobsInTaskManager(bool enable) | ||||
419 | { | ||||
420 | if (jobsInTaskManager() == enable) { | ||||
421 | return; | ||||
422 | } | ||||
423 | JobSettings::setInTaskManager(enable); | ||||
424 | d->setDirty(true); | ||||
425 | } | ||||
426 | | ||||
427 | bool Settings::jobsInNotifications() const | ||||
428 | { | ||||
429 | return JobSettings::inNotifications(); | ||||
430 | } | ||||
431 | void Settings::setJobsInNotifications(bool enable) | ||||
432 | { | ||||
433 | if (jobsInNotifications() == enable) { | ||||
434 | return; | ||||
435 | } | ||||
436 | JobSettings::setInNotifications(enable); | ||||
437 | d->setDirty(true); | ||||
438 | } | ||||
439 | | ||||
440 | bool Settings::permanentJobPopups() const | ||||
441 | { | ||||
442 | return JobSettings::permanentPopups(); | ||||
443 | } | ||||
444 | | ||||
445 | void Settings::setPermanentJobPopups(bool enable) | ||||
446 | { | ||||
447 | if (permanentJobPopups() == enable) { | ||||
448 | return; | ||||
449 | } | ||||
450 | JobSettings::setPermanentPopups(enable); | ||||
451 | d->setDirty(true); | ||||
452 | } | ||||
453 | | ||||
454 | bool Settings::badgesInTaskManager() const | ||||
455 | { | ||||
456 | return BadgeSettings::inTaskManager(); | ||||
457 | } | ||||
458 | | ||||
459 | void Settings::setBadgesInTaskManager(bool enable) | ||||
460 | { | ||||
461 | if (badgesInTaskManager() == enable) { | ||||
462 | return; | ||||
463 | } | ||||
464 | BadgeSettings::setInTaskManager(enable); | ||||
465 | d->setDirty(true); | ||||
466 | } | ||||
467 | | ||||
468 | QStringList Settings::knownApplications() const | ||||
469 | { | ||||
470 | return d->applicationsGroup().groupList(); | ||||
471 | } | ||||
472 | | ||||
473 | QStringList Settings::popupBlacklistedApplications() const | ||||
474 | { | ||||
475 | return d->behaviorMatchesList(d->applicationsGroup(), ShowPopups, false); | ||||
476 | } | ||||
477 | | ||||
478 | QStringList Settings::popupBlacklistedServices() const | ||||
479 | { | ||||
480 | return d->behaviorMatchesList(d->servicesGroup(), ShowPopups, false); | ||||
481 | } | ||||
482 | | ||||
483 | QStringList Settings::doNotDisturbPopupWhitelistedApplications() const | ||||
484 | { | ||||
485 | return d->behaviorMatchesList(d->applicationsGroup(), ShowPopupsInDoNotDisturbMode, true); | ||||
486 | } | ||||
487 | | ||||
488 | QStringList Settings::doNotDisturbPopupWhitelistedServices() const | ||||
489 | { | ||||
490 | return d->behaviorMatchesList(d->servicesGroup(), ShowPopupsInDoNotDisturbMode, true); | ||||
491 | } | ||||
492 | | ||||
493 | QStringList Settings::historyBlacklistedApplications() const | ||||
494 | { | ||||
495 | return d->behaviorMatchesList(d->applicationsGroup(), ShowInHistory, false); | ||||
496 | } | ||||
497 | | ||||
498 | QStringList Settings::historyBlacklistedServices() const | ||||
499 | { | ||||
500 | return d->behaviorMatchesList(d->servicesGroup(), ShowInHistory, false); | ||||
501 | } | ||||
502 | | ||||
503 | QDateTime Settings::notificationsInhibitedUntil() const | ||||
504 | { | ||||
505 | return DoNotDisturbSettings::until(); | ||||
506 | } | ||||
507 | | ||||
508 | void Settings::setNotificationsInhibitedUntil(const QDateTime &time) | ||||
509 | { | ||||
510 | DoNotDisturbSettings::setUntil(time); | ||||
511 | d->setDirty(true); | ||||
512 | } | ||||
513 | | ||||
514 | void Settings::resetNotificationsInhibitedUntil() | ||||
515 | { | ||||
516 | setNotificationsInhibitedUntil(QDateTime());// FIXME DoNotDisturbSettings::defaultUntilValue()); | ||||
517 | } | ||||
518 | | ||||
519 | bool Settings::notificationsInhibitedByApplication() const | ||||
520 | { | ||||
521 | return Server::self().inhibited(); | ||||
522 | } | ||||
523 | | ||||
524 | QStringList Settings::notificationInhibitionApplications() const | ||||
525 | { | ||||
526 | return Server::self().inhibitionApplications(); | ||||
527 | } | ||||
528 | | ||||
529 | QStringList Settings::notificationInhibitionReasons() const | ||||
530 | { | ||||
531 | return Server::self().inhibitionReasons(); | ||||
532 | } | ||||
533 | | ||||
534 | void Settings::revokeApplicationInhibitions() | ||||
535 | { | ||||
536 | Server::self().clearInhibitions(); | ||||
537 | } | ||||
538 | | ||||
539 | bool Settings::notificationSoundsInhibited() const | ||||
540 | { | ||||
541 | return DoNotDisturbSettings::notificationSoundsMuted(); | ||||
542 | } | ||||
543 | | ||||
544 | void Settings::setNotificationSoundsInhibited(bool inhibited) | ||||
545 | { | ||||
546 | if (inhibited == notificationSoundsInhibited()) { | ||||
547 | return; | ||||
548 | } | ||||
549 | | ||||
550 | DoNotDisturbSettings::setNotificationSoundsMuted(inhibited); | ||||
551 | d->setDirty(true); | ||||
552 | } |