1 | /*************************************************************************** |
2 | * Copyright (C) 2005-2014 by the Quassel Project * |
3 | * devel@quassel-irc.org * |
4 | * * |
5 | * This program is free software; you can redistribute it and/or modify * |
6 | * it under the terms of the GNU General Public License as published by * |
7 | * the Free Software Foundation; either version 2 of the License, or * |
8 | * (at your option) version 3. * |
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 <QApplication> |
22 | #include <QCheckBox> |
23 | #include <QGroupBox> |
24 | #include <QHBoxLayout> |
25 | |
26 | #include "systraynotificationbackend.h" |
27 | |
28 | #include "client.h" |
29 | #include "clientsettings.h" |
30 | #include "icon.h" |
31 | #include "iconloader.h" |
32 | #include "mainwin.h" |
33 | #include "networkmodel.h" |
34 | #include "qtui.h" |
35 | #include "systemtray.h" |
36 | |
37 | SystrayNotificationBackend::SystrayNotificationBackend(QObject *parent) |
38 | : AbstractNotificationBackend(parent), |
39 | _blockActivation(false) |
40 | { |
41 | NotificationSettings notificationSettings; |
42 | notificationSettings.initAndNotify("Systray/ShowBubble" , this, SLOT(showBubbleChanged(QVariant)), true); |
43 | notificationSettings.initAndNotify("Systray/Animate" , this, SLOT(animateChanged(QVariant)), true); |
44 | |
45 | connect(QtUi::mainWindow()->systemTray(), SIGNAL(messageClicked(uint)), SLOT(notificationActivated(uint))); |
46 | connect(QtUi::mainWindow()->systemTray(), SIGNAL(activated(SystemTray::ActivationReason)), |
47 | SLOT(notificationActivated(SystemTray::ActivationReason))); |
48 | |
49 | QApplication::instance()->installEventFilter(this); |
50 | |
51 | updateToolTip(); |
52 | } |
53 | |
54 | |
55 | void SystrayNotificationBackend::notify(const Notification &n) |
56 | { |
57 | if (n.type != Highlight && n.type != PrivMsg) |
58 | return; |
59 | |
60 | _notifications.append(n); |
61 | if (_showBubble) { |
62 | QString title = Client::networkModel()->networkName(n.bufferId) + " - " + Client::networkModel()->bufferName(n.bufferId); |
63 | QString message = QString("<%1> %2" ).arg(n.sender, n.message); |
64 | QtUi::mainWindow()->systemTray()->showMessage(title, message, SystemTray::Information, 10000, n.notificationId); |
65 | } |
66 | |
67 | if (_animate) |
68 | QtUi::mainWindow()->systemTray()->setAlert(true); |
69 | |
70 | updateToolTip(); |
71 | } |
72 | |
73 | |
74 | void SystrayNotificationBackend::close(uint notificationId) |
75 | { |
76 | QList<Notification>::iterator i = _notifications.begin(); |
77 | while (i != _notifications.end()) { |
78 | if (i->notificationId == notificationId) |
79 | i = _notifications.erase(i); |
80 | else |
81 | ++i; |
82 | } |
83 | |
84 | QtUi::mainWindow()->systemTray()->closeMessage(notificationId); |
85 | |
86 | //if(!_notifications.count()) //FIXME make configurable |
87 | QtUi::mainWindow()->systemTray()->setAlert(false); |
88 | |
89 | updateToolTip(); |
90 | } |
91 | |
92 | |
93 | void SystrayNotificationBackend::notificationActivated(uint notificationId) |
94 | { |
95 | if (!_blockActivation) { |
96 | if (_notifications.count()) { |
97 | if (QtUi::mainWindow()->systemTray()->mode() == SystemTray::Legacy) |
98 | _blockActivation = true; // prevent double activation because both tray icon and bubble might send a signal |
99 | if (!notificationId) |
100 | notificationId = _notifications.count() ? _notifications.last().notificationId : 0; |
101 | emit activated(notificationId); |
102 | } |
103 | else |
104 | GraphicalUi::toggleMainWidget(); |
105 | } |
106 | } |
107 | |
108 | |
109 | void SystrayNotificationBackend::notificationActivated(SystemTray::ActivationReason reason) |
110 | { |
111 | if (reason == SystemTray::Trigger) { |
112 | notificationActivated(0); |
113 | } |
114 | } |
115 | |
116 | |
117 | // moving the mouse or releasing the button means that we're not dealing with a double activation |
118 | bool SystrayNotificationBackend::eventFilter(QObject *obj, QEvent *event) |
119 | { |
120 | if (event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonRelease) { |
121 | _blockActivation = false; |
122 | } |
123 | return AbstractNotificationBackend::eventFilter(obj, event); |
124 | } |
125 | |
126 | |
127 | void SystrayNotificationBackend::showBubbleChanged(const QVariant &v) |
128 | { |
129 | _showBubble = v.toBool(); |
130 | } |
131 | |
132 | |
133 | void SystrayNotificationBackend::animateChanged(const QVariant &v) |
134 | { |
135 | _animate = v.toBool(); |
136 | } |
137 | |
138 | |
139 | void SystrayNotificationBackend::updateToolTip() |
140 | { |
141 | QtUi::mainWindow()->systemTray()->setToolTip("Quassel IRC" , |
142 | _notifications.count() ? tr("%n pending highlight(s)" , "" , _notifications.count()) : QString()); |
143 | } |
144 | |
145 | |
146 | SettingsPage *SystrayNotificationBackend::createConfigWidget() const |
147 | { |
148 | return new ConfigWidget(); |
149 | } |
150 | |
151 | |
152 | /***************************************************************************/ |
153 | |
154 | SystrayNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent) : SettingsPage("Internal" , "SystrayNotification" , parent) |
155 | { |
156 | _showBubbleBox = new QCheckBox(tr("Show a message in a popup" )); |
157 | _showBubbleBox->setIcon(SmallIcon("dialog-information" )); |
158 | connect(_showBubbleBox, SIGNAL(toggled(bool)), this, SLOT(widgetChanged())); |
159 | QHBoxLayout *layout = new QHBoxLayout(this); |
160 | layout->addWidget(_showBubbleBox); |
161 | } |
162 | |
163 | |
164 | void SystrayNotificationBackend::ConfigWidget::widgetChanged() |
165 | { |
166 | bool changed = (_showBubble != _showBubbleBox->isChecked()); |
167 | if (changed != hasChanged()) |
168 | setChangedState(changed); |
169 | } |
170 | |
171 | |
172 | bool SystrayNotificationBackend::ConfigWidget::hasDefaults() const |
173 | { |
174 | return true; |
175 | } |
176 | |
177 | |
178 | void SystrayNotificationBackend::ConfigWidget::defaults() |
179 | { |
180 | _showBubbleBox->setChecked(false); |
181 | widgetChanged(); |
182 | } |
183 | |
184 | |
185 | void SystrayNotificationBackend::ConfigWidget::load() |
186 | { |
187 | NotificationSettings s; |
188 | _showBubble = s.value("Systray/ShowBubble" , false).toBool(); |
189 | _showBubbleBox->setChecked(_showBubble); |
190 | setChangedState(false); |
191 | } |
192 | |
193 | |
194 | void SystrayNotificationBackend::ConfigWidget::save() |
195 | { |
196 | NotificationSettings s; |
197 | s.setValue("Systray/ShowBubble" , _showBubbleBox->isChecked()); |
198 | load(); |
199 | } |
200 | |