From 39dffd095bb5dbca49199d2173438c7f90c4e6fa Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Wed, 13 Jun 2018 23:47:52 +0200 Subject: [PATCH] qtui: Refactor the system tray implementations Replace the mess of virtual methods and init() and other weird shenanigans by a cleaner architecture. Handle mode/state changes in the base class and let the implementations explicitly act on changes. This should make it much clearer how the implementations behave if mode or state change. Simplify the D-Bus parts of StatusNotifierItem quite a bit by keeping the SNI watcher always alive; no need to kill it when unregistering. Add error handling to the final D-Bus registration call and fall back to the legacy icon if something went wrong. --- src/qtui/legacysystemtray.cpp | 119 ++++++++----------- src/qtui/legacysystemtray.h | 43 +++---- src/qtui/mainwin.cpp | 1 - src/qtui/statusnotifieritem.cpp | 197 +++++++++++++++----------------- src/qtui/statusnotifieritem.h | 21 ++-- src/qtui/systemtray.cpp | 39 +++---- src/qtui/systemtray.h | 21 ++-- 7 files changed, 196 insertions(+), 245 deletions(-) diff --git a/src/qtui/legacysystemtray.cpp b/src/qtui/legacysystemtray.cpp index da27d23d..8e7d2b72 100644 --- a/src/qtui/legacysystemtray.cpp +++ b/src/qtui/legacysystemtray.cpp @@ -20,6 +20,8 @@ #ifndef QT_NO_SYSTEMTRAYICON +#include + #include "legacysystemtray.h" #include "mainwin.h" #include "qtui.h" @@ -39,103 +41,64 @@ LegacySystemTray::LegacySystemTray(QWidget *parent) #endif #ifndef Q_OS_MAC connect(_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), - SLOT(on_activated(QSystemTrayIcon::ActivationReason))); + SLOT(onActivated(QSystemTrayIcon::ActivationReason))); #endif connect(_trayIcon, SIGNAL(messageClicked()), - SLOT(on_messageClicked())); - - _blinkTimer.setInterval(500); - _blinkTimer.setSingleShot(false); - connect(&_blinkTimer, SIGNAL(timeout()), SLOT(on_blinkTimeout())); - - connect(this, SIGNAL(toolTipChanged(QString, QString)), SLOT(syncLegacyIcon())); -} - - -void LegacySystemTray::init() -{ - if (mode() == Invalid) // derived class hasn't set a mode itself - setMode(Legacy); - - SystemTray::init(); + SLOT(onMessageClicked())); _trayIcon->setContextMenu(trayMenu()); -} + _trayIcon->setVisible(false); + setMode(Mode::Legacy); -void LegacySystemTray::syncLegacyIcon() -{ - updateIcon(); + connect(this, SIGNAL(visibilityChanged(bool)), this, SLOT(onVisibilityChanged(bool))); + connect(this, SIGNAL(modeChanged(Mode)), this, SLOT(onModeChanged(Mode))); + connect(this, SIGNAL(stateChanged(State)), this, SLOT(onStateChanged(State))); + connect(this, SIGNAL(toolTipChanged(QString, QString)), SLOT(updateToolTip())); -#if defined Q_OS_MAC || defined Q_OS_WIN - QString tooltip = QString("%1").arg(toolTipTitle()); - if (!toolTipSubTitle().isEmpty()) - tooltip += QString("\n%1").arg(toolTipSubTitle()); -#else - QString tooltip = QString("%1").arg(toolTipTitle()); - if (!toolTipSubTitle().isEmpty()) - tooltip += QString("
%1").arg(toolTipSubTitle()); -#endif + _blinkTimer.setInterval(750); + _blinkTimer.setSingleShot(false); + connect(&_blinkTimer, SIGNAL(timeout()), SLOT(onBlinkTimeout())); - _trayIcon->setToolTip(tooltip); + updateIcon(); + updateToolTip(); } -void LegacySystemTray::setVisible(bool visible) +bool LegacySystemTray::isSystemTrayAvailable() const { - SystemTray::setVisible(visible); - if (mode() == Legacy) { - if (shouldBeVisible()) - _trayIcon->show(); - else - _trayIcon->hide(); - } + return mode() == Mode::Legacy + ? QSystemTrayIcon::isSystemTrayAvailable() + : SystemTray::isSystemTrayAvailable(); } -bool LegacySystemTray::isVisible() const +void LegacySystemTray::onVisibilityChanged(bool isVisible) { if (mode() == Legacy) { - return _trayIcon->isVisible(); + _trayIcon->setVisible(isVisible); } - return SystemTray::isVisible(); } -void LegacySystemTray::setMode(Mode mode_) +void LegacySystemTray::onModeChanged(Mode mode) { - if (mode_ == mode()) - return; - - SystemTray::setMode(mode_); - - if (mode() == Legacy) { - syncLegacyIcon(); - if (shouldBeVisible()) - _trayIcon->show(); - else - _trayIcon->hide(); - if (state() == NeedsAttention) - _blinkTimer.start(); + if (mode == Mode::Legacy) { + _trayIcon->setVisible(isVisible()); } else { _trayIcon->hide(); - _blinkTimer.stop(); } } -void LegacySystemTray::setState(State state_) +void LegacySystemTray::onStateChanged(State state) { - State oldstate = state(); - SystemTray::setState(state_); - if (oldstate != state()) { - if (state() == NeedsAttention && mode() == Legacy && animationEnabled()) - _blinkTimer.start(); - else { - _blinkTimer.stop(); - _blinkState = false; - } + if (state == NeedsAttention && animationEnabled()) + _blinkTimer.start(); + else { + _blinkTimer.stop(); + _blinkState = false; } updateIcon(); } @@ -154,20 +117,36 @@ void LegacySystemTray::updateIcon() } -void LegacySystemTray::on_blinkTimeout() +void LegacySystemTray::updateToolTip() +{ +#if defined Q_OS_MAC || defined Q_OS_WIN + QString tooltip = QString("%1").arg(toolTipTitle()); + if (!toolTipSubTitle().isEmpty()) + tooltip += QString("\n%1").arg(toolTipSubTitle()); +#else + QString tooltip = QString("%1").arg(toolTipTitle()); + if (!toolTipSubTitle().isEmpty()) + tooltip += QString("
%1").arg(toolTipSubTitle()); +#endif + + _trayIcon->setToolTip(tooltip); +} + + +void LegacySystemTray::onBlinkTimeout() { _blinkState = !_blinkState; updateIcon(); } -void LegacySystemTray::on_activated(QSystemTrayIcon::ActivationReason reason) +void LegacySystemTray::onActivated(QSystemTrayIcon::ActivationReason reason) { activate((SystemTray::ActivationReason)reason); } -void LegacySystemTray::on_messageClicked() +void LegacySystemTray::onMessageClicked() { emit messageClicked(_lastMessageId); } diff --git a/src/qtui/legacysystemtray.h b/src/qtui/legacysystemtray.h index c4af3df8..15134b18 100644 --- a/src/qtui/legacysystemtray.h +++ b/src/qtui/legacysystemtray.h @@ -18,11 +18,12 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ -#ifndef LEGACYSYSTEMTRAY_H_ -#define LEGACYSYSTEMTRAY_H_ +#pragma once #ifndef QT_NO_SYSTEMTRAYICON +#include + #ifdef HAVE_KDE4 # include #else @@ -39,32 +40,24 @@ class LegacySystemTray : public SystemTray public: explicit LegacySystemTray(QWidget *parent); - virtual ~LegacySystemTray() {} - virtual void init(); - virtual bool isVisible() const; - virtual inline bool isSystemTrayAvailable() const; + bool isSystemTrayAvailable() const override; public slots: - virtual void setState(State state); - virtual void setVisible(bool visible = true); - virtual void showMessage(const QString &title, const QString &message, MessageIcon icon = Information, int msTimeout = 10000, uint notificationId = 0); - virtual void closeMessage(uint notificationId); + void showMessage(const QString &title, const QString &message, MessageIcon icon = Information, int msTimeout = 10000, uint notificationId = 0) override; + void closeMessage(uint notificationId) override; -protected slots: +private slots: + void onModeChanged(Mode mode); + void onStateChanged(State state); + void onVisibilityChanged(bool isVisible); -protected: - virtual void setMode(Mode mode); + void onBlinkTimeout(); + void onActivated(QSystemTrayIcon::ActivationReason); + void onMessageClicked(); -private: void updateIcon(); - -private slots: - void on_blinkTimeout(); - void on_activated(QSystemTrayIcon::ActivationReason); - void on_messageClicked(); - - void syncLegacyIcon(); + void updateToolTip(); private: QTimer _blinkTimer; @@ -81,13 +74,7 @@ private: // inlines -bool LegacySystemTray::isSystemTrayAvailable() const -{ - return mode() == Legacy ? QSystemTrayIcon::isSystemTrayAvailable() - : SystemTray::isSystemTrayAvailable(); -} -#endif /* QT_NO_SYSTEMTRAYICON */ -#endif /* LEGACYSYSTEMTRAY_H_ */ +#endif /* QT_NO_SYSTEMTRAYICON */ diff --git a/src/qtui/mainwin.cpp b/src/qtui/mainwin.cpp index 39b1f389..07c47a4d 100644 --- a/src/qtui/mainwin.cpp +++ b/src/qtui/mainwin.cpp @@ -1149,7 +1149,6 @@ void MainWin::setupSystray() #else _systemTray = new SystemTray(this); // dummy #endif - _systemTray->init(); } diff --git a/src/qtui/statusnotifieritem.cpp b/src/qtui/statusnotifieritem.cpp index dc33b978..f3b462bc 100644 --- a/src/qtui/statusnotifieritem.cpp +++ b/src/qtui/statusnotifieritem.cpp @@ -35,8 +35,14 @@ #include "statusnotifieritem.h" #include "statusnotifieritemdbus.h" -const int StatusNotifierItem::_protocolVersion = 0; -const QString StatusNotifierItem::_statusNotifierWatcherServiceName("org.kde.StatusNotifierWatcher"); +constexpr int kProtocolVersion {0}; + +const QString kSniWatcherService {QLatin1String{"org.kde.StatusNotifierWatcher"}}; +const QString kSniWatcherPath {QLatin1String{"/StatusNotifierWatcher"}}; +const QString kSniPath {QLatin1String{"/StatusNotifierItem"}}; +const QString kXdgNotificationsService {QLatin1String{"org.freedesktop.Notifications"}}; +const QString kXdgNotificationsPath {QLatin1String{"/org/freedesktop/Notifications"}}; +const QString kMenuObjectPath {QLatin1String{"/MenuBar"}}; #ifdef HAVE_DBUSMENU # include "dbusmenuexporter.h" @@ -67,6 +73,22 @@ StatusNotifierItem::StatusNotifierItem(QWidget *parent) , _iconThemeDir{QDir::tempPath() + QLatin1String{"/quassel-sni-XXXXXX"}} #endif { + static bool registered = []() -> bool { + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + return true; + }(); + Q_UNUSED(registered) + + setMode(Mode::StatusNotifier); + + connect(this, SIGNAL(visibilityChanged(bool)), this, SLOT(onVisibilityChanged(bool))); + connect(this, SIGNAL(modeChanged(Mode)), this, SLOT(onModeChanged(Mode))); + connect(this, SIGNAL(stateChanged(State)), this, SLOT(onStateChanged(State))); + + trayMenu()->installEventFilter(this); + // Create a temporary directory that holds copies of the tray icons. That way, visualizers can find our icons. // For Qt4 the relevant icons are installed in hicolor already, so nothing to be done. #if QT_VERSION >= 0x050000 @@ -74,44 +96,38 @@ StatusNotifierItem::StatusNotifierItem(QWidget *parent) _iconThemePath = _iconThemeDir.path(); } else { - qWarning() << StatusNotifierItem::tr("Could not create temporary directory for themed tray icons: %1").arg(_iconThemeDir.errorString()); + qWarning() << "Could not create temporary directory for themed tray icons!"; } #endif connect(QtUi::instance(), SIGNAL(iconThemeRefreshed()), this, SLOT(refreshIcons())); -} - - -StatusNotifierItem::~StatusNotifierItem() -{ - delete _statusNotifierWatcher; -} - - -void StatusNotifierItem::init() -{ - qDBusRegisterMetaType(); - qDBusRegisterMetaType(); - qDBusRegisterMetaType(); - refreshIcons(); + // Our own SNI service _statusNotifierItemDBus = new StatusNotifierItemDBus(this); - connect(this, SIGNAL(toolTipChanged(QString, QString)), _statusNotifierItemDBus, SIGNAL(NewToolTip())); connect(this, SIGNAL(animationEnabledChanged(bool)), _statusNotifierItemDBus, SIGNAL(NewAttentionIcon())); - QDBusServiceWatcher *watcher = new QDBusServiceWatcher(_statusNotifierWatcherServiceName, - QDBusConnection::sessionBus(), - QDBusServiceWatcher::WatchForOwnerChange, - this); + // Service watcher to keep track of the StatusNotifierWatcher service + QDBusServiceWatcher *watcher = new QDBusServiceWatcher(kSniWatcherService, + QDBusConnection::sessionBus(), + QDBusServiceWatcher::WatchForOwnerChange, + this); connect(watcher, SIGNAL(serviceOwnerChanged(QString, QString, QString)), SLOT(serviceChange(QString, QString, QString))); - setMode(StatusNotifier); - - _notificationsClient = new org::freedesktop::Notifications("org.freedesktop.Notifications", "/org/freedesktop/Notifications", - QDBusConnection::sessionBus(), this); - + // Client instance for StatusNotifierWatcher + _statusNotifierWatcher = new org::kde::StatusNotifierWatcher(kSniWatcherService, + kSniWatcherPath, + QDBusConnection::sessionBus(), + this); + connect(_statusNotifierWatcher, SIGNAL(StatusNotifierHostRegistered()), SLOT(checkForRegisteredHosts())); + connect(_statusNotifierWatcher, SIGNAL(StatusNotifierHostUnregistered()), SLOT(checkForRegisteredHosts())); + + // Client instance for notifications + _notificationsClient = new org::freedesktop::Notifications(kXdgNotificationsService, + kXdgNotificationsPath, + QDBusConnection::sessionBus(), + this); connect(_notificationsClient, SIGNAL(NotificationClosed(uint, uint)), SLOT(notificationClosed(uint, uint))); connect(_notificationsClient, SIGNAL(ActionInvoked(uint, QString)), SLOT(notificationInvoked(uint, QString))); @@ -121,63 +137,57 @@ void StatusNotifierItem::init() _notificationsClientSupportsActions = desktopCapabilities.contains("actions"); } - StatusNotifierItemParent::init(); - trayMenu()->installEventFilter(this); - #ifdef HAVE_DBUSMENU - _menuObjectPath = "/MenuBar"; new QuasselDBusMenuExporter(menuObjectPath(), trayMenu(), _statusNotifierItemDBus->dbusConnection()); // will be added as menu child #endif } -void StatusNotifierItem::registerToDaemon() -{ - if (!_statusNotifierWatcher) { - _statusNotifierWatcher = new org::kde::StatusNotifierWatcher(_statusNotifierWatcherServiceName, - "/StatusNotifierWatcher", - QDBusConnection::sessionBus()); - connect(_statusNotifierWatcher, SIGNAL(StatusNotifierHostRegistered()), SLOT(checkForRegisteredHosts())); - connect(_statusNotifierWatcher, SIGNAL(StatusNotifierHostUnregistered()), SLOT(checkForRegisteredHosts())); - } - if (_statusNotifierWatcher->isValid() - && _statusNotifierWatcher->property("ProtocolVersion").toInt() == _protocolVersion) { - _statusNotifierWatcher->RegisterStatusNotifierItem(_statusNotifierItemDBus->service()); - checkForRegisteredHosts(); - } - else { - //qDebug() << "StatusNotifierWatcher not reachable!"; - setMode(Legacy); - } -} - - void StatusNotifierItem::serviceChange(const QString &name, const QString &oldOwner, const QString &newOwner) { Q_UNUSED(name); if (newOwner.isEmpty()) { //unregistered - //qDebug() << "Connection to the StatusNotifierWatcher lost"; - delete _statusNotifierWatcher; - _statusNotifierWatcher = nullptr; - setMode(Legacy); + setMode(Mode::Legacy); } else if (oldOwner.isEmpty()) { //registered - setMode(StatusNotifier); + setMode(Mode::StatusNotifier); + } +} + + +void StatusNotifierItem::registerToWatcher() +{ + if (_statusNotifierWatcher->isValid() && _statusNotifierWatcher->property("ProtocolVersion").toInt() == kProtocolVersion) { + auto registerMethod = QDBusMessage::createMethodCall(kSniWatcherService, kSniWatcherPath, kSniWatcherService, + QLatin1String{"RegisterStatusNotifierItem"}); + registerMethod.setArguments(QVariantList() << _statusNotifierItemDBus->service()); + _statusNotifierItemDBus->dbusConnection().callWithCallback(registerMethod, this, SLOT(checkForRegisteredHosts()), SLOT(onDBusError(QDBusError))); + } + else { + setMode(Mode::Legacy); } } void StatusNotifierItem::checkForRegisteredHosts() { - if (!_statusNotifierWatcher || !_statusNotifierWatcher->property("IsStatusNotifierHostRegistered").toBool()) - setMode(Legacy); - else - setMode(StatusNotifier); + if (!_statusNotifierWatcher || !_statusNotifierWatcher->property("IsStatusNotifierHostRegistered").toBool()) { + setMode(Mode::Legacy); + } + else { + setMode(Mode::StatusNotifier); + } } +void StatusNotifierItem::onDBusError(const QDBusError &error) +{ + qWarning() << "StatusNotifierItem encountered a D-Bus error:" << error; + setMode(Mode::Legacy); +} + void StatusNotifierItem::refreshIcons() { #if QT_VERSION >= 0x050000 @@ -218,65 +228,44 @@ void StatusNotifierItem::refreshIcons() bool StatusNotifierItem::isSystemTrayAvailable() const { - if (mode() == StatusNotifier) + if (mode() == Mode::StatusNotifier) { return true; // else it should be set to legacy on registration + } return StatusNotifierItemParent::isSystemTrayAvailable(); } -bool StatusNotifierItem::isVisible() const -{ - if (mode() == StatusNotifier) - return shouldBeVisible(); // we don't have a way to check, so we need to trust everything went right - - return StatusNotifierItemParent::isVisible(); -} - - -void StatusNotifierItem::setMode(Mode mode_) +void StatusNotifierItem::onModeChanged(Mode mode) { - if (mode_ == mode()) - return; - - if (mode_ != StatusNotifier) { - _statusNotifierItemDBus->unregisterService(); - } - - StatusNotifierItemParent::setMode(mode_); - - if (mode() == StatusNotifier) { + if (mode == Mode::StatusNotifier) { _statusNotifierItemDBus->registerService(); - registerToDaemon(); + registerToWatcher(); + } + else { + _statusNotifierItemDBus->unregisterService(); } } -void StatusNotifierItem::setState(State state_) +void StatusNotifierItem::onStateChanged(State state) { - StatusNotifierItemParent::setState(state_); - - emit _statusNotifierItemDBus->NewStatus(metaObject()->enumerator(metaObject()->indexOfEnumerator("State")).valueToKey(state())); - emit _statusNotifierItemDBus->NewIcon(); + if (mode() == Mode::StatusNotifier) { + emit _statusNotifierItemDBus->NewIcon(); + emit _statusNotifierItemDBus->NewStatus(metaObject()->enumerator(metaObject()->indexOfEnumerator("State")).valueToKey(state)); + } } -void StatusNotifierItem::setVisible(bool visible) +void StatusNotifierItem::onVisibilityChanged(bool isVisible) { - if (visible == isVisible()) - return; - - LegacySystemTray::setVisible(visible); - - if (mode() == StatusNotifier) { - if (shouldBeVisible()) { + if (mode() == Mode::StatusNotifier) { + if (isVisible) { _statusNotifierItemDBus->registerService(); - registerToDaemon(); + registerToWatcher(); } else { _statusNotifierItemDBus->unregisterService(); - _statusNotifierWatcher->deleteLater(); - _statusNotifierWatcher = 0; } } } @@ -305,7 +294,7 @@ QString StatusNotifierItem::attentionIconName() const return SystemTray::iconName(State::NeedsAttention); } else { - return SystemTray::iconName(State::Active); + return SystemTray::iconName(State::NeedsAttention); } } @@ -324,7 +313,7 @@ QString StatusNotifierItem::iconThemePath() const QString StatusNotifierItem::menuObjectPath() const { - return _menuObjectPath; + return kMenuObjectPath; } @@ -385,13 +374,15 @@ void StatusNotifierItem::showMessage(const QString &title, const QString &messag void StatusNotifierItem::closeMessage(uint notificationId) { - foreach(uint dbusid, _notificationsIdMap.keys()) { + for (auto &&dbusid : _notificationsIdMap.keys()) { if (_notificationsIdMap.value(dbusid) == notificationId) { _notificationsIdMap.remove(dbusid); _notificationsClient->CloseNotification(dbusid); } } _lastNotificationsDBusId = 0; + + StatusNotifierItemParent::closeMessage(notificationId); } diff --git a/src/qtui/statusnotifieritem.h b/src/qtui/statusnotifieritem.h index 9a805be5..8b8eb96f 100644 --- a/src/qtui/statusnotifieritem.h +++ b/src/qtui/statusnotifieritem.h @@ -25,7 +25,9 @@ #ifdef HAVE_DBUS -#include +#include +#include +#include #if QT_VERSION >= 0x050000 # include @@ -50,21 +52,14 @@ class StatusNotifierItem : public StatusNotifierItemParent public: explicit StatusNotifierItem(QWidget *parent); - ~StatusNotifierItem() override; bool isSystemTrayAvailable() const override; - bool isVisible() const override; public slots: - void setState(State state) override; - void setVisible(bool visible) override; void showMessage(const QString &title, const QString &message, MessageIcon icon = Information, int msTimeout = 10000, uint notificationId = 0) override; void closeMessage(uint notificationId) override; protected: - void init() override; - void setMode(Mode mode) override; - QString title() const; QString iconName() const; QString attentionIconName() const; @@ -78,19 +73,21 @@ private slots: void activated(const QPoint &pos); void serviceChange(const QString &name, const QString &oldOwner, const QString &newOwner); void checkForRegisteredHosts(); + void onDBusError(const QDBusError &error); void notificationClosed(uint id, uint reason); void notificationInvoked(uint id, const QString &action); void refreshIcons(); + void onModeChanged(Mode mode); + void onStateChanged(State state); + void onVisibilityChanged(bool isVisible); + private: - void registerToDaemon(); + void registerToWatcher(); - static const int _protocolVersion; - static const QString _statusNotifierWatcherServiceName; StatusNotifierItemDBus *_statusNotifierItemDBus{nullptr}; - org::kde::StatusNotifierWatcher *_statusNotifierWatcher{nullptr}; org::freedesktop::Notifications *_notificationsClient{nullptr}; bool _notificationsClientSupportsMarkup{false}; diff --git a/src/qtui/systemtray.cpp b/src/qtui/systemtray.cpp index 679a4b18..4a68dd64 100644 --- a/src/qtui/systemtray.cpp +++ b/src/qtui/systemtray.cpp @@ -42,17 +42,7 @@ SystemTray::SystemTray(QWidget *parent) NotificationSettings{}.initAndNotify("Systray/Animate", this, SLOT(enableAnimationChanged(QVariant)), true); UiStyleSettings{}.initAndNotify("Icons/InvertTray", this, SLOT(invertTrayIconChanged(QVariant)), false); -} - -SystemTray::~SystemTray() -{ - _trayMenu->deleteLater(); -} - - -void SystemTray::init() -{ ActionCollection *coll = QtUi::actionCollection("General"); _minimizeRestoreAction = new Action(tr("&Minimize"), this, this, SLOT(minimizeRestore())); @@ -81,33 +71,36 @@ void SystemTray::init() } -QWidget *SystemTray::associatedWidget() const +SystemTray::~SystemTray() { - return _associatedWidget; + _trayMenu->deleteLater(); } -bool SystemTray::isSystemTrayAvailable() const +QWidget *SystemTray::associatedWidget() const { - return false; + return _associatedWidget; } -bool SystemTray::isVisible() const +bool SystemTray::isSystemTrayAvailable() const { return false; } -bool SystemTray::shouldBeVisible() const +bool SystemTray::isVisible() const { - return _shouldBeVisible; + return _isVisible; } void SystemTray::setVisible(bool visible) { - _shouldBeVisible = visible; + if (visible != _isVisible) { + _isVisible = visible; + emit visibilityChanged(visible); + } } @@ -117,13 +110,13 @@ SystemTray::Mode SystemTray::mode() const } -void SystemTray::setMode(Mode mode_) +void SystemTray::setMode(Mode mode) { - if (mode_ != _mode) { - _mode = mode_; + if (mode != _mode) { + _mode = mode; #ifdef HAVE_KDE4 if (_trayMenu) { - if (_mode == Legacy) { + if (mode == Mode::Legacy) { _trayMenu->setWindowFlags(Qt::Popup); } else { @@ -131,6 +124,7 @@ void SystemTray::setMode(Mode mode_) } } #endif + emit modeChanged(mode); } } @@ -145,6 +139,7 @@ void SystemTray::setState(State state) { if (_state != state) { _state = state; + emit stateChanged(state); } } diff --git a/src/qtui/systemtray.h b/src/qtui/systemtray.h index 1efdb418..d07edf10 100644 --- a/src/qtui/systemtray.h +++ b/src/qtui/systemtray.h @@ -63,26 +63,30 @@ public: explicit SystemTray(QWidget *parent); ~SystemTray() override; - virtual void init(); Mode mode() const; State state() const; + bool isVisible() const; bool isAlerted() const; - void setAlert(bool alerted); - virtual bool isVisible() const; virtual bool isSystemTrayAvailable() const; QWidget *associatedWidget() const; public slots: - virtual void setState(State); - virtual void setVisible(bool visible = true); - virtual void setToolTip(const QString &title, const QString &subtitle); + void setVisible(bool visible = true); + void setState(State); + void setAlert(bool alerted); + + void setToolTip(const QString &title, const QString &subtitle); virtual void showMessage(const QString &title, const QString &message, MessageIcon icon = Information, int msTimeout = 10000, uint notificationId = 0); virtual void closeMessage(uint notificationId); signals: + void modeChanged(Mode mode); + void stateChanged(State state); + void visibilityChanged(bool isVisible); + void activated(SystemTray::ActivationReason); void iconChanged(const QIcon &icon); void animationEnabledChanged(bool); @@ -94,8 +98,7 @@ protected slots: virtual void activate(SystemTray::ActivationReason = Trigger); protected: - virtual void setMode(Mode mode); - bool shouldBeVisible() const; + void setMode(Mode mode); bool animationEnabled() const; QString toolTipTitle() const; @@ -111,9 +114,9 @@ private slots: void invertTrayIconChanged(const QVariant &); private: + bool _isVisible{false}; Mode _mode{Mode::Invalid}; State _state{State::Passive}; - bool _shouldBeVisible{true}; bool _animationEnabled{true}; bool _trayIconInverted{false}; -- 2.20.1