Quassel IRC  Pre-Release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
statusnotifieritemdbus.cpp
Go to the documentation of this file.
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 
159 
161  : QObject(parent),
162  m_statusNotifierItem(parent),
163  m_service(QString("org.kde.StatusNotifierItem-%1-%2")
164  .arg(QCoreApplication::applicationPid())
165  .arg(++s_serviceCount)),
166  m_dbus(QDBusConnection::connectToBus(QDBusConnection::SessionBus, m_service))
167 {
168  new StatusNotifierItemAdaptor(this);
169  //qDebug() << "service is" << m_service;
170  registerService();
171 }
172 
173 
175 {
177 }
178 
179 
181 {
182  return m_dbus;
183 }
184 
185 
186 // FIXME: prevent double registrations, also test this on platforms != KDE
187 //
189 {
190  //qDebug() << "registering to" << m_service;
191  m_dbus.registerService(m_service);
192  m_dbus.registerObject("/StatusNotifierItem", this);
193 }
194 
195 
196 // FIXME: see above
198 {
199  //qDebug() << "unregistering from" << m_service;
200  if (m_dbus.isConnected()) {
201  m_dbus.unregisterObject("/StatusNotifierItem");
202  m_dbus.unregisterService(m_service);
203  }
204 }
205 
206 
208 {
209  return m_service;
210 }
211 
212 
213 //DBUS slots
214 //Values and calls have been adapted to Quassel
215 
216 QString StatusNotifierItemDBus::Category() const
217 {
218  return QString("Communications"); // no need to make this configurable for Quassel
219 }
220 
221 
222 QString StatusNotifierItemDBus::Title() const
223 {
224  return m_statusNotifierItem->title();
225 }
226 
227 
228 QString StatusNotifierItemDBus::Id() const
229 {
230  return QString("QuasselIRC");
231 }
232 
233 
234 QString StatusNotifierItemDBus::Status() const
235 {
236  return m_statusNotifierItem->metaObject()->enumerator(m_statusNotifierItem->metaObject()->indexOfEnumerator("State")).valueToKey(m_statusNotifierItem->state());
237 }
238 
239 
241 {
242  return toInt(QtUi::mainWindow()->winId());
243 }
244 
245 
246 //Icon
247 //We don't need to support serialized icon data in Quassel
248 
249 QString StatusNotifierItemDBus::IconName() const
250 {
251  return m_statusNotifierItem->iconName();
252 }
253 
254 
256 {
257  return DBusImageVector();
258 }
259 
260 
262 {
263  return QString();
264 }
265 
266 
268 {
269  return DBusImageVector();
270 }
271 
272 
273 //Requesting attention icon and movie
274 
276 {
277  return m_statusNotifierItem->attentionIconName();
278 }
279 
280 
282 {
283  return DBusImageVector();
284 }
285 
286 
288 {
289  return QString();
290 }
291 
292 
293 //ToolTip
294 
296 {
298  toolTip.icon = m_statusNotifierItem->toolTipIconName();
299  toolTip.image = DBusImageVector();
300  toolTip.title = m_statusNotifierItem->toolTipTitle();
301  toolTip.subTitle = m_statusNotifierItem->toolTipSubTitle();
302 
303  return toolTip;
304 }
305 
306 
308 {
309  return m_statusNotifierItem->iconThemePath();
310 }
311 
312 
313 //Menu
314 
315 QDBusObjectPath StatusNotifierItemDBus::Menu() const
316 {
317  return QDBusObjectPath(m_statusNotifierItem->menuObjectPath());
318 }
319 
320 
321 //Interaction
322 
324 {
325  if (!m_statusNotifierItem->trayMenu()) {
326  return;
327  }
328 
329  //TODO: nicer placement, possible?
330  if (!m_statusNotifierItem->trayMenu()->isVisible()) {
331 #ifdef HAVE_KDE4
332  m_statusNotifierItem->trayMenu()->setWindowFlags(Qt::Window|Qt::FramelessWindowHint);
333 #endif
334  m_statusNotifierItem->trayMenu()->popup(QPoint(x, y));
335 #ifdef HAVE_KDE4
336  KWindowSystem::setState(m_statusNotifierItem->trayMenu()->winId(), NET::SkipTaskbar|NET::SkipPager|NET::KeepAbove);
337  KWindowSystem::setType(m_statusNotifierItem->trayMenu()->winId(), NET::PopupMenu);
338  KWindowSystem::forceActiveWindow(m_statusNotifierItem->trayMenu()->winId());
339 #endif
340  }
341  else {
342  m_statusNotifierItem->trayMenu()->hide();
343  }
344 }
345 
346 
348 {
349  m_statusNotifierItem->activated(QPoint(x, y));
350 }
351 
352 
354 {
355  Q_UNUSED(x)
356  Q_UNUSED(y)
357  // emit m_statusNotifierItem->secondaryActivateRequested(QPoint(x,y));
358 }
359 
360 
361 void StatusNotifierItemDBus::Scroll(int delta, const QString &orientation)
362 {
363  Q_UNUSED(delta)
364  Q_UNUSED(orientation)
365  // Qt::Orientation dir = (orientation.toLower() == "horizontal" ? Qt::Horizontal : Qt::Vertical);
366  // emit m_statusNotifierItem->scrollRequested(delta, dir);
367 }