Changeset View
Changeset View
Standalone View
Standalone View
libnotificationmanager/abstractnotificationsmodel.cpp
- This file was copied from libnotificationmanager/notificationsmodel.cpp.
Show All 12 Lines | |||||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | 15 | * Lesser General Public License for more details. | ||
16 | * | 16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | 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/>. | 18 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | 19 | */ | ||
20 | 20 | | |||
21 | #include "notificationsmodel.h" | 21 | #include "abstractnotificationsmodel.h" | ||
22 | 22 | #include "abstractnotificationsmodel_p.h" | |||
23 | #include "debug.h" | 23 | #include "debug.h" | ||
24 | 24 | | |||
25 | #include "server.h" | 25 | #include "server.h" | ||
26 | #include "utils_p.h" | 26 | #include "utils_p.h" | ||
27 | 27 | | |||
28 | #include "notifications.h" | 28 | #include "notifications.h" | ||
29 | 29 | | |||
30 | #include "notification.h" | 30 | #include "notification.h" | ||
31 | #include "notification_p.h" | 31 | #include "notification_p.h" | ||
32 | 32 | | |||
33 | #include <QDebug> | 33 | #include <QDebug> | ||
34 | #include <QProcess> | 34 | #include <QProcess> | ||
35 | #include <QTimer> | 35 | #include <QTimer> | ||
36 | 36 | | |||
37 | #include <KShell> | 37 | #include <KShell> | ||
38 | 38 | | |||
39 | #include <algorithm> | 39 | #include <algorithm> | ||
40 | #include <functional> | 40 | #include <functional> | ||
41 | 41 | | |||
42 | static const int s_notificationsLimit = 1000; | 42 | static const int s_notificationsLimit = 1000; | ||
43 | 43 | | |||
44 | using namespace NotificationManager; | 44 | using namespace NotificationManager; | ||
45 | 45 | | |||
46 | class Q_DECL_HIDDEN NotificationsModel::Private | 46 | AbstractNotificationsModel::Private::Private(AbstractNotificationsModel *q) | ||
47 | { | | |||
48 | public: | | |||
49 | explicit Private(NotificationsModel *q); | | |||
50 | ~Private(); | | |||
51 | | ||||
52 | void onNotificationAdded(const Notification ¬ification); | | |||
53 | void onNotificationReplaced(uint replacedId, const Notification ¬ification); | | |||
54 | void onNotificationRemoved(uint notificationId, Server::CloseReason reason); | | |||
55 | | ||||
56 | void setupNotificationTimeout(const Notification ¬ification); | | |||
57 | | ||||
58 | int rowOfNotification(uint id) const; | | |||
59 | | ||||
60 | NotificationsModel *q; | | |||
61 | | ||||
62 | QVector<Notification> notifications; | | |||
63 | // Fallback timeout to ensure all notifications expire eventually | | |||
64 | // otherwise when it isn't shown to the user and doesn't expire | | |||
65 | // an app might wait indefinitely for the notification to do so | | |||
66 | QHash<uint /*notificationId*/, QTimer*> notificationTimeouts; | | |||
67 | | ||||
68 | QDateTime lastRead; | | |||
69 | | ||||
70 | }; | | |||
71 | | ||||
72 | NotificationsModel::Private::Private(NotificationsModel *q) | | |||
73 | : q(q) | 47 | : q(q) | ||
74 | , lastRead(QDateTime::currentDateTimeUtc()) | 48 | , lastRead(QDateTime::currentDateTimeUtc()) | ||
75 | { | 49 | { | ||
76 | 50 | | |||
77 | } | 51 | } | ||
78 | 52 | | |||
79 | NotificationsModel::Private::~Private() | 53 | AbstractNotificationsModel::Private::~Private() | ||
80 | { | 54 | { | ||
81 | qDeleteAll(notificationTimeouts); | 55 | qDeleteAll(notificationTimeouts); | ||
82 | notificationTimeouts.clear(); | 56 | notificationTimeouts.clear(); | ||
83 | } | 57 | } | ||
84 | 58 | | |||
85 | void NotificationsModel::Private::onNotificationAdded(const Notification ¬ification) | 59 | void AbstractNotificationsModel::Private::onNotificationAdded(const Notification ¬ification) | ||
86 | { | 60 | { | ||
87 | // Once we reach a certain insane number of notifications discard some old ones | 61 | // Once we reach a certain insane number of notifications discard some old ones | ||
88 | // as we keep pixmaps around etc | 62 | // as we keep pixmaps around etc | ||
89 | if (notifications.count() >= s_notificationsLimit) { | 63 | if (notifications.count() >= s_notificationsLimit) { | ||
90 | const int cleanupCount = s_notificationsLimit / 2; | 64 | const int cleanupCount = s_notificationsLimit / 2; | ||
91 | qCDebug(NOTIFICATIONMANAGER) << "Reached the notification limit of" << s_notificationsLimit << ", discarding the oldest" << cleanupCount << "notifications"; | 65 | qCDebug(NOTIFICATIONMANAGER) << "Reached the notification limit of" << s_notificationsLimit << ", discarding the oldest" << cleanupCount << "notifications"; | ||
92 | q->beginRemoveRows(QModelIndex(), 0, cleanupCount - 1); | 66 | q->beginRemoveRows(QModelIndex(), 0, cleanupCount - 1); | ||
93 | for (int i = 0 ; i < cleanupCount; ++i) { | 67 | for (int i = 0 ; i < cleanupCount; ++i) { | ||
94 | notifications.removeAt(0); | 68 | notifications.removeAt(0); | ||
95 | // TODO close gracefully? | 69 | // TODO close gracefully? | ||
96 | } | 70 | } | ||
97 | q->endRemoveRows(); | 71 | q->endRemoveRows(); | ||
98 | } | 72 | } | ||
99 | 73 | | |||
100 | setupNotificationTimeout(notification); | 74 | setupNotificationTimeout(notification); | ||
101 | 75 | | |||
102 | q->beginInsertRows(QModelIndex(), notifications.count(), notifications.count()); | 76 | q->beginInsertRows(QModelIndex(), notifications.count(), notifications.count()); | ||
103 | notifications.append(std::move(notification)); | 77 | notifications.append(std::move(notification)); | ||
104 | q->endInsertRows(); | 78 | q->endInsertRows(); | ||
105 | } | 79 | } | ||
106 | 80 | | |||
107 | void NotificationsModel::Private::onNotificationReplaced(uint replacedId, const Notification ¬ification) | 81 | void AbstractNotificationsModel::Private::onNotificationReplaced(uint replacedId, const Notification ¬ification) | ||
108 | { | 82 | { | ||
109 | const int row = rowOfNotification(replacedId); | 83 | const int row = q->rowOfNotification(replacedId); | ||
110 | 84 | | |||
111 | if (row == -1) { | 85 | if (row == -1) { | ||
112 | qCWarning(NOTIFICATIONMANAGER) << "Trying to replace notification with id" << replacedId << "which doesn't exist, creating a new one. This is an application bug!"; | 86 | qCWarning(NOTIFICATIONMANAGER) << "Trying to replace notification with id" << replacedId << "which doesn't exist, creating a new one. This is an application bug!"; | ||
113 | onNotificationAdded(notification); | 87 | onNotificationAdded(notification); | ||
114 | return; | 88 | return; | ||
115 | } | 89 | } | ||
116 | 90 | | |||
117 | setupNotificationTimeout(notification); | 91 | setupNotificationTimeout(notification); | ||
118 | 92 | | |||
119 | notifications[row] = notification; | 93 | notifications[row] = notification; | ||
120 | const QModelIndex idx = q->index(row, 0); | 94 | const QModelIndex idx = q->index(row, 0); | ||
121 | emit q->dataChanged(idx, idx); | 95 | emit q->dataChanged(idx, idx); | ||
122 | } | 96 | } | ||
123 | 97 | | |||
124 | void NotificationsModel::Private::onNotificationRemoved(uint removedId, Server::CloseReason reason) | 98 | void AbstractNotificationsModel::Private::onNotificationRemoved(uint removedId, Server::CloseReason reason) | ||
125 | { | 99 | { | ||
126 | const int row = rowOfNotification(removedId); | 100 | const int row = q->rowOfNotification(removedId); | ||
127 | if (row == -1) { | 101 | if (row == -1) { | ||
128 | return; | 102 | return; | ||
129 | } | 103 | } | ||
130 | 104 | | |||
131 | q->stopTimeout(removedId); | 105 | q->stopTimeout(removedId); | ||
132 | 106 | | |||
133 | // When a notification expired, keep it around in the history and mark it as such | 107 | // When a notification expired, keep it around in the history and mark it as such | ||
134 | if (reason == Server::CloseReason::Expired) { | 108 | if (reason == Server::CloseReason::Expired) { | ||
Show All 21 Lines | |||||
156 | 130 | | |||
157 | // Otherwise if explicitly closed by either user or app, remove it | 131 | // Otherwise if explicitly closed by either user or app, remove it | ||
158 | 132 | | |||
159 | q->beginRemoveRows(QModelIndex(), row, row); | 133 | q->beginRemoveRows(QModelIndex(), row, row); | ||
160 | notifications.removeAt(row); | 134 | notifications.removeAt(row); | ||
161 | q->endRemoveRows(); | 135 | q->endRemoveRows(); | ||
162 | } | 136 | } | ||
163 | 137 | | |||
164 | void NotificationsModel::Private::setupNotificationTimeout(const Notification ¬ification) | 138 | void AbstractNotificationsModel::Private::setupNotificationTimeout(const Notification ¬ification) | ||
165 | { | 139 | { | ||
166 | if (notification.timeout() == 0) { | 140 | if (notification.timeout() == 0) { | ||
167 | // In case it got replaced by a persistent notification | 141 | // In case it got replaced by a persistent notification | ||
168 | q->stopTimeout(notification.id()); | 142 | q->stopTimeout(notification.id()); | ||
169 | return; | 143 | return; | ||
170 | } | 144 | } | ||
171 | 145 | | |||
172 | QTimer *timer = notificationTimeouts.value(notification.id()); | 146 | QTimer *timer = notificationTimeouts.value(notification.id()); | ||
Show All 9 Lines | |||||
182 | } | 156 | } | ||
183 | 157 | | |||
184 | timer->stop(); | 158 | timer->stop(); | ||
185 | timer->setProperty("notificationId", notification.id()); | 159 | timer->setProperty("notificationId", notification.id()); | ||
186 | timer->setInterval(60000 /*1min*/ + (notification.timeout() == -1 ? 120000 /*2min, max configurable default timeout*/ : notification.timeout())); | 160 | timer->setInterval(60000 /*1min*/ + (notification.timeout() == -1 ? 120000 /*2min, max configurable default timeout*/ : notification.timeout())); | ||
187 | timer->start(); | 161 | timer->start(); | ||
188 | } | 162 | } | ||
189 | 163 | | |||
190 | int NotificationsModel::Private::rowOfNotification(uint id) const | 164 | int AbstractNotificationsModel::rowOfNotification(uint id) const | ||
191 | { | 165 | { | ||
192 | auto it = std::find_if(notifications.constBegin(), notifications.constEnd(), [id](const Notification &item) { | 166 | auto it = std::find_if(d->notifications.constBegin(), d->notifications.constEnd(), [id](const Notification &item) { | ||
193 | return item.id() == id; | 167 | return item.id() == id; | ||
194 | }); | 168 | }); | ||
195 | 169 | | |||
196 | if (it == notifications.constEnd()) { | 170 | if (it == d->notifications.constEnd()) { | ||
197 | return -1; | 171 | return -1; | ||
198 | } | 172 | } | ||
199 | 173 | | |||
200 | return std::distance(notifications.constBegin(), it); | 174 | return std::distance(d->notifications.constBegin(), it); | ||
201 | } | 175 | } | ||
202 | 176 | | |||
203 | NotificationsModel::NotificationsModel() | 177 | AbstractNotificationsModel::AbstractNotificationsModel() | ||
204 | : QAbstractListModel(nullptr) | 178 | : QAbstractListModel(nullptr) | ||
205 | , d(new Private(this)) | 179 | , d(new Private(this)) | ||
206 | { | 180 | { | ||
207 | connect(&Server::self(), &Server::notificationAdded, this, [this](const Notification ¬ification) { | | |||
208 | d->onNotificationAdded(notification); | | |||
209 | }); | | |||
210 | connect(&Server::self(), &Server::notificationReplaced, this, [this](uint replacedId, const Notification ¬ification) { | | |||
211 | d->onNotificationReplaced(replacedId, notification); | | |||
212 | }); | | |||
213 | connect(&Server::self(), &Server::notificationRemoved, this, [this](uint removedId, Server::CloseReason reason) { | | |||
214 | d->onNotificationRemoved(removedId, reason); | | |||
215 | }); | | |||
216 | connect(&Server::self(), &Server::serviceOwnershipLost, this, [this] { | | |||
217 | // Expire all notifications as we're defunct now | | |||
218 | const auto notifications = d->notifications; | | |||
219 | for (const Notification ¬ification : notifications) { | | |||
220 | if (!notification.expired()) { | | |||
221 | d->onNotificationRemoved(notification.id(), Server::CloseReason::Expired); | | |||
222 | } | | |||
223 | } | 181 | } | ||
224 | }); | | |||
225 | 182 | | |||
226 | Server::self().init(); | 183 | AbstractNotificationsModel::~AbstractNotificationsModel() = default; | ||
227 | } | | |||
228 | 184 | | |||
229 | NotificationsModel::~NotificationsModel() = default; | 185 | QDateTime AbstractNotificationsModel::lastRead() const | ||
230 | | ||||
231 | NotificationsModel::Ptr NotificationsModel::createNotificationsModel() | | |||
232 | { | | |||
233 | static QWeakPointer<NotificationsModel> s_instance; | | |||
234 | if (!s_instance) { | | |||
235 | QSharedPointer<NotificationsModel> ptr(new NotificationsModel()); | | |||
236 | s_instance = ptr.toWeakRef(); | | |||
237 | return ptr; | | |||
238 | } | | |||
239 | return s_instance.toStrongRef(); | | |||
240 | } | | |||
241 | | ||||
242 | QDateTime NotificationsModel::lastRead() const | | |||
243 | { | 186 | { | ||
244 | return d->lastRead; | 187 | return d->lastRead; | ||
245 | } | 188 | } | ||
246 | 189 | | |||
247 | void NotificationsModel::setLastRead(const QDateTime &lastRead) | 190 | void AbstractNotificationsModel::setLastRead(const QDateTime &lastRead) | ||
248 | { | 191 | { | ||
249 | if (d->lastRead != lastRead) { | 192 | if (d->lastRead != lastRead) { | ||
250 | d->lastRead = lastRead; | 193 | d->lastRead = lastRead; | ||
251 | emit lastReadChanged(); | 194 | emit lastReadChanged(); | ||
252 | } | 195 | } | ||
253 | } | 196 | } | ||
254 | 197 | | |||
255 | QVariant NotificationsModel::data(const QModelIndex &index, int role) const | 198 | QVariant AbstractNotificationsModel::data(const QModelIndex &index, int role) const | ||
256 | { | 199 | { | ||
257 | if (!checkIndex(index)) { | 200 | if (!checkIndex(index)) { | ||
258 | return QVariant(); | 201 | return QVariant(); | ||
259 | } | 202 | } | ||
260 | 203 | | |||
261 | const Notification ¬ification = d->notifications.at(index.row()); | 204 | const Notification ¬ification = d->notifications.at(index.row()); | ||
262 | 205 | | |||
263 | switch (role) { | 206 | switch (role) { | ||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Line(s) | |||||
317 | case Notifications::ReplyPlaceholderTextRole: return notification.replyPlaceholderText(); | 260 | case Notifications::ReplyPlaceholderTextRole: return notification.replyPlaceholderText(); | ||
318 | case Notifications::ReplySubmitButtonTextRole: return notification.replySubmitButtonText(); | 261 | case Notifications::ReplySubmitButtonTextRole: return notification.replySubmitButtonText(); | ||
319 | case Notifications::ReplySubmitButtonIconNameRole: return notification.replySubmitButtonIconName(); | 262 | case Notifications::ReplySubmitButtonIconNameRole: return notification.replySubmitButtonIconName(); | ||
320 | } | 263 | } | ||
321 | 264 | | |||
322 | return QVariant(); | 265 | return QVariant(); | ||
323 | } | 266 | } | ||
324 | 267 | | |||
325 | bool NotificationsModel::setData(const QModelIndex &index, const QVariant &value, int role) | 268 | bool AbstractNotificationsModel::setData(const QModelIndex &index, const QVariant &value, int role) | ||
326 | { | 269 | { | ||
327 | if (!checkIndex(index)) { | 270 | if (!checkIndex(index)) { | ||
328 | return false; | 271 | return false; | ||
329 | } | 272 | } | ||
330 | 273 | | |||
331 | Notification ¬ification = d->notifications[index.row()]; | 274 | Notification ¬ification = d->notifications[index.row()]; | ||
332 | 275 | | |||
333 | switch (role) { | 276 | switch (role) { | ||
334 | case Notifications::ReadRole: | 277 | case Notifications::ReadRole: | ||
335 | if (value.toBool() != notification.read()) { | 278 | if (value.toBool() != notification.read()) { | ||
336 | notification.setRead(value.toBool()); | 279 | notification.setRead(value.toBool()); | ||
337 | return true; | 280 | return true; | ||
338 | } | 281 | } | ||
339 | break; | 282 | break; | ||
340 | } | 283 | } | ||
341 | 284 | | |||
342 | return false; | 285 | return false; | ||
343 | } | 286 | } | ||
344 | 287 | | |||
345 | int NotificationsModel::rowCount(const QModelIndex &parent) const | 288 | int AbstractNotificationsModel::rowCount(const QModelIndex &parent) const | ||
346 | { | 289 | { | ||
347 | if (parent.isValid()) { | 290 | if (parent.isValid()) { | ||
348 | return 0; | 291 | return 0; | ||
349 | } | 292 | } | ||
350 | 293 | | |||
351 | return d->notifications.count(); | 294 | return d->notifications.count(); | ||
352 | } | 295 | } | ||
353 | 296 | | |||
354 | QHash<int, QByteArray> NotificationsModel::roleNames() const | 297 | QHash<int, QByteArray> AbstractNotificationsModel::roleNames() const | ||
355 | { | 298 | { | ||
356 | return Utils::roleNames(); | 299 | return Utils::roleNames(); | ||
357 | } | 300 | } | ||
358 | 301 | | |||
359 | void NotificationsModel::expire(uint notificationId) | 302 | void AbstractNotificationsModel::startTimeout(uint notificationId) | ||
360 | { | | |||
361 | if (d->rowOfNotification(notificationId) > -1) { | | |||
362 | Server::self().closeNotification(notificationId, Server::CloseReason::Expired); | | |||
363 | } | | |||
364 | } | | |||
365 | | ||||
366 | void NotificationsModel::close(uint notificationId) | | |||
367 | { | | |||
368 | if (d->rowOfNotification(notificationId) > -1) { | | |||
369 | Server::self().closeNotification(notificationId, Server::CloseReason::DismissedByUser); | | |||
370 | } | | |||
371 | } | | |||
372 | | ||||
373 | void NotificationsModel::configure(uint notificationId) | | |||
374 | { | | |||
375 | const int row = d->rowOfNotification(notificationId); | | |||
376 | if (row == -1) { | | |||
377 | return; | | |||
378 | } | | |||
379 | | ||||
380 | const Notification ¬ification = d->notifications.at(row); | | |||
381 | | ||||
382 | if (notification.d->hasConfigureAction) { | | |||
383 | Server::self().invokeAction(notificationId, QStringLiteral("settings")); // FIXME make a static Notification::configureActionName() or something | | |||
384 | return; | | |||
385 | } | | |||
386 | | ||||
387 | if (!notification.desktopEntry().isEmpty() || !notification.notifyRcName().isEmpty()) { | | |||
388 | configure(notification.desktopEntry(), notification.notifyRcName(), notification.eventId()); | | |||
389 | return; | | |||
390 | } | | |||
391 | | ||||
392 | qCWarning(NOTIFICATIONMANAGER) << "Trying to configure notification" << notificationId << "which isn't configurable"; | | |||
393 | } | | |||
394 | | ||||
395 | void NotificationsModel::configure(const QString &desktopEntry, const QString ¬ifyRcName, const QString &eventId) | | |||
396 | { | | |||
397 | // TODO would be nice to just have a signal but since NotificationsModel is shared, | | |||
398 | // if we connect to this from Notifications you would get a signal in every instance | | |||
399 | // and potentially open the config dialog multiple times. | | |||
400 | | ||||
401 | QStringList args; | | |||
402 | if (!desktopEntry.isEmpty()) { | | |||
403 | args.append(QStringLiteral("--desktop-entry")); | | |||
404 | args.append(desktopEntry); | | |||
405 | } | | |||
406 | if (!notifyRcName.isEmpty()) { | | |||
407 | args.append(QStringLiteral("--notifyrc")); | | |||
408 | args.append(notifyRcName); | | |||
409 | } | | |||
410 | if (!eventId.isEmpty()) { | | |||
411 | args.append(QStringLiteral("--event-id")); | | |||
412 | args.append(eventId); | | |||
413 | } | | |||
414 | | ||||
415 | QProcess::startDetached(QStringLiteral("kcmshell5"), { | | |||
416 | QStringLiteral("notifications"), | | |||
417 | QStringLiteral("--args"), | | |||
418 | KShell::joinArgs(args) | | |||
419 | }); | | |||
420 | } | | |||
421 | | ||||
422 | void NotificationsModel::invokeDefaultAction(uint notificationId) | | |||
423 | { | 303 | { | ||
424 | const int row = d->rowOfNotification(notificationId); | 304 | const int row = rowOfNotification(notificationId); | ||
425 | if (row == -1) { | | |||
426 | return; | | |||
427 | } | | |||
428 | | ||||
429 | const Notification ¬ification = d->notifications.at(row); | | |||
430 | if (!notification.hasDefaultAction()) { | | |||
431 | qCWarning(NOTIFICATIONMANAGER) << "Trying to invoke default action on notification" << notificationId << "which doesn't have one"; | | |||
432 | return; | | |||
433 | } | | |||
434 | | ||||
435 | Server::self().invokeAction(notificationId, QStringLiteral("default")); // FIXME make a static Notification::defaultActionName() or something | | |||
436 | } | | |||
437 | | ||||
438 | void NotificationsModel::invokeAction(uint notificationId, const QString &actionName) | | |||
439 | { | | |||
440 | const int row = d->rowOfNotification(notificationId); | | |||
441 | if (row == -1) { | | |||
442 | return; | | |||
443 | } | | |||
444 | | ||||
445 | const Notification ¬ification = d->notifications.at(row); | | |||
446 | if (!notification.actionNames().contains(actionName)) { | | |||
447 | qCWarning(NOTIFICATIONMANAGER) << "Trying to invoke action" << actionName << "on notification" << notificationId << "which it doesn't have"; | | |||
448 | return; | | |||
449 | } | | |||
450 | | ||||
451 | Server::self().invokeAction(notificationId, actionName); | | |||
452 | } | | |||
453 | | ||||
454 | void NotificationsModel::reply(uint notificationId, const QString &text) | | |||
455 | { | | |||
456 | const int row = d->rowOfNotification(notificationId); | | |||
457 | if (row == -1) { | | |||
458 | return; | | |||
459 | } | | |||
460 | | ||||
461 | const Notification ¬ification = d->notifications.at(row); | | |||
462 | if (!notification.hasReplyAction()) { | | |||
463 | qCWarning(NOTIFICATIONMANAGER) << "Trying to reply to a notification which doesn't have a reply action"; | | |||
464 | return; | | |||
465 | } | | |||
466 | | ||||
467 | Server::self().reply(notification.dBusService(), notificationId, text); | | |||
468 | } | | |||
469 | | ||||
470 | void NotificationsModel::startTimeout(uint notificationId) | | |||
471 | { | | |||
472 | const int row = d->rowOfNotification(notificationId); | | |||
473 | if (row == -1) { | 305 | if (row == -1) { | ||
474 | return; | 306 | return; | ||
475 | } | 307 | } | ||
476 | 308 | | |||
477 | const Notification ¬ification = d->notifications.at(row); | 309 | const Notification ¬ification = d->notifications.at(row); | ||
478 | 310 | | |||
479 | if (!notification.timeout() || notification.expired()) { | 311 | if (!notification.timeout() || notification.expired()) { | ||
480 | return; | 312 | return; | ||
481 | } | 313 | } | ||
482 | 314 | | |||
483 | d->setupNotificationTimeout(notification); | 315 | d->setupNotificationTimeout(notification); | ||
484 | } | 316 | } | ||
485 | 317 | | |||
486 | void NotificationsModel::stopTimeout(uint notificationId) | 318 | void AbstractNotificationsModel::stopTimeout(uint notificationId) | ||
487 | { | 319 | { | ||
488 | delete d->notificationTimeouts.take(notificationId); | 320 | delete d->notificationTimeouts.take(notificationId); | ||
489 | } | 321 | } | ||
490 | 322 | | |||
491 | void NotificationsModel::clear(Notifications::ClearFlags flags) | 323 | void AbstractNotificationsModel::clear(Notifications::ClearFlags flags) | ||
492 | { | 324 | { | ||
493 | if (d->notifications.isEmpty()) { | 325 | if (d->notifications.isEmpty()) { | ||
494 | return; | 326 | return; | ||
495 | } | 327 | } | ||
496 | 328 | | |||
497 | // Tries to remove a contiguous group if possible as the likely case is | 329 | // Tries to remove a contiguous group if possible as the likely case is | ||
498 | // you have n unread notifications at the end of the list, we don't want to | 330 | // you have n unread notifications at the end of the list, we don't want to | ||
499 | // remove and signal each item individually | 331 | // remove and signal each item individually | ||
Show All 29 Lines | |||||
529 | for (const auto &range : clearQueue) { | 361 | for (const auto &range : clearQueue) { | ||
530 | beginRemoveRows(QModelIndex(), range.first, range.second); | 362 | beginRemoveRows(QModelIndex(), range.first, range.second); | ||
531 | for (int i = range.second; i >= range.first; --i) { | 363 | for (int i = range.second; i >= range.first; --i) { | ||
532 | d->notifications.removeAt(i); | 364 | d->notifications.removeAt(i); | ||
533 | } | 365 | } | ||
534 | endRemoveRows(); | 366 | endRemoveRows(); | ||
535 | } | 367 | } | ||
536 | } | 368 | } | ||
369 | | ||||
370 | void AbstractNotificationsModel::onNotificationAdded(const Notification ¬ification) | ||||
371 | { | ||||
372 | d->onNotificationAdded(notification); | ||||
373 | } | ||||
374 | | ||||
375 | void AbstractNotificationsModel::onNotificationReplaced(uint replacedId, const Notification ¬ification) | ||||
376 | { | ||||
377 | d->onNotificationReplaced(replacedId, notification); | ||||
378 | } | ||||
379 | | ||||
380 | void AbstractNotificationsModel::onNotificationRemoved(uint notificationId, Server::CloseReason reason) | ||||
381 | { | ||||
382 | d->onNotificationRemoved(notificationId, reason); | ||||
383 | } | ||||
384 | | ||||
385 | void AbstractNotificationsModel::setupNotificationTimeout(const Notification ¬ification) | ||||
386 | { | ||||
387 | d->setupNotificationTimeout(notification); | ||||
388 | } | ||||
389 | | ||||
390 | const QVector<Notification>& AbstractNotificationsModel::notifications() | ||||
391 | { | ||||
392 | return d->notifications; | ||||
393 | } |