1 | /*************************************************************************** |
2 | * Copyright (C) 2013 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 "dockmanagernotificationbackend.h" |
22 | |
23 | #include <QHBoxLayout> |
24 | #include <QCheckBox> |
25 | #include <QDBusReply> |
26 | |
27 | #include "client.h" |
28 | #include "clientsettings.h" |
29 | #include "coreconnection.h" |
30 | #include "clientbacklogmanager.h" |
31 | |
32 | DockManagerNotificationBackend::DockManagerNotificationBackend(QObject *parent) |
33 | : AbstractNotificationBackend(parent), _bus(QDBusConnection::sessionBus()), _dock(0), _item(0), _count(0) |
34 | { |
35 | NotificationSettings notificationSettings; |
36 | _enabled = notificationSettings.value("DockManager/Enabled" , false).toBool(); |
37 | |
38 | notificationSettings.notify("DockManager/Enabled" , this, SLOT(enabledChanged(const QVariant &))); |
39 | |
40 | _dock = new QDBusInterface("net.launchpad.DockManager" , "/net/launchpad/DockManager" , "net.launchpad.DockManager" , _bus, this); |
41 | if (_dock->isValid()) { |
42 | _bus.connect("net.launchpad.DockManager" , "/net/launchpad/DockManager" , "net.launchpad.DockManager" , "ItemAdded" , this, SLOT(itemAdded(QDBusObjectPath))); |
43 | } else { |
44 | // evil implementations (awn) use fd.o |
45 | _dock = new QDBusInterface("org.freedesktop.DockManager" , "/org/freedesktop/DockManager" , "org.freedesktop.DockManager" , _bus, this); |
46 | if (_dock->isValid()) { |
47 | _bus.connect("org.freedesktop.DockManager" , "/org/freedesktop/DockManager" , "org.freedesktop.DockManager" , "ItemAdded" , this, SLOT(itemAdded(QDBusObjectPath))); |
48 | } else { |
49 | qDebug() << "No DockManager available" ; |
50 | _enabled = false; |
51 | return; |
52 | } |
53 | } |
54 | |
55 | itemAdded(QDBusObjectPath()); |
56 | |
57 | connect(Client::coreConnection(), SIGNAL(progressValueChanged(int)), this, SLOT(updateProgress(int))); |
58 | connect(Client::coreConnection(), SIGNAL(synchronized()), this, SLOT(synchronized())); |
59 | } |
60 | |
61 | |
62 | void DockManagerNotificationBackend::itemAdded(QDBusObjectPath p) |
63 | { |
64 | Q_UNUSED(p); |
65 | |
66 | if (_item) |
67 | return; |
68 | |
69 | // stupid implementations (awn; kde?) use wrong casing of PID, but proper type |
70 | QDBusReply<QList<QDBusObjectPath> > paths = _dock->call("GetItemsByPid" , (int)QCoreApplication::applicationPid()); |
71 | if (!paths.isValid()) { |
72 | // stupid implementations (i.e. docky) use uint, but proper casing |
73 | paths = _dock->call("GetItemsByPID" , (unsigned int)QCoreApplication::applicationPid()); |
74 | if (!paths.isValid()) { |
75 | qDebug() << "DBus error:" << paths.error().message(); |
76 | return; |
77 | } |
78 | } |
79 | if (paths.value().count() == 0) { // no icon for this instance |
80 | return; |
81 | } |
82 | |
83 | QString path = paths.value()[0].path(); // no sense in using multiple icons for one instance |
84 | _item = new QDBusInterface("org.freedesktop.DockManager" , path, "org.freedesktop.DockItem" , _bus, this); |
85 | } |
86 | |
87 | |
88 | void DockManagerNotificationBackend::updateProgress(int progress) |
89 | { |
90 | if (!_enabled || !_item) |
91 | return; |
92 | |
93 | CoreConnection *c = Client::instance()->coreConnection(); |
94 | int perc = 0; |
95 | if (c->progressMaximum() == c->progressMinimum()) |
96 | perc = 0; |
97 | else |
98 | perc = (progress - c->progressMinimum()) * 100 / (c->progressMaximum() - c->progressMinimum()); |
99 | |
100 | QHash<QString, QVariant> args; |
101 | args["progress" ] = perc; |
102 | _item->call("UpdateDockItem" , args); |
103 | } |
104 | |
105 | |
106 | void DockManagerNotificationBackend::updateProgress(int done, int total) |
107 | { |
108 | if (!_enabled || !_item) |
109 | return; |
110 | |
111 | int perc = 0; |
112 | if (done == total) { |
113 | disconnect(Client::backlogManager(), 0, this, 0); |
114 | perc = -1; |
115 | } else |
116 | perc = (done * 100) / total; |
117 | |
118 | QHash<QString, QVariant> args; |
119 | args["progress" ] = perc; |
120 | _item->call("UpdateDockItem" , args); |
121 | } |
122 | |
123 | |
124 | void DockManagerNotificationBackend::synchronized() |
125 | { |
126 | connect(Client::backlogManager(), SIGNAL(updateProgress(int, int)), this, SLOT(updateProgress(int, int))); |
127 | } |
128 | |
129 | |
130 | void DockManagerNotificationBackend::notify(const Notification ¬ification) |
131 | { |
132 | if (!_enabled || !_item) { |
133 | return; |
134 | } |
135 | if (notification.type != Highlight && notification.type != PrivMsg) { |
136 | return; |
137 | } |
138 | |
139 | QHash<QString, QVariant> args; |
140 | args["attention" ] = true; |
141 | args["badge" ] = QString::number(++_count); |
142 | _item->call("UpdateDockItem" , args); |
143 | } |
144 | |
145 | |
146 | void DockManagerNotificationBackend::close(uint notificationId) |
147 | { |
148 | Q_UNUSED(notificationId); |
149 | if (!_item) |
150 | return; |
151 | |
152 | QHash<QString, QVariant> args; |
153 | args["attention" ] = false; |
154 | args["badge" ] = --_count == 0 ? QString() : QString::number(_count); |
155 | _item->call("UpdateDockItem" , args); |
156 | } |
157 | |
158 | |
159 | void DockManagerNotificationBackend::enabledChanged(const QVariant &v) |
160 | { |
161 | _enabled = v.toBool(); |
162 | |
163 | if (!_enabled && _item) { |
164 | QHash<QString, QVariant> args; |
165 | args["attention" ] = false; |
166 | args["badge" ] = QString(); |
167 | _item->call("UpdateDockItem" , args); |
168 | } |
169 | } |
170 | |
171 | |
172 | SettingsPage *DockManagerNotificationBackend::createConfigWidget() const |
173 | { |
174 | return new ConfigWidget(); |
175 | } |
176 | |
177 | |
178 | /***************************************************************************/ |
179 | |
180 | DockManagerNotificationBackend::ConfigWidget::ConfigWidget(QWidget *parent) |
181 | : SettingsPage("Internal" , "DockManagerNotification" , parent) |
182 | { |
183 | QHBoxLayout *layout = new QHBoxLayout(this); |
184 | layout->addWidget(enabledBox = new QCheckBox(tr("Mark dockmanager entry" ), this)); |
185 | enabledBox->setEnabled(true); |
186 | |
187 | connect(enabledBox, SIGNAL(toggled(bool)), SLOT(widgetChanged())); |
188 | } |
189 | |
190 | |
191 | void DockManagerNotificationBackend::ConfigWidget::widgetChanged() |
192 | { |
193 | bool changed = enabled != enabledBox->isChecked(); |
194 | |
195 | if (changed != hasChanged()) setChangedState(changed); |
196 | } |
197 | |
198 | |
199 | bool DockManagerNotificationBackend::ConfigWidget::hasDefaults() const |
200 | { |
201 | return true; |
202 | } |
203 | |
204 | |
205 | void DockManagerNotificationBackend::ConfigWidget::defaults() |
206 | { |
207 | enabledBox->setChecked(false); |
208 | widgetChanged(); |
209 | } |
210 | |
211 | |
212 | void DockManagerNotificationBackend::ConfigWidget::load() |
213 | { |
214 | NotificationSettings s; |
215 | enabled = s.value("DockManager/Enabled" , false).toBool(); |
216 | |
217 | enabledBox->setChecked(enabled); |
218 | setChangedState(false); |
219 | } |
220 | |
221 | |
222 | void DockManagerNotificationBackend::ConfigWidget::save() |
223 | { |
224 | NotificationSettings s; |
225 | s.setValue("DockManager/Enabled" , enabledBox->isChecked()); |
226 | load(); |
227 | } |
228 | |