Improve systray notifications
authorManuel Nickschas <sputnick@quassel-irc.org>
Wed, 1 Apr 2009 10:03:47 +0000 (12:03 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 1 Apr 2009 10:06:42 +0000 (12:06 +0200)
* Add an action button to KDE's notification bubble, as it doesn't report
  clicks other than action triggers
* Bring Quassel to front on click (thanks Zarin for pointing out how to bypass focus
  stealing prevention)
* Select buffer where the highlight occurred on click

Note: Plasma notifications are mostly broken currently at least for me; YMMV. If it doesn't work for
you, try using old-fashioned notifications in KDE and see if it works there.

src/qtui/knotificationbackend.cpp
src/qtui/knotificationbackend.h
src/qtui/qtui.cpp
src/qtui/qtui.h
src/qtui/systraynotificationbackend.cpp
src/qtui/systraynotificationbackend.h
src/uisupport/abstractnotificationbackend.h

index 64bdfdc..fda674d 100644 (file)
@@ -41,7 +41,11 @@ void KNotificationBackend::notify(const Notification &n) {
   QString message = QString("<b>&lt;%1&gt;</b> %2").arg(n.sender, n.message);
   KNotification *notification = KNotification::event("Highlight", message, DesktopIcon("dialog-information"), QtUi::mainWindow(),
                                 KNotification::Persistent|KNotification::RaiseWidgetOnActivation|KNotification::CloseWhenWidgetActivated);
-  connect(notification, SIGNAL(activated()), SLOT(notificationActivated()));
+  connect(notification, SIGNAL(activated(uint)), SLOT(notificationActivated()));
+  connect(notification, SIGNAL(closed()), SLOT(notificationClosed()));
+  notification->setActions(QStringList("View"));
+  _notificationIds[notification] = n.notificationId;
+
   QtUi::mainWindow()->systemTray()->setAlert(true);
 }
 
@@ -51,7 +55,18 @@ void KNotificationBackend::close(uint notificationId) {
 }
 
 void KNotificationBackend::notificationActivated() {
-  emit activated();
+  uint id = 0;
+  KNotification *n = qobject_cast<KNotification *>(sender());
+  if(n && _notificationIds.contains(n))
+    id = _notificationIds.value(n);
+
+  emit activated(id);
+}
+
+void KNotificationBackend::notificationClosed() {
+  KNotification *n = qobject_cast<KNotification *>(sender());
+  if(n && _notificationIds.contains(n))
+    _notificationIds.remove(n);
 }
 
 SettingsPage *KNotificationBackend::createConfigWidget() const {
index ca0585c..04723d3 100644 (file)
@@ -39,9 +39,12 @@ public:
 
 private slots:
   void notificationActivated();
+  void notificationClosed();
 
 private:
   class ConfigWidget;
+
+  QHash<KNotification *, uint> _notificationIds;
 };
 
 class KNotificationBackend::ConfigWidget : public SettingsPage {
index 2efdf72..4623142 100644 (file)
@@ -21,6 +21,7 @@
 #include "qtui.h"
 
 #include "abstractnotificationbackend.h"
+#include "buffermodel.h"
 #include "chatlinemodel.h"
 #include "contextmenuactionprovider.h"
 #include "mainwin.h"
 #include "types.h"
 #include "util.h"
 
+#ifdef Q_WS_X11
+#  include <QX11Info>
+#endif
+
 QPointer<QtUi> QtUi::_instance = 0;
 QPointer<MainWin> QtUi::_mainWin = 0;
 QList<AbstractNotificationBackend *> QtUi::_notificationBackends;
@@ -88,7 +93,7 @@ void QtUi::disconnectedFromCore() {
 void QtUi::registerNotificationBackend(AbstractNotificationBackend *backend) {
   if(!_notificationBackends.contains(backend)) {
     _notificationBackends.append(backend);
-    instance()->connect(backend, SIGNAL(activated()), SLOT(notificationActivated()));
+    instance()->connect(backend, SIGNAL(activated(uint)), SLOT(notificationActivated(uint)));
   }
 }
 
@@ -145,8 +150,30 @@ const QList<AbstractNotificationBackend::Notification> &QtUi::activeNotification
   return _notifications;
 }
 
-void QtUi::notificationActivated() {
-  // this might not work with some window managers
+void QtUi::notificationActivated(uint notificationId) {
+  if(notificationId != 0) {
+    QList<AbstractNotificationBackend::Notification>::iterator i = _notifications.begin();
+    while(i != _notifications.end()) {
+      if((*i).notificationId == notificationId) {
+        BufferId bufId = (*i).bufferId;
+        if(bufId.isValid())
+          Client::bufferModel()->switchToBuffer(bufId);
+        _notifications.erase(i);
+        break;
+      }
+    }
+  }
+
+#ifdef Q_WS_X11
+  // Bypass focus stealing prevention
+  QX11Info::setAppUserTime(QX11Info::appTime());
+#endif
+
+  if(_mainWin->windowState() & Qt::WindowMinimized) {
+    // restore
+    _mainWin->setWindowState((_mainWin->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
+    _mainWin->show();
+  }
   _mainWin->raise();
   _mainWin->activateWindow();
 }
index 1e2144c..5885210 100644 (file)
@@ -67,7 +67,7 @@ public slots:
 protected slots:
   void connectedToCore();
   void disconnectedFromCore();
-  void notificationActivated();
+  void notificationActivated(uint notificationId);
 
 private:
   static QPointer<QtUi> _instance;
index 3d9d74b..6b67b20 100644 (file)
@@ -31,7 +31,7 @@
 #include "systemtray.h"
 
 SystrayNotificationBackend::SystrayNotificationBackend(QObject *parent)
-  : AbstractNotificationBackend(parent)
+  : AbstractNotificationBackend(parent), _activeId(0)
 {
   NotificationSettings notificationSettings;
   _showBubble = notificationSettings.value("Systray/ShowBubble", true).toBool();
@@ -40,7 +40,7 @@ SystrayNotificationBackend::SystrayNotificationBackend(QObject *parent)
   notificationSettings.notify("Systray/ShowBubble", this, SLOT(showBubbleChanged(const QVariant &)));
   notificationSettings.notify("Systray/Animate", this, SLOT(animateChanged(const QVariant &)));
 
-  connect(QtUi::mainWindow()->systemTray(), SIGNAL(messageClicked()), this, SIGNAL(activated()));
+  connect(QtUi::mainWindow()->systemTray(), SIGNAL(messageClicked()), SLOT(notificationActivated()));
 }
 
 void SystrayNotificationBackend::notify(const Notification &notification) {
@@ -76,6 +76,7 @@ void SystrayNotificationBackend::showBubble() {
   // for now, we just show the last message
   if(_notifications.isEmpty()) return;
   Notification n = _notifications.takeLast();
+  _activeId = n.notificationId;
   QString title = Client::networkModel()->networkName(n.bufferId) + " - " + Client::networkModel()->bufferName(n.bufferId);
   QString message = QString("<%1> %2").arg(n.sender, n.message);
   QtUi::mainWindow()->systemTray()->showMessage(title, message);
@@ -88,6 +89,10 @@ void SystrayNotificationBackend::closeBubble() {
 #endif
 }
 
+void SystrayNotificationBackend::notificationActivated() {
+  emit activated(_activeId);
+}
+
 void SystrayNotificationBackend::showBubbleChanged(const QVariant &v) {
   _showBubble = v.toBool();
 }
index 2a7784b..f4e2c6e 100644 (file)
@@ -40,6 +40,7 @@ public:
 private slots:
   void showBubble();
   void closeBubble();
+  void notificationActivated();
 
   void animateChanged(const QVariant &);
   void showBubbleChanged(const QVariant &);
@@ -50,6 +51,7 @@ private:
   bool _showBubble;
   bool _animate;
   QList<Notification> _notifications;
+  uint _activeId;
 };
 
 class SystrayNotificationBackend::ConfigWidget : public SettingsPage {
index 7882a21..01324d4 100644 (file)
@@ -57,7 +57,7 @@ public:
 
 signals:
   //! May be emitted by the notification to tell the MainWin to raise itself
-  void activated();
+  void activated(uint notificationId = 0);
 
 };