cmake: avoid de-duplication of user's CXXFLAGS
[quassel.git] / src / qtui / systemtray.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2020 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This file is free software; you can redistribute it and/or modify     *
6  *   it under the terms of the GNU Library General Public License (LGPL)   *
7  *   as published by the Free Software Foundation; either version 2 of the *
8  *   License, or (at your option) any later version.                       *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20
21 #include "systemtray.h"
22
23 #include <QApplication>
24 #include <QMenu>
25
26 #include "action.h"
27 #include "actioncollection.h"
28 #include "client.h"
29 #include "icon.h"
30 #include "qtui.h"
31
32 SystemTray::SystemTray(QWidget* parent)
33     : QObject(parent)
34     , _associatedWidget(parent)
35 {
36     Q_ASSERT(parent);
37
38     NotificationSettings{}.initAndNotify("Systray/ChangeColor", this, &SystemTray::enableChangeColorChanged, true);
39     NotificationSettings{}.initAndNotify("Systray/Animate", this, &SystemTray::enableBlinkChanged, false);
40     UiStyleSettings{}.initAndNotify("Icons/InvertTray", this, &SystemTray::invertTrayIconChanged, false);
41
42     ActionCollection* coll = QtUi::actionCollection("General");
43     _minimizeRestoreAction = new Action(tr("&Minimize"), this, this, &SystemTray::minimizeRestore);
44
45     _trayMenu = new QMenu(associatedWidget());
46     _trayMenu->setTitle("Quassel IRC");
47     _trayMenu->setAttribute(Qt::WA_Hover);
48
49     _trayMenu->addAction(coll->action("ConnectCore"));
50     _trayMenu->addAction(coll->action("DisconnectCore"));
51     _trayMenu->addAction(coll->action("CoreInfo"));
52     _trayMenu->addSeparator();
53     _trayMenu->addAction(_minimizeRestoreAction);
54     _trayMenu->addAction(coll->action("Quit"));
55     connect(_trayMenu, &QMenu::aboutToShow, this, &SystemTray::trayMenuAboutToShow);
56
57     connect(QtUi::instance(), &QtUi::iconThemeRefreshed, this, &SystemTray::iconsChanged);
58
59     _blinkTimer.setInterval(1000);
60     _blinkTimer.setSingleShot(false);
61     connect(&_blinkTimer, &QTimer::timeout, this, &SystemTray::onBlinkTimeout);
62 }
63
64 SystemTray::~SystemTray()
65 {
66     _trayMenu->deleteLater();
67 }
68
69 QWidget* SystemTray::associatedWidget() const
70 {
71     return _associatedWidget;
72 }
73
74 bool SystemTray::isSystemTrayAvailable() const
75 {
76     return false;
77 }
78
79 bool SystemTray::isVisible() const
80 {
81     return _isVisible;
82 }
83
84 void SystemTray::setVisible(bool visible)
85 {
86     if (visible != _isVisible) {
87         _isVisible = visible;
88         emit visibilityChanged(visible);
89     }
90 }
91
92 SystemTray::Mode SystemTray::mode() const
93 {
94     return _mode;
95 }
96
97 void SystemTray::setMode(Mode mode)
98 {
99     if (mode != _mode) {
100         _mode = mode;
101         emit modeChanged(mode);
102     }
103 }
104
105 SystemTray::State SystemTray::state() const
106 {
107     return _state;
108 }
109
110 void SystemTray::setState(State state)
111 {
112     if (_state != state) {
113         _state = state;
114         emit stateChanged(state);
115
116         if (state == NeedsAttention && _attentionBehavior == AttentionBehavior::Blink) {
117             _blinkTimer.start();
118             _blinkState = true;
119         }
120         else {
121             _blinkTimer.stop();
122             _blinkState = false;
123         }
124         emit currentIconNameChanged();
125     }
126 }
127
128 QString SystemTray::iconName(State state) const
129 {
130     QString name;
131     switch (state) {
132     case State::Passive:
133         name = "inactive-quassel-tray";
134         break;
135     case State::Active:
136         name = "active-quassel-tray";
137         break;
138     case State::NeedsAttention:
139         name = "message-quassel-tray";
140         break;
141     }
142
143     if (_trayIconInverted) {
144         name += "-inverted";
145     }
146
147     return name;
148 }
149
150 QString SystemTray::currentIconName() const
151 {
152     if (state() == State::NeedsAttention) {
153         if (_attentionBehavior == AttentionBehavior::ChangeColor) {
154             return iconName(State::NeedsAttention);
155         }
156         if (_attentionBehavior == AttentionBehavior::Blink && _blinkState) {
157             return iconName(State::NeedsAttention);
158         }
159         return iconName(State::Active);
160     }
161     else {
162         return iconName(state());
163     }
164 }
165
166 QString SystemTray::currentAttentionIconName() const
167 {
168     if (state() == State::NeedsAttention && _attentionBehavior == AttentionBehavior::Blink && !_blinkState) {
169         return iconName(State::Active);
170     }
171     return iconName(State::NeedsAttention);
172 }
173
174 bool SystemTray::isAlerted() const
175 {
176     return state() == State::NeedsAttention;
177 }
178
179 void SystemTray::setAlert(bool alerted)
180 {
181     if (alerted) {
182         setState(NeedsAttention);
183     }
184     else {
185         setState(Client::isConnected() ? Active : Passive);
186     }
187 }
188
189 void SystemTray::onBlinkTimeout()
190 {
191     _blinkState = !_blinkState;
192     emit currentIconNameChanged();
193 }
194
195 QMenu* SystemTray::trayMenu() const
196 {
197     return _trayMenu;
198 }
199
200 void SystemTray::trayMenuAboutToShow()
201 {
202     if (GraphicalUi::isMainWidgetVisible())
203         _minimizeRestoreAction->setText(tr("&Minimize"));
204     else
205         _minimizeRestoreAction->setText(tr("&Restore"));
206 }
207
208 void SystemTray::enableChangeColorChanged(const QVariant& v)
209 {
210     if (v.toBool()) {
211         _attentionBehavior = AttentionBehavior::ChangeColor;
212     }
213     else {
214         if (_attentionBehavior == AttentionBehavior::ChangeColor) {
215             _attentionBehavior = AttentionBehavior::DoNothing;
216         }
217     }
218     emit currentIconNameChanged();
219 }
220
221 void SystemTray::enableBlinkChanged(const QVariant& v)
222 {
223     if (v.toBool()) {
224         _attentionBehavior = AttentionBehavior::Blink;
225     }
226     else {
227         if (_attentionBehavior == AttentionBehavior::Blink) {
228             _attentionBehavior = AttentionBehavior::DoNothing;
229         }
230     }
231     emit currentIconNameChanged();
232 }
233
234 void SystemTray::invertTrayIconChanged(const QVariant& v)
235 {
236     _trayIconInverted = v.toBool();
237     emit iconsChanged();
238 }
239
240 QString SystemTray::toolTipTitle() const
241 {
242     return _toolTipTitle;
243 }
244
245 QString SystemTray::toolTipSubTitle() const
246 {
247     return _toolTipSubTitle;
248 }
249
250 void SystemTray::setToolTip(const QString& title, const QString& subtitle)
251 {
252     _toolTipTitle = title;
253     _toolTipSubTitle = subtitle;
254     emit toolTipChanged(title, subtitle);
255 }
256
257 void SystemTray::showMessage(const QString& title, const QString& message, MessageIcon icon, int millisecondsTimeoutHint, uint id)
258 {
259     Q_UNUSED(title)
260     Q_UNUSED(message)
261     Q_UNUSED(icon)
262     Q_UNUSED(millisecondsTimeoutHint)
263     Q_UNUSED(id)
264 }
265
266 void SystemTray::closeMessage(uint notificationId)
267 {
268     Q_UNUSED(notificationId)
269 }
270
271 void SystemTray::activate(SystemTray::ActivationReason reason)
272 {
273     emit activated(reason);
274 }
275
276 void SystemTray::minimizeRestore()
277 {
278     GraphicalUi::toggleMainWidget();
279 }