Fix buffer preselection on reconnect
[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 General Public License as published by  *
8  *   the Free Software Foundation; either version 2 of the License, or     *
9  *   (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  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, 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_KDE
35 #  include <KWindowInfo>
36 #  include <KWindowSystem>
37 #endif
38
39 #include "statusnotifierwatcher.h"
40 #include "statusnotifieritemadaptor.h"
41
42 // Marshall the ImageStruct data into a D-BUS argument
43 const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageStruct &icon)
44 {
45     argument.beginStructure();
46     argument << icon.width;
47     argument << icon.height;
48     argument << icon.data;
49     argument.endStructure();
50     return argument;
51 }
52
53 // Retrieve the ImageStruct data from the D-BUS argument
54 const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImageStruct &icon)
55 {
56     qint32 width;
57     qint32 height;
58     QByteArray data;
59
60     argument.beginStructure();
61     argument >> width;
62     argument >> height;
63     argument >> data;
64     argument.endStructure();
65
66     icon.width = width;
67     icon.height = height;
68     icon.data = data;
69
70     return argument;
71 }
72
73
74 // Marshall the ImageVector data into a D-BUS argument
75 const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageVector &iconVector)
76 {
77     argument.beginArray(qMetaTypeId<DBusImageStruct>());
78     for (int i=0; i<iconVector.size(); ++i) {
79         argument << iconVector[i];
80     }
81     argument.endArray();
82     return argument;
83 }
84
85 // Retrieve the ImageVector data from the D-BUS argument
86 const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImageVector &iconVector)
87 {
88     argument.beginArray();
89     iconVector.clear();
90
91     while ( !argument.atEnd() ) {
92        DBusImageStruct element;
93        argument >> element;
94        iconVector.append(element);
95     }
96
97     argument.endArray();
98
99
100     return argument;
101 }
102
103 // Marshall the ToolTipStruct data into a D-BUS argument
104 const QDBusArgument &operator<<(QDBusArgument &argument, const DBusToolTipStruct &toolTip)
105 {
106     argument.beginStructure();
107     argument << toolTip.icon;
108     argument << toolTip.image;
109     argument << toolTip.title;
110     argument << toolTip.subTitle;
111     argument.endStructure();
112     return argument;
113 }
114
115 // Retrieve the ToolTipStruct data from the D-BUS argument
116 const QDBusArgument &operator>>(const QDBusArgument &argument, DBusToolTipStruct &toolTip)
117 {
118     QString icon;
119     DBusImageVector image;
120     QString title;
121     QString subTitle;
122
123     argument.beginStructure();
124     argument >> icon;
125     argument >> image;
126     argument >> title;
127     argument >> subTitle;
128     argument.endStructure();
129
130     toolTip.icon = icon;
131     toolTip.image = image;
132     toolTip.title = title;
133     toolTip.subTitle = subTitle;
134
135     return argument;
136 }
137
138
139 int StatusNotifierItemDBus::s_serviceCount = 0;
140
141 StatusNotifierItemDBus::StatusNotifierItemDBus(StatusNotifierItem *parent)
142   : QObject(parent),
143     m_statusNotifierItem(parent),
144     m_service(QString("org.kde.StatusNotifierItem-%1-%2")
145                       .arg(QCoreApplication::applicationPid())
146                       .arg(++s_serviceCount)),
147     m_dbus(QDBusConnection::connectToBus(QDBusConnection::SessionBus, m_service))
148 {
149    new StatusNotifierItemAdaptor(this);
150    //qDebug() << "service is" << m_service;
151    registerService();
152    m_dbus.registerObject("/StatusNotifierItem", this);
153 }
154
155 StatusNotifierItemDBus::~StatusNotifierItemDBus()
156 {
157     unregisterService();
158 }
159
160 // FIXME: prevent double registrations, also test this on platforms != KDE
161 //
162 void StatusNotifierItemDBus::registerService()
163 {
164     //qDebug() << "registering to" << m_service;
165     m_dbus.registerService(m_service);
166 }
167
168 // FIXME: see above
169 void StatusNotifierItemDBus::unregisterService()
170 {
171     //qDebug() << "unregistering from" << m_service;
172     if(m_dbus.isConnected()) {
173         m_dbus.unregisterService(m_service);
174     }
175 }
176
177 QString StatusNotifierItemDBus::service() const
178 {
179     return m_service;
180 }
181
182 //DBUS slots
183 //Values and calls have been adapted to Quassel
184
185 QString StatusNotifierItemDBus::Category() const
186 {
187     return QString("Communications"); // no need to make this configurable for Quassel
188 }
189
190 QString StatusNotifierItemDBus::Title() const
191 {
192     return m_statusNotifierItem->title();
193 }
194
195 QString StatusNotifierItemDBus::Id() const
196 {
197     return QString("QuasselIRC");
198 }
199
200 QString StatusNotifierItemDBus::Status() const
201 {
202     return m_statusNotifierItem->metaObject()->enumerator(m_statusNotifierItem->metaObject()->indexOfEnumerator("State")).valueToKey(m_statusNotifierItem->state());
203 }
204
205 int StatusNotifierItemDBus::WindowId() const
206 {
207     return (int)QtUi::mainWindow()->winId();
208 }
209
210
211 //Icon
212 //We don't need to support serialized icon data in Quassel
213
214 QString StatusNotifierItemDBus::IconName() const
215 {
216     return m_statusNotifierItem->iconName();
217 }
218
219 DBusImageVector StatusNotifierItemDBus::IconPixmap() const
220 {
221     return DBusImageVector();
222 }
223
224 QString StatusNotifierItemDBus::OverlayIconName() const
225 {
226     return QString();
227 }
228
229 DBusImageVector StatusNotifierItemDBus::OverlayIconPixmap() const
230 {
231     return DBusImageVector();
232 }
233
234 //Requesting attention icon and movie
235
236 QString StatusNotifierItemDBus::AttentionIconName() const
237 {
238     return m_statusNotifierItem->attentionIconName();
239 }
240
241 DBusImageVector StatusNotifierItemDBus::AttentionIconPixmap() const
242 {
243     return DBusImageVector();
244 }
245
246 QString StatusNotifierItemDBus::AttentionMovieName() const
247 {
248     return QString();
249 }
250
251
252 //ToolTip
253
254 DBusToolTipStruct StatusNotifierItemDBus::ToolTip() const
255 {
256     DBusToolTipStruct toolTip;
257     toolTip.icon = m_statusNotifierItem->toolTipIconName();
258     toolTip.image = DBusImageVector();
259     toolTip.title = m_statusNotifierItem->toolTipTitle();
260     toolTip.subTitle = m_statusNotifierItem->toolTipSubTitle();
261
262     return toolTip;
263 }
264
265 //Interaction
266
267 void StatusNotifierItemDBus::ContextMenu(int x, int y)
268 {
269     if (!m_statusNotifierItem->trayMenu()) {
270         return;
271     }
272
273     //TODO: nicer placement, possible?
274     if (!m_statusNotifierItem->trayMenu()->isVisible()) {
275 #ifdef HAVE_KDE
276         m_statusNotifierItem->trayMenu()->setWindowFlags(Qt::Window|Qt::FramelessWindowHint);
277 #endif
278         m_statusNotifierItem->trayMenu()->popup(QPoint(x,y));
279 #ifdef HAVE_KDE
280         KWindowSystem::setState(m_statusNotifierItem->trayMenu()->winId(), NET::SkipTaskbar|NET::SkipPager|NET::KeepAbove);
281         KWindowSystem::setType(m_statusNotifierItem->trayMenu()->winId(), NET::PopupMenu);
282         KWindowSystem::forceActiveWindow(m_statusNotifierItem->trayMenu()->winId());
283 #endif
284     } else {
285         m_statusNotifierItem->trayMenu()->hide();
286     }
287 }
288
289 void StatusNotifierItemDBus::Activate(int x, int y)
290 {
291     m_statusNotifierItem->activated(QPoint(x,y));
292 }
293
294 void StatusNotifierItemDBus::SecondaryActivate(int x, int y)
295 {
296     Q_UNUSED(x)
297     Q_UNUSED(y)
298     // emit m_statusNotifierItem->secondaryActivateRequested(QPoint(x,y));
299 }
300
301 void StatusNotifierItemDBus::Scroll(int delta, const QString &orientation)
302 {
303     Q_UNUSED(delta)
304     Q_UNUSED(orientation)
305     // Qt::Orientation dir = (orientation.toLower() == "horizontal" ? Qt::Horizontal : Qt::Vertical);
306     // emit m_statusNotifierItem->scrollRequested(delta, dir);
307 }