clang-tidy: Avoid another warning about potential memory leak
[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 #ifdef HAVE_KDE4
27 #  include <KMenu>
28 #  include <KWindowInfo>
29 #  include <KWindowSystem>
30 #endif
31
32 #include "action.h"
33 #include "actioncollection.h"
34 #include "client.h"
35 #include "icon.h"
36 #include "qtui.h"
37
38 SystemTray::SystemTray(QWidget *parent)
39     : QObject(parent),
40     _associatedWidget(parent)
41 {
42     Q_ASSERT(parent);
43
44     NotificationSettings{}.initAndNotify("Systray/ChangeColor", this, SLOT(enableChangeColorChanged(QVariant)), true);
45     NotificationSettings{}.initAndNotify("Systray/Animate", this, SLOT(enableBlinkChanged(QVariant)), false);
46     UiStyleSettings{}.initAndNotify("Icons/InvertTray", this, SLOT(invertTrayIconChanged(QVariant)), false);
47
48     ActionCollection *coll = QtUi::actionCollection("General");
49     _minimizeRestoreAction = new Action(tr("&Minimize"), this, this, SLOT(minimizeRestore()));
50
51 #ifdef HAVE_KDE4
52     KMenu *kmenu;
53     _trayMenu = kmenu = new KMenu();
54     kmenu->addTitle(icon::get(iconName(State::Active)), "Quassel IRC");
55 #else
56     _trayMenu = new QMenu(associatedWidget());
57 #endif
58
59     _trayMenu->setTitle("Quassel IRC");
60
61 #ifndef HAVE_KDE4
62     _trayMenu->setAttribute(Qt::WA_Hover);
63 #endif
64
65     _trayMenu->addAction(coll->action("ConnectCore"));
66     _trayMenu->addAction(coll->action("DisconnectCore"));
67     _trayMenu->addAction(coll->action("CoreInfo"));
68     _trayMenu->addSeparator();
69     _trayMenu->addAction(_minimizeRestoreAction);
70     _trayMenu->addAction(coll->action("Quit"));
71     connect(_trayMenu, SIGNAL(aboutToShow()), SLOT(trayMenuAboutToShow()));
72
73     connect(QtUi::instance(), SIGNAL(iconThemeRefreshed()), this, SIGNAL(iconsChanged()));
74
75     _blinkTimer.setInterval(1000);
76     _blinkTimer.setSingleShot(false);
77     connect(&_blinkTimer, SIGNAL(timeout()), SLOT(onBlinkTimeout()));
78 }
79
80
81 SystemTray::~SystemTray()
82 {
83     _trayMenu->deleteLater();
84 }
85
86
87 QWidget *SystemTray::associatedWidget() const
88 {
89     return _associatedWidget;
90 }
91
92
93 bool SystemTray::isSystemTrayAvailable() const
94 {
95     return false;
96 }
97
98
99 bool SystemTray::isVisible() const
100 {
101     return _isVisible;
102 }
103
104
105 void SystemTray::setVisible(bool visible)
106 {
107     if (visible != _isVisible) {
108         _isVisible = visible;
109         emit visibilityChanged(visible);
110     }
111 }
112
113
114 SystemTray::Mode SystemTray::mode() const
115 {
116     return _mode;
117 }
118
119
120 void SystemTray::setMode(Mode mode)
121 {
122     if (mode != _mode) {
123         _mode = mode;
124 #ifdef HAVE_KDE4
125         if (_trayMenu) {
126             if (mode == Mode::Legacy) {
127                 _trayMenu->setWindowFlags(Qt::Popup);
128             }
129             else {
130                 _trayMenu->setWindowFlags(Qt::Window);
131             }
132         }
133 #endif
134         emit modeChanged(mode);
135     }
136 }
137
138
139 SystemTray::State SystemTray::state() const
140 {
141     return _state;
142 }
143
144
145 void SystemTray::setState(State state)
146 {
147     if (_state != state) {
148         _state = state;
149         emit stateChanged(state);
150
151         if (state == NeedsAttention && _attentionBehavior == AttentionBehavior::Blink) {
152             _blinkTimer.start();
153             _blinkState = true;
154         }
155         else {
156             _blinkTimer.stop();
157             _blinkState = false;
158         }
159         emit currentIconNameChanged();
160     }
161 }
162
163
164 QString SystemTray::iconName(State state) const
165 {
166     QString name;
167     switch (state) {
168     case State::Passive:
169         name = "inactive-quassel-tray";
170         break;
171     case State::Active:
172         name = "active-quassel-tray";
173         break;
174     case State::NeedsAttention:
175         name = "message-quassel-tray";
176         break;
177     }
178
179     if (_trayIconInverted) {
180         name += "-inverted";
181     }
182
183     return name;
184 }
185
186
187 QString SystemTray::currentIconName() const
188 {
189     if (state() == State::NeedsAttention) {
190         if (_attentionBehavior == AttentionBehavior::ChangeColor) {
191             return iconName(State::NeedsAttention);
192         }
193         if (_attentionBehavior == AttentionBehavior::Blink && _blinkState) {
194             return iconName(State::NeedsAttention);
195         }
196         return iconName(State::Active);
197     }
198     else {
199         return iconName(state());
200     }
201 }
202
203
204 QString SystemTray::currentAttentionIconName() const
205 {
206     if (state() == State::NeedsAttention && _attentionBehavior == AttentionBehavior::Blink && !_blinkState) {
207         return iconName(State::Active);
208     }
209     return iconName(State::NeedsAttention);
210 }
211
212
213 bool SystemTray::isAlerted() const
214 {
215     return state() == State::NeedsAttention;
216 }
217
218
219 void SystemTray::setAlert(bool alerted)
220 {
221     if (alerted) {
222         setState(NeedsAttention);
223     }
224     else {
225         setState(Client::isConnected() ? Active : Passive);
226     }
227 }
228
229
230 void SystemTray::onBlinkTimeout()
231 {
232     _blinkState = !_blinkState;
233     emit currentIconNameChanged();
234 }
235
236
237 QMenu *SystemTray::trayMenu() const
238 {
239     return _trayMenu;
240 }
241
242
243 void SystemTray::trayMenuAboutToShow()
244 {
245     if (GraphicalUi::isMainWidgetVisible())
246         _minimizeRestoreAction->setText(tr("&Minimize"));
247     else
248         _minimizeRestoreAction->setText(tr("&Restore"));
249 }
250
251
252 void SystemTray::enableChangeColorChanged(const QVariant &v)
253 {
254     if (v.toBool()) {
255         _attentionBehavior = AttentionBehavior::ChangeColor;
256     }
257     else {
258         if (_attentionBehavior == AttentionBehavior::ChangeColor) {
259             _attentionBehavior = AttentionBehavior::DoNothing;
260         }
261     }
262     emit currentIconNameChanged();
263 }
264
265
266 void SystemTray::enableBlinkChanged(const QVariant &v)
267 {
268     if (v.toBool()) {
269         _attentionBehavior = AttentionBehavior::Blink;
270     }
271     else {
272         if (_attentionBehavior == AttentionBehavior::Blink) {
273             _attentionBehavior = AttentionBehavior::DoNothing;
274         }
275     }
276     emit currentIconNameChanged();
277 }
278
279
280 void SystemTray::invertTrayIconChanged(const QVariant &v)
281 {
282     _trayIconInverted = v.toBool();
283     emit iconsChanged();
284 }
285
286
287 QString SystemTray::toolTipTitle() const
288 {
289     return _toolTipTitle;
290 }
291
292
293 QString SystemTray::toolTipSubTitle() const
294 {
295     return _toolTipSubTitle;
296 }
297
298
299 void SystemTray::setToolTip(const QString &title, const QString &subtitle)
300 {
301     _toolTipTitle = title;
302     _toolTipSubTitle = subtitle;
303     emit toolTipChanged(title, subtitle);
304 }
305
306
307 void SystemTray::showMessage(const QString &title, const QString &message, MessageIcon icon, int millisecondsTimeoutHint, uint id)
308 {
309     Q_UNUSED(title)
310     Q_UNUSED(message)
311     Q_UNUSED(icon)
312     Q_UNUSED(millisecondsTimeoutHint)
313     Q_UNUSED(id)
314 }
315
316
317 void SystemTray::closeMessage(uint notificationId)
318 {
319     Q_UNUSED(notificationId)
320 }
321
322
323 void SystemTray::activate(SystemTray::ActivationReason reason)
324 {
325     emit activated(reason);
326 }
327
328
329 void SystemTray::minimizeRestore()
330 {
331     GraphicalUi::toggleMainWidget();
332 }