+SystemTray::SystemTray(QWidget *parent)
+ : QObject(parent),
+ _associatedWidget(parent)
+{
+ Q_ASSERT(parent);
+
+ NotificationSettings{}.initAndNotify("Systray/ChangeColor", this, SLOT(enableChangeColorChanged(QVariant)), true);
+ NotificationSettings{}.initAndNotify("Systray/Animate", this, SLOT(enableBlinkChanged(QVariant)), false);
+ UiStyleSettings{}.initAndNotify("Icons/InvertTray", this, SLOT(invertTrayIconChanged(QVariant)), false);
+
+ ActionCollection *coll = QtUi::actionCollection("General");
+ _minimizeRestoreAction = new Action(tr("&Minimize"), this, this, &SystemTray::minimizeRestore);
+
+ _trayMenu = new QMenu(associatedWidget());
+ _trayMenu->setTitle("Quassel IRC");
+ _trayMenu->setAttribute(Qt::WA_Hover);
+
+ _trayMenu->addAction(coll->action("ConnectCore"));
+ _trayMenu->addAction(coll->action("DisconnectCore"));
+ _trayMenu->addAction(coll->action("CoreInfo"));
+ _trayMenu->addSeparator();
+ _trayMenu->addAction(_minimizeRestoreAction);
+ _trayMenu->addAction(coll->action("Quit"));
+ connect(_trayMenu, &QMenu::aboutToShow, this, &SystemTray::trayMenuAboutToShow);
+
+ connect(QtUi::instance(), &QtUi::iconThemeRefreshed, this, &SystemTray::iconsChanged);
+
+ _blinkTimer.setInterval(1000);
+ _blinkTimer.setSingleShot(false);
+ connect(&_blinkTimer, &QTimer::timeout, this, &SystemTray::onBlinkTimeout);
+}
+
+
+SystemTray::~SystemTray()
+{
+ _trayMenu->deleteLater();
+}
+
+
+QWidget *SystemTray::associatedWidget() const
+{
+ return _associatedWidget;
+}
+
+
+bool SystemTray::isSystemTrayAvailable() const
+{
+ return false;
+}
+
+
+bool SystemTray::isVisible() const
+{
+ return _isVisible;
+}
+
+
+void SystemTray::setVisible(bool visible)
+{
+ if (visible != _isVisible) {
+ _isVisible = visible;
+ emit visibilityChanged(visible);
+ }
+}
+
+
+SystemTray::Mode SystemTray::mode() const
+{
+ return _mode;
+}
+
+
+void SystemTray::setMode(Mode mode)
+{
+ if (mode != _mode) {
+ _mode = mode;
+ emit modeChanged(mode);
+ }
+}
+
+
+SystemTray::State SystemTray::state() const
+{
+ return _state;
+}
+
+
+void SystemTray::setState(State state)
+{
+ if (_state != state) {
+ _state = state;
+ emit stateChanged(state);
+
+ if (state == NeedsAttention && _attentionBehavior == AttentionBehavior::Blink) {
+ _blinkTimer.start();
+ _blinkState = true;
+ }
+ else {
+ _blinkTimer.stop();
+ _blinkState = false;
+ }
+ emit currentIconNameChanged();
+ }
+}
+
+
+QString SystemTray::iconName(State state) const
+{
+ QString name;
+ switch (state) {
+ case State::Passive:
+ name = "inactive-quassel-tray";
+ break;
+ case State::Active:
+ name = "active-quassel-tray";
+ break;
+ case State::NeedsAttention:
+ name = "message-quassel-tray";
+ break;
+ }
+
+ if (_trayIconInverted) {
+ name += "-inverted";
+ }
+
+ return name;
+}
+
+
+QString SystemTray::currentIconName() const
+{
+ if (state() == State::NeedsAttention) {
+ if (_attentionBehavior == AttentionBehavior::ChangeColor) {
+ return iconName(State::NeedsAttention);
+ }
+ if (_attentionBehavior == AttentionBehavior::Blink && _blinkState) {
+ return iconName(State::NeedsAttention);
+ }
+ return iconName(State::Active);
+ }
+ else {
+ return iconName(state());
+ }
+}
+
+
+QString SystemTray::currentAttentionIconName() const
+{
+ if (state() == State::NeedsAttention && _attentionBehavior == AttentionBehavior::Blink && !_blinkState) {
+ return iconName(State::Active);
+ }
+ return iconName(State::NeedsAttention);
+}
+
+
+bool SystemTray::isAlerted() const
+{
+ return state() == State::NeedsAttention;
+}
+
+
+void SystemTray::setAlert(bool alerted)
+{
+ if (alerted) {
+ setState(NeedsAttention);
+ }
+ else {
+ setState(Client::isConnected() ? Active : Passive);
+ }
+}
+
+
+void SystemTray::onBlinkTimeout()