Basic StatusNotifierItem support
[quassel.git] / src / qtui / statusnotifieritemdbus.cpp
diff --git a/src/qtui/statusnotifieritemdbus.cpp b/src/qtui/statusnotifieritemdbus.cpp
new file mode 100644 (file)
index 0000000..db93d5c
--- /dev/null
@@ -0,0 +1,287 @@
+/***************************************************************************
+ *   The original file is part of the KDE libraries                        *
+ *   Copyright (C) 2009 by Marco Martin <notmart@gmail.com>                *
+ *   Quasselfied 2010 by Manuel Nickschas <sputnick@quassel-irc.org>       *
+ *                                                                         *
+ *   This file is free software; you can redistribute it and/or modify     *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "statusnotifieritemdbus.h"
+#include "statusnotifieritem.h"
+#include "qtui.h"
+
+#include <QDBusConnection>
+#include <QPixmap>
+#include <QImage>
+#include <QApplication>
+#include <QMenu>
+#include <QMovie>
+
+#ifdef HAVE_KDE
+#  include <KWindowInfo>
+#  include <KWindowSystem>
+#endif
+
+#include "statusnotifierwatcher.h"
+#include "statusnotifieritemadaptor.h"
+
+// Marshall the ImageStruct data into a D-BUS argument
+const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageStruct &icon)
+{
+    argument.beginStructure();
+    argument << icon.width;
+    argument << icon.height;
+    argument << icon.data;
+    argument.endStructure();
+    return argument;
+}
+
+// Retrieve the ImageStruct data from the D-BUS argument
+const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImageStruct &icon)
+{
+    qint32 width;
+    qint32 height;
+    QByteArray data;
+
+    argument.beginStructure();
+    argument >> width;
+    argument >> height;
+    argument >> data;
+    argument.endStructure();
+
+    icon.width = width;
+    icon.height = height;
+    icon.data = data;
+
+    return argument;
+}
+
+
+// Marshall the ImageVector data into a D-BUS argument
+const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageVector &iconVector)
+{
+    argument.beginArray(qMetaTypeId<DBusImageStruct>());
+    for (int i=0; i<iconVector.size(); ++i) {
+        argument << iconVector[i];
+    }
+    argument.endArray();
+    return argument;
+}
+
+// Retrieve the ImageVector data from the D-BUS argument
+const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImageVector &iconVector)
+{
+    argument.beginArray();
+    iconVector.clear();
+
+    while ( !argument.atEnd() ) {
+       DBusImageStruct element;
+       argument >> element;
+       iconVector.append(element);
+    }
+
+    argument.endArray();
+
+
+    return argument;
+}
+
+// Marshall the ToolTipStruct data into a D-BUS argument
+const QDBusArgument &operator<<(QDBusArgument &argument, const DBusToolTipStruct &toolTip)
+{
+    argument.beginStructure();
+    argument << toolTip.icon;
+    argument << toolTip.image;
+    argument << toolTip.title;
+    argument << toolTip.subTitle;
+    argument.endStructure();
+    return argument;
+}
+
+// Retrieve the ToolTipStruct data from the D-BUS argument
+const QDBusArgument &operator>>(const QDBusArgument &argument, DBusToolTipStruct &toolTip)
+{
+    QString icon;
+    DBusImageVector image;
+    QString title;
+    QString subTitle;
+
+    argument.beginStructure();
+    argument >> icon;
+    argument >> image;
+    argument >> title;
+    argument >> subTitle;
+    argument.endStructure();
+
+    toolTip.icon = icon;
+    toolTip.image = image;
+    toolTip.title = title;
+    toolTip.subTitle = subTitle;
+
+    return argument;
+}
+
+
+int StatusNotifierItemDBus::s_serviceCount = 0;
+
+StatusNotifierItemDBus::StatusNotifierItemDBus(StatusNotifierItem *parent)
+  : QObject(parent),
+    m_statusNotifierItem(parent),
+    m_service(QString("org.kde.StatusNotifierItem-%1-%2")
+                      .arg(QCoreApplication::applicationPid())
+                      .arg(++s_serviceCount)),
+    m_dbus(QDBusConnection::connectToBus(QDBusConnection::SessionBus, m_service))
+{
+   new StatusNotifierItemAdaptor(this);
+   qDebug() << "service is" << m_service;
+   m_dbus.registerService(m_service);
+   m_dbus.registerObject("/StatusNotifierItem", this);
+}
+
+StatusNotifierItemDBus::~StatusNotifierItemDBus()
+{
+    m_dbus.unregisterService(m_service);
+}
+
+QString StatusNotifierItemDBus::service() const
+{
+    return m_service;
+}
+
+//DBUS slots
+//Values and calls have been adapted to Quassel
+
+QString StatusNotifierItemDBus::Category() const
+{
+    return QString("Communications"); // no need to make this configurable for Quassel
+}
+
+QString StatusNotifierItemDBus::Title() const
+{
+    return m_statusNotifierItem->title();
+}
+
+QString StatusNotifierItemDBus::Id() const
+{
+    return QString("QuasselIRC");
+}
+
+QString StatusNotifierItemDBus::Status() const
+ {
+    return m_statusNotifierItem->metaObject()->enumerator(m_statusNotifierItem->metaObject()->indexOfEnumerator("State")).valueToKey(m_statusNotifierItem->state());
+}
+
+int StatusNotifierItemDBus::WindowId() const
+{
+    return (int)QtUi::mainWindow()->winId();
+}
+
+
+//Icon
+//We don't need to support serialized icon data in Quassel
+
+QString StatusNotifierItemDBus::IconName() const
+{
+    return m_statusNotifierItem->iconName();
+}
+
+DBusImageVector StatusNotifierItemDBus::IconPixmap() const
+{
+    return DBusImageVector();
+}
+
+QString StatusNotifierItemDBus::OverlayIconName() const
+{
+    return QString();
+}
+
+DBusImageVector StatusNotifierItemDBus::OverlayIconPixmap() const
+{
+    return DBusImageVector();
+}
+
+//Requesting attention icon and movie
+
+QString StatusNotifierItemDBus::AttentionIconName() const
+{
+    return m_statusNotifierItem->attentionIconName();
+}
+
+DBusImageVector StatusNotifierItemDBus::AttentionIconPixmap() const
+{
+    return DBusImageVector();
+}
+
+QString StatusNotifierItemDBus::AttentionMovieName() const
+{
+    return QString();
+}
+
+
+//ToolTip
+
+DBusToolTipStruct StatusNotifierItemDBus::ToolTip() const
+{
+    DBusToolTipStruct toolTip;
+    toolTip.icon = m_statusNotifierItem->toolTipIconName();
+    toolTip.image = DBusImageVector();
+    toolTip.title = m_statusNotifierItem->toolTipTitle();
+    toolTip.subTitle = m_statusNotifierItem->toolTipSubTitle();
+
+    return toolTip;
+}
+
+//Interaction
+
+void StatusNotifierItemDBus::ContextMenu(int x, int y)
+{
+    if (!m_statusNotifierItem->trayMenu()) {
+        return;
+    }
+
+    //TODO: nicer placement, possible?
+    if (!m_statusNotifierItem->trayMenu()->isVisible()) {
+        m_statusNotifierItem->trayMenu()->setWindowFlags(Qt::Window|Qt::FramelessWindowHint);
+        m_statusNotifierItem->trayMenu()->popup(QPoint(x,y));
+#ifdef HAVE_KDE
+        KWindowSystem::setState(m_statusNotifierItem->trayMenu()->winId(), NET::SkipTaskbar|NET::SkipPager|NET::KeepAbove);
+        KWindowSystem::setType(m_statusNotifierItem->trayMenu()->winId(), NET::PopupMenu);
+        KWindowSystem::forceActiveWindow(m_statusNotifierItem->trayMenu()->winId());
+#endif
+    } else {
+        m_statusNotifierItem->trayMenu()->hide();
+    }
+}
+
+void StatusNotifierItemDBus::Activate(int x, int y)
+{
+    m_statusNotifierItem->activated(QPoint(x,y));
+}
+
+void StatusNotifierItemDBus::SecondaryActivate(int x, int y)
+{
+    Q_UNUSED(x)
+    Q_UNUSED(y)
+    // emit m_statusNotifierItem->secondaryActivateRequested(QPoint(x,y));
+}
+
+void StatusNotifierItemDBus::Scroll(int delta, const QString &orientation)
+{
+    Q_UNUSED(delta)
+    Q_UNUSED(orientation)
+    // Qt::Orientation dir = (orientation.toLower() == "horizontal" ? Qt::Horizontal : Qt::Vertical);
+    // emit m_statusNotifierItem->scrollRequested(delta, dir);
+}