Introduce SystemTray class to handle the systray icon sanely
authorManuel Nickschas <sputnick@quassel-irc.org>
Sat, 14 Feb 2009 21:38:32 +0000 (22:38 +0100)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sat, 14 Feb 2009 21:41:33 +0000 (22:41 +0100)
This provides a sane API to set the state of the icon without having to bother
with icon files (this is all handled internally now). State progressions are
now animated thanks to Nuno's animation phases, and we have a nice glow effect
on highlight too!

src/qtui/CMakeLists.txt
src/qtui/systemtray.cpp [new file with mode: 0644]
src/qtui/systemtray.h [new file with mode: 0644]

index 492c50a..de9db43 100644 (file)
@@ -43,6 +43,7 @@ set(SOURCES
     sessionsettings.cpp
     settingsdlg.cpp
     settingspagedlg.cpp
+    systemtray.cpp
     systraynotificationbackend.cpp
     taskbarnotificationbackend.cpp
     titlesetter.cpp
@@ -83,6 +84,7 @@ set(MOC_HDRS
     qtuimessageprocessor.h
     settingsdlg.h
     settingspagedlg.h
+    systemtray.h
     systraynotificationbackend.h
     taskbarnotificationbackend.h
     titlesetter.h
diff --git a/src/qtui/systemtray.cpp b/src/qtui/systemtray.cpp
new file mode 100644 (file)
index 0000000..acb68b1
--- /dev/null
@@ -0,0 +1,155 @@
+/***************************************************************************
+*   Copyright (C) 2005-09 by the Quassel Project                          *
+*   devel@quassel-irc.org                                                 *
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) version 3.                                           *
+*                                                                         *
+*   This program is distributed in the hope that it will be useful,       *
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+*   GNU General Public License for more details.                          *
+*                                                                         *
+*   You should have received a copy of the GNU General Public License     *
+*   along with this program; if not, write to the                         *
+*   Free Software Foundation, Inc.,                                       *
+*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+***************************************************************************/
+
+#include <QMenu>
+
+#include "systemtray.h"
+
+#include "actioncollection.h"
+#include "iconloader.h"
+#include "qtui.h"
+#include "qtuisettings.h"
+
+SystemTray::SystemTray(QObject *parent)
+: QObject(parent),
+  _state(Inactive),
+  _alert(false),
+  _currentIdx(0)
+{
+  loadAnimations();
+  _currentIdx = _idxOffEnd;
+  _trayIcon = new QSystemTrayIcon(_phases.at(_currentIdx), this);
+
+  _animationTimer.setInterval(150);
+  _animationTimer.setSingleShot(false);
+  connect(&_animationTimer, SIGNAL(timeout()), SLOT(nextPhase()));
+
+  ActionCollection *coll = QtUi::actionCollection("General");
+  _trayMenu = new QMenu();
+  _trayMenu->addAction(coll->action("ConnectCore"));
+  _trayMenu->addAction(coll->action("DisconnectCore"));
+  _trayMenu->addAction(coll->action("CoreInfo"));
+  _trayMenu->addSeparator();
+  _trayMenu->addAction(coll->action("Quit"));
+
+  _trayIcon->setContextMenu(_trayMenu);
+
+  QtUiSettings s;
+  if(s.value("UseSystemTrayIcon", QVariant(true)).toBool()) {
+    _trayIcon->show();
+  }
+
+  connect(_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), SIGNAL(activated(QSystemTrayIcon::ActivationReason)));
+  connect(_trayIcon, SIGNAL(messageClicked()), SIGNAL(messageClicked()));
+}
+
+SystemTray::~SystemTray() {
+  _trayMenu->deleteLater();
+}
+
+void SystemTray::loadAnimations() {
+// system tray icon size
+#ifdef Q_WS_WIN
+  const int size = 16;
+#elif defined Q_WS_MAC
+  const int size = 128;
+#else
+  const int size = 22;
+#endif
+
+  _phases.clear();
+
+#ifdef HAVE_KDE
+  KIconLoader *loader = KIconLoader::global();
+#else
+  IconLoader *loader = IconLoader::global();
+#endif
+
+  _idxOffStart = 0;
+  QString fadeOffName("quassel_tray-fade-off-%1");
+  for(int i = 2; i <= 10; i++)
+    _phases.append(loader->loadIcon(fadeOffName.arg(i), IconLoader::Panel, size));
+  _idxOffEnd = _idxOnStart = _phases.count() - 1;
+
+  QString fadeOnName("quassel_tray-fade-on-%1");
+  for(int i = 2; i <= 15; i++)
+    _phases.append(loader->loadIcon(fadeOnName.arg(i), IconLoader::Panel, size));
+  _idxOnEnd = _idxAlertStart = _phases.count() - 1;
+
+  QString alertName("quassel_tray-alert-%1");
+  for(int i = 1; i <= 10; i++)
+    _phases.append(loader->loadIcon(alertName.arg(i), IconLoader::Panel, size));
+}
+
+void SystemTray::nextPhase() {
+  if(_currentIdx == _idxOnEnd && !_alert && _state == Inactive)
+    _currentIdx = _idxOffStart; // skip alert phases
+
+  else if(++_currentIdx >= _phases.count()) {
+    if(_alert)
+      _currentIdx = _idxAlertStart;
+    else
+      if(_state == Active)
+        _currentIdx = _idxOnEnd;
+      else
+        _currentIdx = _idxOffStart;
+  }
+
+  _trayIcon->setIcon(_phases.at(_currentIdx));
+
+  if(_alert)
+    return;
+
+  if((_state == Active && _currentIdx == _idxOnEnd) || (_state == Inactive && _currentIdx == _idxOffEnd))
+    _animationTimer.stop();
+}
+
+void SystemTray::setState(State state) {
+  if(_state != state) {
+    _state = state;
+    if(state == Inactive && _alert)
+      _alert = false;
+    if(!_animationTimer.isActive())
+      _animationTimer.start();
+  }
+}
+
+void SystemTray::setAlert(bool alert) {
+  if(_alert != alert) {
+    _alert = alert;
+    if(!_animationTimer.isActive())
+      _animationTimer.start();
+  }
+}
+
+void SystemTray::setIconVisible(bool visible) {
+  if(visible)
+    _trayIcon->show();
+  else
+    _trayIcon->hide();
+}
+
+void SystemTray::setToolTip(const QString &tip) {
+  _trayIcon->setToolTip(tip);
+}
+
+void SystemTray::showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon icon, int millisecondsTimeoutHint) {
+  _trayIcon->showMessage(title, message, icon, millisecondsTimeoutHint);
+}
diff --git a/src/qtui/systemtray.h b/src/qtui/systemtray.h
new file mode 100644 (file)
index 0000000..1e811cd
--- /dev/null
@@ -0,0 +1,81 @@
+/***************************************************************************
+*   Copyright (C) 2005-09 by the Quassel Project                          *
+*   devel@quassel-irc.org                                                 *
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) version 3.                                           *
+*                                                                         *
+*   This program is distributed in the hope that it will be useful,       *
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+*   GNU General Public License for more details.                          *
+*                                                                         *
+*   You should have received a copy of the GNU General Public License     *
+*   along with this program; if not, write to the                         *
+*   Free Software Foundation, Inc.,                                       *
+*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+***************************************************************************/
+
+#ifndef SYSTEMTRAY_H_
+#define SYSTEMTRAY_H_
+
+#include <QSystemTrayIcon>
+#include <QTimer>
+
+#include "icon.h"
+
+class SystemTray : public QObject {
+  Q_OBJECT
+
+public:
+  enum State {
+    Inactive,
+    Active
+  };
+
+  SystemTray(QObject *parent = 0);
+  ~SystemTray();
+
+  inline bool isSystemTrayAvailable() const;
+  Icon icon() const;
+  QString toolTip() const;
+
+public slots:
+  void setState(State);
+  void setAlert(bool alert = true);
+  void setIconVisible(bool visible = true);
+  void setToolTip(const QString &tip);
+  void showMessage(const QString &title, const QString &message,
+                   QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::Information, int millisecondsTimeoutHint = 10000);
+
+
+signals:
+  void activated(QSystemTrayIcon::ActivationReason);
+  void iconChanged(const Icon &);
+  void messageClicked();
+
+private slots:
+  void nextPhase();
+
+private:
+  void loadAnimations();
+
+  QSystemTrayIcon *_trayIcon;
+  QMenu *_trayMenu;
+  State _state;
+  bool _alert;
+
+  int _idxOffStart, _idxOffEnd, _idxOnStart, _idxOnEnd, _idxAlertStart;
+  int _currentIdx;
+  QTimer _animationTimer;
+
+  QList<QPixmap> _phases;
+};
+
+// inlines
+
+bool SystemTray::isSystemTrayAvailable() const { return QSystemTrayIcon::isSystemTrayAvailable(); }
+
+#endif