1 /*
2 * Copyright (C) by Klaas Freitag <freitag@owncloud.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 */
14
15 #include <QtGui>
16 #include <QtWidgets>
17
18 #include "activitylistmodel.h"
19 #include "activitywidget.h"
20 #include "syncresult.h"
21 #include "logger.h"
22 #include "theme.h"
23 #include "folderman.h"
24 #include "syncfileitem.h"
25 #include "folder.h"
26 #include "openfilemanager.h"
27 #include "owncloudpropagator.h"
28 #include "account.h"
29 #include "accountstate.h"
30 #include "accountmanager.h"
31 #include "activityitemdelegate.h"
32 #include "protocolwidget.h"
33 #include "issueswidget.h"
34 #include "QProgressIndicator.h"
35 #include "notificationwidget.h"
36 #include "notificationconfirmjob.h"
37 #include "servernotificationhandler.h"
38 #include "theme.h"
39 #include "ocsjob.h"
40
41 #include "ui_activitywidget.h"
42
43 #include <climits>
44
45 // time span in milliseconds which has to be between two
46 // refreshes of the notifications
47 #define NOTIFICATION_REQUEST_FREE_PERIOD 15000
48
49 namespace OCC {
50
ActivityWidget(QWidget * parent)51 ActivityWidget::ActivityWidget(QWidget *parent)
52 : QWidget(parent)
53 , _ui(new Ui::ActivityWidget)
54 , _notificationRequestsRunning(0)
55 {
56 _ui->setupUi(this);
57
58 // Adjust copyToClipboard() when making changes here!
59 #if defined(Q_OS_MAC)
60 _ui->_activityList->setMinimumWidth(400);
61 #endif
62
63 _model = new ActivityListModel(this);
64 ActivityItemDelegate *delegate = new ActivityItemDelegate;
65 delegate->setParent(this);
66 _ui->_activityList->setItemDelegate(delegate);
67 _ui->_activityList->setAlternatingRowColors(true);
68 _ui->_activityList->setModel(_model);
69
70 _ui->_notifyLabel->hide();
71 _ui->_notifyScroll->hide();
72
73 // Create a widget container for the notifications. The ui file defines
74 // a scroll area that get a widget with a layout as children
75 QWidget *w = new QWidget;
76 _notificationsLayout = new QVBoxLayout;
77 w->setLayout(_notificationsLayout);
78 _notificationsLayout->setAlignment(Qt::AlignTop);
79 _ui->_notifyScroll->setAlignment(Qt::AlignTop);
80 _ui->_notifyScroll->setWidget(w);
81
82 showLabels();
83
84 connect(_model, &ActivityListModel::activityJobStatusCode,
85 this, &ActivityWidget::slotAccountActivityStatus);
86
87 connect(AccountManager::instance(), &AccountManager::accountRemoved, this, [this](AccountState *ast) {
88 if (_accountsWithoutActivities.remove(ast->account()->displayName())) {
89 showLabels();
90 }
91
92 for (auto it = _widgetForNotifId.cbegin(); it != _widgetForNotifId.cend(); ++it) {
93 if (it.key().second == ast->account()->displayName()) {
94 scheduleWidgetToRemove(it.value());
95 }
96 }
97 });
98
99 _copyBtn = _ui->_dialogButtonBox->addButton(tr("Copy"), QDialogButtonBox::ActionRole);
100 _copyBtn->setToolTip(tr("Copy the activity list to the clipboard."));
101 connect(_copyBtn, &QAbstractButton::clicked, this, &ActivityWidget::copyToClipboard);
102
103 connect(_model, &QAbstractItemModel::rowsInserted, this, &ActivityWidget::rowsInserted);
104
105 connect(_ui->_activityList, &QListView::activated, this, &ActivityWidget::slotOpenFile);
106
107 connect(&_removeTimer, &QTimer::timeout, this, &ActivityWidget::slotCheckToCleanWidgets);
108 _removeTimer.setInterval(1000);
109 }
110
~ActivityWidget()111 ActivityWidget::~ActivityWidget()
112 {
113 delete _ui;
114 }
115
slotRefreshActivities(AccountState * ptr)116 void ActivityWidget::slotRefreshActivities(AccountState *ptr)
117 {
118 _model->slotRefreshActivity(ptr);
119 }
120
slotRefreshNotifications(AccountState * ptr)121 void ActivityWidget::slotRefreshNotifications(AccountState *ptr)
122 {
123 // start a server notification handler if no notification requests
124 // are running
125 if (_notificationRequestsRunning == 0) {
126 ServerNotificationHandler *snh = new ServerNotificationHandler;
127 connect(snh, &ServerNotificationHandler::newNotificationList,
128 this, &ActivityWidget::slotBuildNotificationDisplay);
129
130 snh->slotFetchNotifications(ptr);
131 } else {
132 qCWarning(lcActivity) << "Notification request counter not zero.";
133 }
134 }
135
slotRemoveAccount(AccountState * ptr)136 void ActivityWidget::slotRemoveAccount(AccountState *ptr)
137 {
138 _model->slotRemoveAccount(ptr);
139 }
140
showLabels()141 void ActivityWidget::showLabels()
142 {
143 QString t = tr("Server Activities");
144 _ui->_headerLabel->setTextFormat(Qt::RichText);
145 _ui->_headerLabel->setText(t);
146
147 _ui->_notifyLabel->setText(tr("Notifications"));
148
149 t.clear();
150 QSetIterator<QString> i(_accountsWithoutActivities);
151 while (i.hasNext()) {
152 t.append(tr("<br/>Account %1 does not have activities enabled.").arg(i.next()));
153 }
154 _ui->_bottomLabel->setTextFormat(Qt::RichText);
155 _ui->_bottomLabel->setText(t);
156 }
157
slotAccountActivityStatus(AccountState * ast,int statusCode)158 void ActivityWidget::slotAccountActivityStatus(AccountState *ast, int statusCode)
159 {
160 if (!(ast && ast->account())) {
161 return;
162 }
163 if (statusCode == 999) {
164 _accountsWithoutActivities.insert(ast->account()->displayName());
165 } else {
166 _accountsWithoutActivities.remove(ast->account()->displayName());
167 }
168
169 checkActivityTabVisibility();
170 showLabels();
171 }
172
173 // FIXME: Reused from protocol widget. Move over to utilities.
timeString(QDateTime dt,QLocale::FormatType format) const174 QString ActivityWidget::timeString(QDateTime dt, QLocale::FormatType format) const
175 {
176 const QLocale loc = QLocale::system();
177 QString dtFormat = loc.dateTimeFormat(format);
178 static const QRegExp re("(HH|H|hh|h):mm(?!:s)");
179 dtFormat.replace(re, "\\1:mm:ss");
180 return loc.toString(dt, dtFormat);
181 }
182
storeActivityList(QTextStream & ts)183 void ActivityWidget::storeActivityList(QTextStream &ts)
184 {
185 ActivityList activities = _model->activityList();
186
187 foreach (Activity activity, activities) {
188 ts << right
189 // account name
190 << qSetFieldWidth(30)
191 << activity._accName
192 // separator
193 << qSetFieldWidth(0) << ","
194
195 // date and time
196 << qSetFieldWidth(34)
197 << activity._dateTime.toString()
198 // separator
199 << qSetFieldWidth(0) << ","
200
201 // file
202 << qSetFieldWidth(30)
203 << activity._file
204 // separator
205 << qSetFieldWidth(0) << ","
206
207 // subject
208 << qSetFieldWidth(100)
209 << activity._subject
210 // separator
211 << qSetFieldWidth(0) << ","
212
213 // message (mostly empty)
214 << qSetFieldWidth(55)
215 << activity._message
216 //
217 << qSetFieldWidth(0)
218 << endl;
219 }
220 }
221
checkActivityTabVisibility()222 void ActivityWidget::checkActivityTabVisibility()
223 {
224 int accountCount = AccountManager::instance()->accounts().count();
225 bool hasAccountsWithActivity =
226 _accountsWithoutActivities.count() != accountCount;
227 bool hasNotifications = !_widgetForNotifId.isEmpty();
228
229 _ui->_headerLabel->setVisible(hasAccountsWithActivity);
230 _ui->_activityList->setVisible(hasAccountsWithActivity);
231
232 _ui->_notifyLabel->setVisible(hasNotifications);
233 _ui->_notifyScroll->setVisible(hasNotifications);
234
235 emit hideActivityTab(!hasAccountsWithActivity && !hasNotifications);
236 }
237
slotOpenFile(QModelIndex indx)238 void ActivityWidget::slotOpenFile(QModelIndex indx)
239 {
240 qCDebug(lcActivity) << indx.isValid() << indx.data(ActivityItemDelegate::PathRole).toString() << QFile::exists(indx.data(ActivityItemDelegate::PathRole).toString());
241 if (indx.isValid()) {
242 QString fullPath = indx.data(ActivityItemDelegate::PathRole).toString();
243
244 if (QFile::exists(fullPath)) {
245 showInFileManager(fullPath);
246 }
247 }
248 }
249
250 // GUI: Display the notifications.
251 // All notifications in list are coming from the same account
252 // but in the _widgetForNotifId hash widgets for all accounts are
253 // collected.
slotBuildNotificationDisplay(const ActivityList & list)254 void ActivityWidget::slotBuildNotificationDisplay(const ActivityList &list)
255 {
256 QHash<QString, int> accNotified;
257 QString listAccountName;
258
259 // Whether a new notification widget was added to the notificationLayout.
260 bool newNotificationShown = false;
261
262 foreach (auto activity, list) {
263 if (_blacklistedNotifications.contains(activity)) {
264 qCInfo(lcActivity) << "Activity in blacklist, skip";
265 continue;
266 }
267
268 NotificationWidget *widget = nullptr;
269
270 if (_widgetForNotifId.contains(activity.ident())) {
271 widget = _widgetForNotifId[activity.ident()];
272 } else {
273 widget = new NotificationWidget(this);
274 connect(widget, &NotificationWidget::sendNotificationRequest,
275 this, &ActivityWidget::slotSendNotificationRequest);
276 connect(widget, &NotificationWidget::requestCleanupAndBlacklist,
277 this, &ActivityWidget::slotRequestCleanupAndBlacklist);
278
279 _notificationsLayout->addWidget(widget);
280 // _ui->_notifyScroll->setMinimumHeight( widget->height());
281 _ui->_notifyScroll->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
282 _widgetForNotifId[activity.ident()] = widget;
283 newNotificationShown = true;
284 }
285
286 widget->setActivity(activity);
287
288 // remember the list account name for the strayCat handling below.
289 listAccountName = activity._accName;
290
291 // handle gui logs. In order to NOT annoy the user with every fetching of the
292 // notifications the notification id is stored in a Set. Only if an id
293 // is not in the set, it qualifies for guiLog.
294 // Important: The _guiLoggedNotifications set must be wiped regularly which
295 // will repeat the gui log.
296
297 // after one hour, clear the gui log notification store
298 if (_guiLogTimer.elapsed() > 60 * 60 * 1000) {
299 _guiLoggedNotifications.clear();
300 }
301 if (!_guiLoggedNotifications.contains(activity._id)) {
302 QString host = activity._accName;
303 // store the name of the account that sends the notification to be
304 // able to add it to the tray notification
305 if (!host.isEmpty()) {
306 if (accNotified.contains(host)) {
307 accNotified[host] = accNotified[host] + 1;
308 } else {
309 accNotified[host] = 1;
310 }
311 }
312 _guiLoggedNotifications.insert(activity._id);
313 }
314 }
315
316 // check if there are widgets that have no corresponding activity from
317 // the server any more. Collect them in a list
318 QList<Activity::Identifier> strayCats;
319 foreach (auto id, _widgetForNotifId.keys()) {
320 NotificationWidget *widget = _widgetForNotifId[id];
321
322 bool found = false;
323 // do not mark widgets of other accounts to delete.
324 if (widget->activity()._accName != listAccountName) {
325 continue;
326 }
327
328 foreach (auto activity, list) {
329 if (activity.ident() == id) {
330 // found an activity
331 found = true;
332 break;
333 }
334 }
335 if (!found) {
336 // the activity does not exist any more.
337 strayCats.append(id);
338 }
339 }
340
341 // .. and now delete all these stray cat widgets.
342 foreach (auto strayCatId, strayCats) {
343 NotificationWidget *widgetToGo = _widgetForNotifId[strayCatId];
344 scheduleWidgetToRemove(widgetToGo, 0);
345 }
346
347 checkActivityTabVisibility();
348
349 const int newGuiLogCount = accNotified.count();
350
351 if (newGuiLogCount > 0) {
352 // restart the gui log timer now that we show a notification
353 _guiLogTimer.start();
354
355 // Assemble a tray notification
356 QString msg;
357 if (newGuiLogCount == 1) {
358 msg = tr("%n notifications(s) for %1.", "", accNotified.begin().value()).arg(accNotified.begin().key());
359 } else if (newGuiLogCount >= 2) {
360 const auto acc1 = accNotified.begin();
361 const auto acc2 = acc1 + 1;
362 if (newGuiLogCount == 2) {
363 const int notiCount = acc1.value() + acc2.value();
364 msg = tr("%n notifications(s) for %1 and %2.", "", notiCount).arg(acc1.key(), acc2.key());
365 } else {
366 msg = tr("New notifications for %1, %2 and other accounts.").arg(acc1.key(), acc2.key());
367 }
368 }
369 const QString log = tr("Open the activity view for details.");
370 emit guiLog(msg, log);
371 }
372
373 if (newNotificationShown) {
374 emit newNotification();
375 }
376 }
377
slotSendNotificationRequest(const QString & accountName,const QString & link,const QByteArray & verb)378 void ActivityWidget::slotSendNotificationRequest(const QString &accountName, const QString &link, const QByteArray &verb)
379 {
380 qCInfo(lcActivity) << "Server Notification Request " << verb << link << "on account" << accountName;
381 NotificationWidget *theSender = qobject_cast<NotificationWidget *>(sender());
382
383 const QStringList validVerbs = QStringList() << "GET"
384 << "PUT"
385 << "POST"
386 << "DELETE";
387
388 if (validVerbs.contains(verb)) {
389 AccountStatePtr acc = AccountManager::instance()->account(accountName);
390 if (acc) {
391 NotificationConfirmJob *job = new NotificationConfirmJob(acc->account());
392 QUrl l(link);
393 job->setLinkAndVerb(l, verb);
394 job->setWidget(theSender);
395 connect(job, &AbstractNetworkJob::networkError,
396 this, &ActivityWidget::slotNotifyNetworkError);
397 connect(job, &NotificationConfirmJob::jobFinished,
398 this, &ActivityWidget::slotNotifyServerFinished);
399 job->start();
400
401 // count the number of running notification requests. If this member var
402 // is larger than zero, no new fetching of notifications is started
403 _notificationRequestsRunning++;
404 }
405 } else {
406 qCWarning(lcActivity) << "Notification Links: Invalid verb:" << verb;
407 }
408 }
409
endNotificationRequest(NotificationWidget * widget,int replyCode)410 void ActivityWidget::endNotificationRequest(NotificationWidget *widget, int replyCode)
411 {
412 _notificationRequestsRunning--;
413 if (widget) {
414 widget->slotNotificationRequestFinished(replyCode);
415 }
416 }
417
slotNotifyNetworkError(QNetworkReply * reply)418 void ActivityWidget::slotNotifyNetworkError(QNetworkReply *reply)
419 {
420 NotificationConfirmJob *job = qobject_cast<NotificationConfirmJob *>(sender());
421 if (!job) {
422 return;
423 }
424
425 int resultCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
426
427 endNotificationRequest(job->widget(), resultCode);
428 qCWarning(lcActivity) << "Server notify job failed with code " << resultCode;
429 }
430
slotNotifyServerFinished(const QString & reply,int replyCode)431 void ActivityWidget::slotNotifyServerFinished(const QString &reply, int replyCode)
432 {
433 NotificationConfirmJob *job = qobject_cast<NotificationConfirmJob *>(sender());
434 if (!job) {
435 return;
436 }
437
438 endNotificationRequest(job->widget(), replyCode);
439 qCInfo(lcActivity) << "Server Notification reply code" << replyCode << reply;
440
441 // if the notification was successful start a timer that triggers
442 // removal of the done widgets in a few seconds
443 // Add 200 millisecs to the predefined value to make sure that the timer in
444 // widget's method readyToClose() has elapsed.
445 if (replyCode == OCS_SUCCESS_STATUS_CODE || replyCode == OCS_SUCCESS_STATUS_CODE_V2) {
446 scheduleWidgetToRemove(job->widget());
447 }
448 }
449
450 // blacklist the activity coming in here.
slotRequestCleanupAndBlacklist(const Activity & blacklistActivity)451 void ActivityWidget::slotRequestCleanupAndBlacklist(const Activity &blacklistActivity)
452 {
453 if (!_blacklistedNotifications.contains(blacklistActivity)) {
454 _blacklistedNotifications.append(blacklistActivity);
455 }
456
457 NotificationWidget *widget = _widgetForNotifId[blacklistActivity.ident()];
458 scheduleWidgetToRemove(widget);
459 }
460
scheduleWidgetToRemove(NotificationWidget * widget,int milliseconds)461 void ActivityWidget::scheduleWidgetToRemove(NotificationWidget *widget, int milliseconds)
462 {
463 if (!widget) {
464 return;
465 }
466 // in five seconds from now, remove the widget.
467 QDateTime removeTime = QDateTime::currentDateTimeUtc().addMSecs(milliseconds);
468 QDateTime &it = _widgetsToRemove[widget];
469 if (!it.isValid() || it > removeTime) {
470 it = removeTime;
471 }
472 if (!_removeTimer.isActive()) {
473 _removeTimer.start();
474 }
475 }
476
477 // Called every second to see if widgets need to be removed.
slotCheckToCleanWidgets()478 void ActivityWidget::slotCheckToCleanWidgets()
479 {
480 auto currentTime = QDateTime::currentDateTimeUtc();
481 auto it = _widgetsToRemove.begin();
482 while (it != _widgetsToRemove.end()) {
483 // loop over all widgets in the to-remove queue
484 QDateTime t = it.value();
485 NotificationWidget *widget = it.key();
486
487 if (currentTime > t) {
488 // found one to remove!
489 Activity::Identifier id = widget->activity().ident();
490 _widgetForNotifId.remove(id);
491 widget->deleteLater();
492 it = _widgetsToRemove.erase(it);
493 } else {
494 ++it;
495 }
496 }
497
498 if (_widgetsToRemove.isEmpty()) {
499 _removeTimer.stop();
500 }
501
502 // check to see if the whole notification pane should be hidden
503 if (_widgetForNotifId.isEmpty()) {
504 _ui->_notifyLabel->setHidden(true);
505 _ui->_notifyScroll->setHidden(true);
506 }
507 }
508
509
510 /* ==================================================================== */
511
ActivitySettings(QWidget * parent)512 ActivitySettings::ActivitySettings(QWidget *parent)
513 : QWidget(parent)
514 {
515 QHBoxLayout *hbox = new QHBoxLayout(this);
516 setLayout(hbox);
517
518 // create a tab widget for the three activity views
519 _tab = new QTabWidget(this);
520 hbox->addWidget(_tab);
521 _activityWidget = new ActivityWidget(this);
522 _activityTabId = _tab->addTab(_activityWidget, Theme::instance()->applicationIcon(), tr("Server Activity"));
523 connect(_activityWidget, &ActivityWidget::copyToClipboard, this, &ActivitySettings::slotCopyToClipboard);
524 connect(_activityWidget, &ActivityWidget::hideActivityTab, this, &ActivitySettings::setActivityTabHidden);
525 connect(_activityWidget, &ActivityWidget::guiLog, this, &ActivitySettings::guiLog);
526 connect(_activityWidget, &ActivityWidget::newNotification, this, &ActivitySettings::slotShowActivityTab);
527
528 _protocolWidget = new ProtocolWidget(this);
529 _protocolTabId = _tab->addTab(_protocolWidget, Theme::instance()->syncStateIcon(SyncResult::Success), tr("Sync Protocol"));
530 connect(_protocolWidget, &ProtocolWidget::copyToClipboard, this, &ActivitySettings::slotCopyToClipboard);
531
532 _issuesWidget = new IssuesWidget(this);
533 _syncIssueTabId = _tab->addTab(_issuesWidget, Theme::instance()->syncStateIcon(SyncResult::Problem), QString());
534 slotShowIssueItemCount(0); // to display the label.
535 connect(_issuesWidget, &IssuesWidget::issueCountUpdated,
536 this, &ActivitySettings::slotShowIssueItemCount);
537 connect(_issuesWidget, &IssuesWidget::copyToClipboard,
538 this, &ActivitySettings::slotCopyToClipboard);
539
540 // Add a progress indicator to spin if the acitivity list is updated.
541 _progressIndicator = new QProgressIndicator(this);
542 _tab->setCornerWidget(_progressIndicator);
543
544 connect(&_notificationCheckTimer, &QTimer::timeout,
545 this, &ActivitySettings::slotRegularNotificationCheck);
546
547 // connect a model signal to stop the animation.
548 connect(_activityWidget, &ActivityWidget::rowsInserted, _progressIndicator, &QProgressIndicator::stopAnimation);
549
550 // We want the protocol be the default
551 _tab->setCurrentIndex(1);
552 }
553
setNotificationRefreshInterval(std::chrono::milliseconds interval)554 void ActivitySettings::setNotificationRefreshInterval(std::chrono::milliseconds interval)
555 {
556 qCDebug(lcActivity) << "Starting Notification refresh timer with " << interval.count() / 1000 << " sec interval";
557 _notificationCheckTimer.start(interval.count());
558 }
559
setActivityTabHidden(bool hidden)560 void ActivitySettings::setActivityTabHidden(bool hidden)
561 {
562 if (hidden && _activityTabId > -1) {
563 _tab->removeTab(_activityTabId);
564 _activityTabId = -1;
565 _protocolTabId -= 1;
566 _syncIssueTabId -= 1;
567 }
568
569 if (!hidden && _activityTabId == -1) {
570 _activityTabId = _tab->insertTab(0, _activityWidget, Theme::instance()->applicationIcon(), tr("Server Activity"));
571 _protocolTabId += 1;
572 _syncIssueTabId += 1;
573 }
574 }
575
slotShowIssueItemCount(int cnt)576 void ActivitySettings::slotShowIssueItemCount(int cnt)
577 {
578 QString cntText = tr("Not Synced");
579 if (cnt) {
580 //: %1 is the number of not synced files.
581 cntText = tr("Not Synced (%1)").arg(cnt);
582 }
583 _tab->setTabText(_syncIssueTabId, cntText);
584 }
585
slotShowActivityTab()586 void ActivitySettings::slotShowActivityTab()
587 {
588 if (_activityTabId != -1) {
589 _tab->setCurrentIndex(_activityTabId);
590 }
591 }
592
slotShowIssuesTab(const QString & folderAlias)593 void ActivitySettings::slotShowIssuesTab(const QString &folderAlias)
594 {
595 if (_syncIssueTabId == -1)
596 return;
597 _tab->setCurrentIndex(_syncIssueTabId);
598
599 _issuesWidget->showFolderErrors(folderAlias);
600 }
601
slotCopyToClipboard()602 void ActivitySettings::slotCopyToClipboard()
603 {
604 QString text;
605 QTextStream ts(&text);
606
607 int idx = _tab->currentIndex();
608 QString message;
609
610 if (idx == _activityTabId) {
611 // the activity widget
612 _activityWidget->storeActivityList(ts);
613 message = tr("The server activity list has been copied to the clipboard.");
614 } else if (idx == _protocolTabId) {
615 // the protocol widget
616 _protocolWidget->storeSyncActivity(ts);
617 message = tr("The sync activity list has been copied to the clipboard.");
618 } else if (idx == _syncIssueTabId) {
619 // issues Widget
620 message = tr("The list of unsynced items has been copied to the clipboard.");
621 _issuesWidget->storeSyncIssues(ts);
622 }
623
624 QApplication::clipboard()->setText(text);
625 emit guiLog(tr("Copied to clipboard"), message);
626 }
627
slotRemoveAccount(AccountState * ptr)628 void ActivitySettings::slotRemoveAccount(AccountState *ptr)
629 {
630 _activityWidget->slotRemoveAccount(ptr);
631 }
632
slotRefresh(AccountState * ptr)633 void ActivitySettings::slotRefresh(AccountState *ptr)
634 {
635 // QElapsedTimer isn't actually constructed as invalid.
636 if (!_timeSinceLastCheck.contains(ptr)) {
637 _timeSinceLastCheck[ptr].invalidate();
638 }
639 QElapsedTimer &timer = _timeSinceLastCheck[ptr];
640
641 // Fetch Activities only if visible and if last check is longer than 15 secs ago
642 if (timer.isValid() && timer.elapsed() < NOTIFICATION_REQUEST_FREE_PERIOD) {
643 qCDebug(lcActivity) << "Do not check as last check is only secs ago: " << timer.elapsed() / 1000;
644 return;
645 }
646 if (ptr && ptr->isConnected()) {
647 if (isVisible() || !timer.isValid()) {
648 _progressIndicator->startAnimation();
649 _activityWidget->slotRefreshActivities(ptr);
650 }
651 _activityWidget->slotRefreshNotifications(ptr);
652 timer.start();
653 }
654 }
655
slotRegularNotificationCheck()656 void ActivitySettings::slotRegularNotificationCheck()
657 {
658 AccountManager *am = AccountManager::instance();
659 foreach (AccountStatePtr a, am->accounts()) {
660 slotRefresh(a.data());
661 }
662 }
663
event(QEvent * e)664 bool ActivitySettings::event(QEvent *e)
665 {
666 if (e->type() == QEvent::Show) {
667 slotRegularNotificationCheck();
668 }
669 return QWidget::event(e);
670 }
671
~ActivitySettings()672 ActivitySettings::~ActivitySettings()
673 {
674 }
675 }
676