qtui: Make the debug log a proper dialog
[quassel.git] / src / qtui / statusnotifieritemdbus.cpp
1 /***************************************************************************
2  *   The original file is part of the KDE libraries                        *
3  *   Copyright (C) 2009 by Marco Martin <notmart@gmail.com>                *
4  *   Quasselfied 2010 by Manuel Nickschas <sputnick@quassel-irc.org>       *
5  *                                                                         *
6  *   This file is free software; you can redistribute it and/or modify     *
7  *   it under the terms of the GNU Library General Public License (LGPL)   *
8  *   as published by the Free Software Foundation; either version 2 of the *
9  *   License, or (at your option) any later version.                       *
10  *                                                                         *
11  *   This program is distributed in the hope that it will be useful,       *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14  *   GNU General Public License for more details.                          *
15  *                                                                         *
16  *   You should have received a copy of the GNU General Public License     *
17  *   along with this program; if not, write to the                         *
18  *   Free Software Foundation, Inc.,                                       *
19  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
20  ***************************************************************************/
21
22 #include "mainwin.h"
23 #include "qtui.h"
24 #include "statusnotifieritemdbus.h"
25 #include "statusnotifieritem.h"
26
27 #include <QDBusConnection>
28 #include <QPixmap>
29 #include <QImage>
30 #include <QApplication>
31 #include <QMenu>
32 #include <QMovie>
33
34 #ifdef HAVE_KDE4
35 #  include <KWindowInfo>
36 #  include <KWindowSystem>
37 #endif
38
39 #include "statusnotifierwatcher.h"
40 #include "statusnotifieritemadaptor.h"
41
42 #ifdef Q_OS_WIN64
43 __inline int toInt(WId wid)
44 {
45     return (int)((__int64)wid);
46 }
47
48
49 #else
50 __inline int toInt(WId wid)
51 {
52     return (int)wid;
53 }
54
55
56 #endif
57
58 // Marshall the ImageStruct data into a D-BUS argument
59 const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageStruct &icon)
60 {
61     argument.beginStructure();
62     argument << icon.width;
63     argument << icon.height;
64     argument << icon.data;
65     argument.endStructure();
66     return argument;
67 }
68
69
70 // Retrieve the ImageStruct data from the D-BUS argument
71 const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImageStruct &icon)
72 {
73     qint32 width;
74     qint32 height;
75     QByteArray data;
76
77     argument.beginStructure();
78     argument >> width;
79     argument >> height;
80     argument >> data;
81     argument.endStructure();
82
83     icon.width = width;
84     icon.height = height;
85     icon.data = data;
86
87     return argument;
88 }
89
90
91 // Marshall the ImageVector data into a D-BUS argument
92 const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageVector &iconVector)
93 {
94     argument.beginArray(qMetaTypeId<DBusImageStruct>());
95     for (int i = 0; i < iconVector.size(); ++i) {
96         argument << iconVector[i];
97     }
98     argument.endArray();
99     return argument;
100 }
101
102
103 // Retrieve the ImageVector data from the D-BUS argument
104 const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImageVector &iconVector)
105 {
106     argument.beginArray();
107     iconVector.clear();
108
109     while (!argument.atEnd()) {
110         DBusImageStruct element;
111         argument >> element;
112         iconVector.append(element);
113     }
114
115     argument.endArray();
116
117     return argument;
118 }
119
120
121 // Marshall the ToolTipStruct data into a D-BUS argument
122 const QDBusArgument &operator<<(QDBusArgument &argument, const DBusToolTipStruct &toolTip)
123 {
124     argument.beginStructure();
125     argument << toolTip.icon;
126     argument << toolTip.image;
127     argument << toolTip.title;
128     argument << toolTip.subTitle;
129     argument.endStructure();
130     return argument;
131 }
132
133
134 // Retrieve the ToolTipStruct data from the D-BUS argument
135 const QDBusArgument &operator>>(const QDBusArgument &argument, DBusToolTipStruct &toolTip)
136 {
137     QString icon;
138     DBusImageVector image;
139     QString title;
140     QString subTitle;
141
142     argument.beginStructure();
143     argument >> icon;
144     argument >> image;
145     argument >> title;
146     argument >> subTitle;
147     argument.endStructure();
148
149     toolTip.icon = icon;
150     toolTip.image = image;
151     toolTip.title = title;
152     toolTip.subTitle = subTitle;
153
154     return argument;
155 }
156
157
158 int StatusNotifierItemDBus::s_serviceCount = 0;
159
160 StatusNotifierItemDBus::StatusNotifierItemDBus(StatusNotifierItem *parent)
161     : QObject(parent),
162     m_statusNotifierItem(parent),
163     m_dbus(QDBusConnection::connectToBus(QDBusConnection::SessionBus,
164                                          QString("org.kde.StatusNotifierItem-%1-%2").arg(QCoreApplication::applicationPid()).arg(++s_serviceCount)))
165 {
166     new StatusNotifierItemAdaptor(this);
167 }
168
169
170 StatusNotifierItemDBus::~StatusNotifierItemDBus()
171 {
172     unregisterTrayIcon();
173 }
174
175
176 QDBusConnection StatusNotifierItemDBus::dbusConnection() const
177 {
178     return m_dbus;
179 }
180
181
182 // FIXME: prevent double registrations, also test this on platforms != KDE
183 //
184 void StatusNotifierItemDBus::registerTrayIcon()
185 {
186     m_dbus.registerObject("/StatusNotifierItem", this);
187 }
188
189
190 // FIXME: see above
191 void StatusNotifierItemDBus::unregisterTrayIcon()
192 {
193     if (m_dbus.isConnected()) {
194         m_dbus.unregisterObject("/StatusNotifierItem");
195     }
196 }
197
198
199 QString StatusNotifierItemDBus::service() const
200 {
201     return m_dbus.baseService();
202 }
203
204
205 //DBUS slots
206 //Values and calls have been adapted to Quassel
207
208 QString StatusNotifierItemDBus::Category() const
209 {
210     return QString("Communications"); // no need to make this configurable for Quassel
211 }
212
213
214 QString StatusNotifierItemDBus::Title() const
215 {
216     return m_statusNotifierItem->title();
217 }
218
219
220 QString StatusNotifierItemDBus::Id() const
221 {
222     return QString("QuasselIRC");
223 }
224
225
226 QString StatusNotifierItemDBus::Status() const
227 {
228     return m_statusNotifierItem->metaObject()->enumerator(m_statusNotifierItem->metaObject()->indexOfEnumerator("State")).valueToKey(m_statusNotifierItem->state());
229 }
230
231
232 int StatusNotifierItemDBus::WindowId() const
233 {
234     return toInt(QtUi::mainWindow()->winId());
235 }
236
237
238 //Icon
239 //We don't need to support serialized icon data in Quassel
240
241 QString StatusNotifierItemDBus::IconName() const
242 {
243     return m_statusNotifierItem->iconName();
244 }
245
246
247 DBusImageVector StatusNotifierItemDBus::IconPixmap() const
248 {
249     return DBusImageVector();
250 }
251
252
253 QString StatusNotifierItemDBus::OverlayIconName() const
254 {
255     return QString();
256 }
257
258
259 DBusImageVector StatusNotifierItemDBus::OverlayIconPixmap() const
260 {
261     return DBusImageVector();
262 }
263
264
265 //Requesting attention icon and movie
266
267 QString StatusNotifierItemDBus::AttentionIconName() const
268 {
269     return m_statusNotifierItem->attentionIconName();
270 }
271
272
273 DBusImageVector StatusNotifierItemDBus::AttentionIconPixmap() const
274 {
275     return DBusImageVector();
276 }
277
278
279 QString StatusNotifierItemDBus::AttentionMovieName() const
280 {
281     return QString();
282 }
283
284
285 //ToolTip
286
287 DBusToolTipStruct StatusNotifierItemDBus::ToolTip() const
288 {
289     DBusToolTipStruct toolTip;
290     toolTip.icon = m_statusNotifierItem->toolTipIconName();
291     toolTip.image = DBusImageVector();
292     toolTip.title = m_statusNotifierItem->toolTipTitle();
293     toolTip.subTitle = m_statusNotifierItem->toolTipSubTitle();
294
295     return toolTip;
296 }
297
298
299 QString StatusNotifierItemDBus::IconThemePath() const
300 {
301     return m_statusNotifierItem->iconThemePath();
302 }
303
304
305 //Menu
306
307 QDBusObjectPath StatusNotifierItemDBus::Menu() const
308 {
309     return QDBusObjectPath(m_statusNotifierItem->menuObjectPath());
310 }
311
312
313 //Interaction
314
315 void StatusNotifierItemDBus::ContextMenu(int x, int y)
316 {
317     if (!m_statusNotifierItem->trayMenu()) {
318         return;
319     }
320
321     //TODO: nicer placement, possible?
322     if (!m_statusNotifierItem->trayMenu()->isVisible()) {
323 #ifdef HAVE_KDE4
324         m_statusNotifierItem->trayMenu()->setWindowFlags(Qt::Window|Qt::FramelessWindowHint);
325 #endif
326         m_statusNotifierItem->trayMenu()->popup(QPoint(x, y));
327 #ifdef HAVE_KDE4
328         KWindowSystem::setState(m_statusNotifierItem->trayMenu()->winId(), NET::SkipTaskbar|NET::SkipPager|NET::KeepAbove);
329         KWindowSystem::setType(m_statusNotifierItem->trayMenu()->winId(), NET::PopupMenu);
330         KWindowSystem::forceActiveWindow(m_statusNotifierItem->trayMenu()->winId());
331 #endif
332     }
333     else {
334         m_statusNotifierItem->trayMenu()->hide();
335     }
336 }
337
338
339 void StatusNotifierItemDBus::Activate(int x, int y)
340 {
341     m_statusNotifierItem->activated(QPoint(x, y));
342 }
343
344
345 void StatusNotifierItemDBus::SecondaryActivate(int x, int y)
346 {
347     Q_UNUSED(x)
348     Q_UNUSED(y)
349     // emit m_statusNotifierItem->secondaryActivateRequested(QPoint(x,y));
350 }
351
352
353 void StatusNotifierItemDBus::Scroll(int delta, const QString &orientation)
354 {
355     Q_UNUSED(delta)
356     Q_UNUSED(orientation)
357     // Qt::Orientation dir = (orientation.toLower() == "horizontal" ? Qt::Horizontal : Qt::Vertical);
358     // emit m_statusNotifierItem->scrollRequested(delta, dir);
359 }