c85e7bf22df7c4f1b8ed3a7e47da1b24ac441497
[quassel.git] / src / qtui / systemtray.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2018 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, SLOT(enableChangeColorChanged(QVariant)), true);
39     NotificationSettings{}.initAndNotify("Systray/Animate", this, SLOT(enableBlinkChanged(QVariant)), false);
40     UiStyleSettings{}.initAndNotify("Icons/InvertTray", this, SLOT(invertTrayIconChanged(QVariant)), 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
65 SystemTray::~SystemTray()
66 {
67     _trayMenu->deleteLater();
68 }
69
70
71 QWidget *SystemTray::associatedWidget() const
72 {
73     return _associatedWidget;
74 }
75
76
77 bool SystemTray::isSystemTrayAvailable() const
78 {
79     return false;
80 }
81
82
83 bool SystemTray::isVisible() const
84 {
85     return _isVisible;
86 }
87
88
89 void SystemTray::setVisible(bool visible)
90 {
91     if (visible != _isVisible) {
92         _isVisible = visible;
93         emit visibilityChanged(visible);
94     }
95 }
96
97
98 SystemTray::Mode SystemTray::mode() const
99 {
100     return _mode;
101 }
102
103
104 void SystemTray::setMode(Mode mode)
105 {
106     if (mode != _mode) {
107         _mode = mode;
108         emit modeChanged(mode);
109     }
110 }
111
112
113 SystemTray::State SystemTray::state() const
114 {
115     return _state;
116 }
117
118
119 void SystemTray::setState(State state)
120 {
121     if (_state != state) {
122         _state = state;
123         emit stateChanged(state);
124
125         if (state == NeedsAttention && _attentionBehavior == AttentionBehavior::Blink) {
126             _blinkTimer.start();
127             _blinkState = true;
128         }
129         else {
130             _blinkTimer.stop();
131             _blinkState = false;
132         }
133         emit currentIconNameChanged();
134     }
135 }
136
137
138 QString SystemTray::iconName(State state) const
139 {
140     QString name;
141     switch (state) {
142     case State::Passive:
143         name = "inactive-quassel-tray";
144         break;
145     case State::Active:
146         name = "active-quassel-tray";
147         break;
148     case State::NeedsAttention:
149         name = "message-quassel-tray";
150         break;
151     }
152
153     if (_trayIconInverted) {
154         name += "-inverted";
155     }
156
157     return name;
158 }
159
160
161 QString SystemTray::currentIconName() const
162 {
163     if (state() == State::NeedsAttention) {
164         if (_attentionBehavior == AttentionBehavior::ChangeColor) {
165             return iconName(State::NeedsAttention);
166         }
167         if (_attentionBehavior == AttentionBehavior::Blink && _blinkState) {
168             return iconName(State::NeedsAttention);
169         }
170         return iconName(State::Active);
171     }
172     else {
173         return iconName(state());
174     }
175 }
176
177
178 QString SystemTray::currentAttentionIconName() const
179 {
180     if (state() == State::NeedsAttention && _attentionBehavior == AttentionBehavior::Blink && !_blinkState) {
181         return iconName(State::Active);
182     }
183     return iconName(State::NeedsAttention);
184 }
185
186
187 bool SystemTray::isAlerted() const
188 {
189     return state() == State::NeedsAttention;
190 }
191
192
193 void SystemTray::setAlert(bool alerted)
194 {
195     if (alerted) {
196         setState(NeedsAttention);
197     }
198     else {
199         setState(Client::isConnected() ? Active : Passive);
200     }
201 }
202
203
204 void SystemTray::onBlinkTimeout()
205 {
206     _blinkState = !_blinkState;
207     emit currentIconNameChanged();
208 }
209
210
211 QMenu *SystemTray::trayMenu() const
212 {
213     return _trayMenu;
214 }
215
216
217 void SystemTray::trayMenuAboutToShow()
218 {
219     if (GraphicalUi::isMainWidgetVisible())
220         _minimizeRestoreAction->setText(tr("&Minimize"));
221     else
222         _minimizeRestoreAction->setText(tr("&Restore"));
223 }
224
225
226 void SystemTray::enableChangeColorChanged(const QVariant &v)
227 {
228     if (v.toBool()) {
229         _attentionBehavior = AttentionBehavior::ChangeColor;
230     }
231     else {
232         if (_attentionBehavior == AttentionBehavior::ChangeColor) {
233             _attentionBehavior = AttentionBehavior::DoNothing;
234         }
235     }
236     emit currentIconNameChanged();
237 }
238
239
240 void SystemTray::enableBlinkChanged(const QVariant &v)
241 {
242     if (v.toBool()) {
243         _attentionBehavior = AttentionBehavior::Blink;
244     }
245     else {
246         if (_attentionBehavior == AttentionBehavior::Blink) {
247             _attentionBehavior = AttentionBehavior::DoNothing;
248         }
249     }
250     emit currentIconNameChanged();
251 }
252
253
254 void SystemTray::invertTrayIconChanged(const QVariant &v)
255 {
256     _trayIconInverted = v.toBool();
257     emit iconsChanged();
258 }
259
260
261 QString SystemTray::toolTipTitle() const
262 {
263     return _toolTipTitle;
264 }
265
266
267 QString SystemTray::toolTipSubTitle() const
268 {
269     return _toolTipSubTitle;
270 }
271
272
273 void SystemTray::setToolTip(const QString &title, const QString &subtitle)
274 {
275     _toolTipTitle = title;
276     _toolTipSubTitle = subtitle;
277     emit toolTipChanged(title, subtitle);
278 }
279
280
281 void SystemTray::showMessage(const QString &title, const QString &message, MessageIcon icon, int millisecondsTimeoutHint, uint id)
282 {
283     Q_UNUSED(title)
284     Q_UNUSED(message)
285     Q_UNUSED(icon)
286     Q_UNUSED(millisecondsTimeoutHint)
287     Q_UNUSED(id)
288 }
289
290
291 void SystemTray::closeMessage(uint notificationId)
292 {
293     Q_UNUSED(notificationId)
294 }
295
296
297 void SystemTray::activate(SystemTray::ActivationReason reason)
298 {
299     emit activated(reason);
300 }
301
302
303 void SystemTray::minimizeRestore()
304 {
305     GraphicalUi::toggleMainWidget();
306 }