Add support for dbusmenu
authorManuel Nickschas <sputnick@quassel-irc.org>
Tue, 24 Aug 2010 07:22:44 +0000 (09:22 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Tue, 24 Aug 2010 07:22:44 +0000 (09:22 +0200)
If libdbusmenu-qt is present, Quassel should now export the tray menu via D-Bus.
Note that I could not test this as my KDE doesn't seem to care about dbusmenu here...
Note also that icons in the tray menu won't be displayed for now.

This also adds the new IconThemePath() method for the StatusNotifier.

CMakeLists.txt
cmake/modules/FindDBusMenuQt.cmake [new file with mode: 0644]
src/CMakeLists.txt
src/qtui/statusnotifieritem.cpp
src/qtui/statusnotifieritem.h
src/qtui/statusnotifieritemdbus.cpp
src/qtui/statusnotifieritemdbus.h

index a0a34c0..2e5faf0 100644 (file)
@@ -205,6 +205,19 @@ if(BUILD_GUI)
       set(CLIENT_QT4_VARS ${CLIENT_QT4_VARS} DBUS)
       set(CLIENT_COMPILE_FLAGS "${CLIENT_COMPILE_FLAGS} -DQT_DBUS_LIB")
       set(HAVE_DBUS true)
       set(CLIENT_QT4_VARS ${CLIENT_QT4_VARS} DBUS)
       set(CLIENT_COMPILE_FLAGS "${CLIENT_COMPILE_FLAGS} -DQT_DBUS_LIB")
       set(HAVE_DBUS true)
+
+      # check if we have dbusmenu as well
+      find_package(DBusMenuQt)
+      if(DBUSMENUQT_FOUND)
+        message(STATUS "Enabling support for exporting the tray menu via D-Bus")
+        add_definitions(-DHAVE_DBUSMENU)
+        include_directories(${DBUSMENUQT_INCLUDE_DIR})
+        set(CLIENT_LIBRARIES ${CLIENT_LIBRARIES} ${DBUSMENUQT_LIBRARIES})
+        set(CLIENT_COMPILE_FLAGS "${CLIENT_COMPILE_FLAGS} ${DBUSMENUQT_DEFINITIONS}")
+      else(DBUSMENUQT_FOUND)
+        message(STATUS "Disabling support for exporting the tray menu via D-Bus")
+      endif(DBUSMENUQT_FOUND)
+
     else(QT_QTDBUS_FOUND)
       message(STATUS "QtDBus not found, disabling D-Bus support")
     endif(QT_QTDBUS_FOUND)
     else(QT_QTDBUS_FOUND)
       message(STATUS "QtDBus not found, disabling D-Bus support")
     endif(QT_QTDBUS_FOUND)
@@ -235,7 +248,7 @@ if(BUILD_GUI)
       include_directories(${KDE4_INCLUDES})
       add_definitions(-DHAVE_KDE ${KDE4_DEFINITIONS})
       set(HAVE_KDE 1)
       include_directories(${KDE4_INCLUDES})
       add_definitions(-DHAVE_KDE ${KDE4_DEFINITIONS})
       set(HAVE_KDE 1)
-      set(QUASSEL_KDE_LIBRARIES ${KDE4_KDECORE_LIBS} ${KDE4_KDEUI_LIBRARY} ${KDE4_SOLID_LIBS} knotifyconfig)
+      set(CLIENT_LIBRARIES ${CLIENT_LIBRARIES} ${KDE4_KDECORE_LIBS} ${KDE4_KDEUI_LIBRARY} ${KDE4_SOLID_LIBS} knotifyconfig)
       # We always use external icons for KDE4 support, since we use its iconloader rather than our own
       set(EMBED_DATA OFF)
     else(KDE4_FOUND)
       # We always use external icons for KDE4 support, since we use its iconloader rather than our own
       set(EMBED_DATA OFF)
     else(KDE4_FOUND)
@@ -252,6 +265,8 @@ if(BUILD_GUI)
       if(PHONON_FOUND)
         message(STATUS "Enabling Phonon support")
         add_definitions(-DHAVE_PHONON)
       if(PHONON_FOUND)
         message(STATUS "Enabling Phonon support")
         add_definitions(-DHAVE_PHONON)
+        include_directories(${PHONON_INCLUDES})
+        set(CLIENT_LIBRARIES ${CLIENT_LIBRARIES} ${PHONON_LIBS})
         set(HAVE_PHONON true)
       else(PHONON_FOUND)
         message(STATUS "Phonon not found, disabling audio notifications")
         set(HAVE_PHONON true)
       else(PHONON_FOUND)
         message(STATUS "Phonon not found, disabling audio notifications")
@@ -268,6 +283,8 @@ if(BUILD_GUI)
       message(STATUS "Enabling Ayatana notification support")
       set(HAVE_INDICATEQT true)
       add_definitions(-DHAVE_INDICATEQT)
       message(STATUS "Enabling Ayatana notification support")
       set(HAVE_INDICATEQT true)
       add_definitions(-DHAVE_INDICATEQT)
+      link_directories(${INDICATEQT_LIBRARY_DIRS})
+      set(CLIENT_LIBRARIES ${CLIENT_LIBRARIES} ${INDICATEQT_LIBRARIES})
     else(INDICATEQT_FOUND)
       message(STATUS "Disabling Ayatana notification support")
     endif(INDICATEQT_FOUND)
     else(INDICATEQT_FOUND)
       message(STATUS "Disabling Ayatana notification support")
     endif(INDICATEQT_FOUND)
diff --git a/cmake/modules/FindDBusMenuQt.cmake b/cmake/modules/FindDBusMenuQt.cmake
new file mode 100644 (file)
index 0000000..82673b7
--- /dev/null
@@ -0,0 +1,36 @@
+# - Try to find dbusmenu-qt
+# Once done this will define
+#
+#  DBUSMENUQT_FOUND - system has dbusmenu-qt
+#  DBUSMENUQT_INCLUDE_DIR - the dbusmenu-qt include directory
+#  DBUSMENUQT_LIBRARIES - the libraries needed to use dbusmenu-qt
+#  DBUSMENUQT_DEFINITIONS - Compiler switches required for using dbusmenu-qt
+
+# Copyright (c) 2009, Canonical Ltd.
+# - Author: Aurélien Gâteau <aurelien.gateau@canonical.com>
+#
+# Based on FindQCA2.cmake
+# Copyright (c) 2006, Michael Larouche, <michael.larouche@kdemail.net>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+include(FindPackageHandleStandardArgs)
+
+find_package(PkgConfig)
+pkg_check_modules(PC_DBUSMENUQT QUIET dbusmenu-qt)
+set(DBUSMENUQT_DEFINITIONS ${PC_DBUSMENUQT_CFLAGS_OTHER})
+
+find_library(DBUSMENUQT_LIBRARIES
+    NAMES dbusmenu-qt dbusmenu-qtd
+    HINTS ${PC_DBUSMENUQT_LIBDIR} ${PC_DBUSMENUQT_LIBRARY_DIRS}
+    )
+
+find_path(DBUSMENUQT_INCLUDE_DIR dbusmenuexporter.h
+    HINTS ${PC_DBUSMENUQT_INCLUDEDIR} ${PC_DBUSMENUQT_INCLUDE_DIRS}
+    PATH_SUFFIXES dbusmenu-qt
+    )
+
+find_package_handle_standard_args(DBusMenuQt "Could not find dbusmenu-qt; available at https://launchpad.net/libdbusmenu-qt/" DBUSMENUQT_LIBRARIES DBUSMENUQT_INCLUDE_DIR)
+
+mark_as_advanced(DBUSMENUQT_INCLUDE_DIR DBUSMENUQT_LIBRARIES)
index ea2e15a..42cfe07 100644 (file)
@@ -28,10 +28,6 @@ qt4_add_resources(CLIENT_DEPS ${CLIENT_RCS})
 qt4_add_resources(CORE_DEPS ${CORE_RCS})
 qt4_add_resources(COMMON_DEPS ${COMMON_RCS})
 
 qt4_add_resources(CORE_DEPS ${CORE_RCS})
 qt4_add_resources(COMMON_DEPS ${COMMON_RCS})
 
-if(HAVE_INDICATEQT)
-  link_directories(${INDICATEQT_LIBRARY_DIRS})
-endif(HAVE_INDICATEQT)
-
 if(WANT_CORE)
   setup_qt4_variables(NETWORK SCRIPT SQL)
   add_executable(quasselcore common/main.cpp ${COMMON_DEPS} ${CORE_DEPS})
 if(WANT_CORE)
   setup_qt4_variables(NETWORK SCRIPT SQL)
   add_executable(quasselcore common/main.cpp ${COMMON_DEPS} ${CORE_DEPS})
@@ -52,7 +48,7 @@ if(WANT_QTCLIENT)
                                       COMPILE_FLAGS "-DQT_GUI_LIB -DQT_NETWORK_LIB ${CLIENT_COMPILE_FLAGS} -DBUILD_QTUI"
                                       OUTPUT_NAME ../quasselclient)
   target_link_libraries(quasselclient ${LINK_KDE} mod_qtui mod_uisupport mod_client mod_common ${CLIENT_LIBS}
                                       COMPILE_FLAGS "-DQT_GUI_LIB -DQT_NETWORK_LIB ${CLIENT_COMPILE_FLAGS} -DBUILD_QTUI"
                                       OUTPUT_NAME ../quasselclient)
   target_link_libraries(quasselclient ${LINK_KDE} mod_qtui mod_uisupport mod_client mod_common ${CLIENT_LIBS}
-                                      ${QUASSEL_QT_LIBRARIES} ${QUASSEL_KDE_LIBRARIES} ${QUASSEL_SSL_LIBRARIES} ${PHONON_LIBS} ${INDICATEQT_LIBRARIES})
+                                      ${QUASSEL_QT_LIBRARIES} ${QUASSEL_SSL_LIBRARIES} ${CLIENT_LIBRARIES})
   install(TARGETS quasselclient RUNTIME DESTINATION ${BIN_INSTALL_DIR})
 endif(WANT_QTCLIENT)
 
   install(TARGETS quasselclient RUNTIME DESTINATION ${BIN_INSTALL_DIR})
 endif(WANT_QTCLIENT)
 
@@ -65,7 +61,7 @@ if(WANT_MONO)
                                 COMPILE_FLAGS "-DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_SCRIPT_LIB -DQT_SQL_LIB ${CLIENT_COMPILE_FLAGS} -DBUILD_MONO"
                                 OUTPUT_NAME ../quassel)
   target_link_libraries(quassel mod_qtui mod_uisupport mod_client mod_core mod_common ${CLIENT_LIBS}
                                 COMPILE_FLAGS "-DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_SCRIPT_LIB -DQT_SQL_LIB ${CLIENT_COMPILE_FLAGS} -DBUILD_MONO"
                                 OUTPUT_NAME ../quassel)
   target_link_libraries(quassel mod_qtui mod_uisupport mod_client mod_core mod_common ${CLIENT_LIBS}
-                                ${QUASSEL_QT_LIBRARIES} ${QUASSEL_KDE_LIBRARIES} ${QUASSEL_SSL_LIBRARIES} ${PHONON_LIBS} ${INDICATEQT_LIBRARIES})
+                                ${QUASSEL_QT_LIBRARIES} ${QUASSEL_SSL_LIBRARIES} ${CLIENT_LIBRARIES})
   install(TARGETS quassel RUNTIME DESTINATION ${BIN_INSTALL_DIR})
 endif(WANT_MONO)
 
   install(TARGETS quassel RUNTIME DESTINATION ${BIN_INSTALL_DIR})
 endif(WANT_MONO)
 
index 8d7972f..08197f8 100644 (file)
 
 #ifdef HAVE_DBUS
 
 
 #ifdef HAVE_DBUS
 
-#include "statusnotifieritem.h"
-#include "statusnotifieritemdbus.h"
-
 #include <QApplication>
 #include <QMenu>
 #include <QMouseEvent>
 #include <QTextDocument>
 
 #include <QApplication>
 #include <QMenu>
 #include <QMouseEvent>
 #include <QTextDocument>
 
+#include "quassel.h"
+#include "statusnotifieritem.h"
+#include "statusnotifieritemdbus.h"
+
 const int StatusNotifierItem::_protocolVersion = 0;
 
 const int StatusNotifierItem::_protocolVersion = 0;
 
+#ifdef HAVE_DBUSMENU
+#  include "dbusmenuexporter.h"
+
+/**
+ * Specialization to provide access to icon names
+ */
+class QuasselDBusMenuExporter : public DBusMenuExporter {
+public:
+  QuasselDBusMenuExporter(const QString &dbusObjectPath, QMenu *menu, const QDBusConnection &dbusConnection)
+    : DBusMenuExporter(dbusObjectPath, menu, dbusConnection)
+  {}
+
+protected:
+  virtual QString iconNameForAction(QAction *action) { // TODO Qt 4.7: fixme when we have converted our iconloader
+    Icon icon(action->icon());
+#if QT_VERSION >= 0x040701
+    // QIcon::name() is in the 4.7 git branch, but it is not in 4.7 TP.
+    // If you get a build error here, you need to update your pre-release
+    // of Qt 4.7.
+    return icon.isNull() ? QString() : icon.name();
+#else
+    return QString();
+#endif
+  }
+};
+
+#endif /* HAVE_DBUSMENU */
+
 StatusNotifierItem::StatusNotifierItem(QWidget *parent)
   : StatusNotifierItemParent(parent),
   _statusNotifierItemDBus(0),
 StatusNotifierItem::StatusNotifierItem(QWidget *parent)
   : StatusNotifierItemParent(parent),
   _statusNotifierItemDBus(0),
@@ -76,13 +105,20 @@ void StatusNotifierItem::init() {
 
   StatusNotifierItemParent::init();
   trayMenu()->installEventFilter(this);
 
   StatusNotifierItemParent::init();
   trayMenu()->installEventFilter(this);
+
+  // use the appdata icon folder for now
+  _iconThemePath = Quassel::findDataFilePath("icons");
+
+#ifdef HAVE_DBUSMENU
+  _menuObjectPath = "/MenuBar";
+  new QuasselDBusMenuExporter(menuObjectPath(), trayMenu(), _statusNotifierItemDBus->dbusConnection()); // will be added as menu child
+#endif
 }
 
 void StatusNotifierItem::registerToDaemon() {
   if(!_statusNotifierWatcher) {
     QString interface("org.kde.StatusNotifierWatcher");
 }
 
 void StatusNotifierItem::registerToDaemon() {
   if(!_statusNotifierWatcher) {
     QString interface("org.kde.StatusNotifierWatcher");
-    _statusNotifierWatcher = new org::kde::StatusNotifierWatcher(interface, "/StatusNotifierWatcher",
-                                                                 QDBusConnection::sessionBus());
+    _statusNotifierWatcher = new org::kde::StatusNotifierWatcher(interface, "/StatusNotifierWatcher", QDBusConnection::sessionBus());
   }
   if(_statusNotifierWatcher->isValid()
     && _statusNotifierWatcher->property("ProtocolVersion").toInt() == _protocolVersion) {
   }
   if(_statusNotifierWatcher->isValid()
     && _statusNotifierWatcher->property("ProtocolVersion").toInt() == _protocolVersion) {
@@ -201,6 +237,14 @@ QString StatusNotifierItem::toolTipIconName() const {
   return QString("quassel");
 }
 
   return QString("quassel");
 }
 
+QString StatusNotifierItem::iconThemePath() const {
+  return _iconThemePath;
+}
+
+QString StatusNotifierItem::menuObjectPath() const {
+  return _menuObjectPath;
+}
+
 void StatusNotifierItem::activated(const QPoint &pos) {
   Q_UNUSED(pos)
   activate(Trigger);
 void StatusNotifierItem::activated(const QPoint &pos) {
   Q_UNUSED(pos)
   activate(Trigger);
index 1ca4e4a..b6c69ca 100644 (file)
@@ -63,6 +63,8 @@ protected:
   QString iconName() const;
   QString attentionIconName() const;
   QString toolTipIconName() const;
   QString iconName() const;
   QString attentionIconName() const;
   QString toolTipIconName() const;
+  QString iconThemePath() const;
+  QString menuObjectPath() const;
 
   virtual bool eventFilter(QObject *watched, QEvent *event);
 
 
   virtual bool eventFilter(QObject *watched, QEvent *event);
 
@@ -85,6 +87,9 @@ private:
   quint32 _lastNotificationsDBusId;
   QHash<uint, uint> _notificationsIdMap; ///< Maps our own notification ID to the D-Bus one
 
   quint32 _lastNotificationsDBusId;
   QHash<uint, uint> _notificationsIdMap; ///< Maps our own notification ID to the D-Bus one
 
+  QString _iconThemePath;
+  QString _menuObjectPath;
+
   friend class StatusNotifierItemDBus;
 };
 
   friend class StatusNotifierItemDBus;
 };
 
index 28f5dda..e359c45 100644 (file)
 #include "statusnotifierwatcher.h"
 #include "statusnotifieritemadaptor.h"
 
 #include "statusnotifierwatcher.h"
 #include "statusnotifieritemadaptor.h"
 
-#ifdef Q_OS_WIN64    
-__inline int toInt(WId wid) 
+#ifdef Q_OS_WIN64
+__inline int toInt(WId wid)
 {
         return (int)((__int64)wid);
 }
 
 #else
 {
         return (int)((__int64)wid);
 }
 
 #else
-__inline int toInt(WId wid) 
+__inline int toInt(WId wid)
 {
         return (int)wid;
 }
 {
         return (int)wid;
 }
-#endif        
+#endif
 
 // Marshall the ImageStruct data into a D-BUS argument
 const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageStruct &icon)
 
 // Marshall the ImageStruct data into a D-BUS argument
 const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageStruct &icon)
@@ -170,6 +170,11 @@ StatusNotifierItemDBus::~StatusNotifierItemDBus()
     unregisterService();
 }
 
     unregisterService();
 }
 
+QDBusConnection StatusNotifierItemDBus::dbusConnection() const
+{
+    return m_dbus;
+}
+
 // FIXME: prevent double registrations, also test this on platforms != KDE
 //
 void StatusNotifierItemDBus::registerService()
 // FIXME: prevent double registrations, also test this on platforms != KDE
 //
 void StatusNotifierItemDBus::registerService()
@@ -275,6 +280,19 @@ DBusToolTipStruct StatusNotifierItemDBus::ToolTip() const
     return toolTip;
 }
 
     return toolTip;
 }
 
+QString StatusNotifierItemDBus::IconThemePath() const
+{
+    return m_statusNotifierItem->iconThemePath();
+}
+
+//Menu
+
+QDBusObjectPath StatusNotifierItemDBus::Menu() const
+{
+    return QDBusObjectPath(m_statusNotifierItem->menuObjectPath());
+}
+
+
 //Interaction
 
 void StatusNotifierItemDBus::ContextMenu(int x, int y)
 //Interaction
 
 void StatusNotifierItemDBus::ContextMenu(int x, int y)
index 2fcefda..d033c9c 100644 (file)
@@ -63,12 +63,19 @@ class StatusNotifierItemDBus : public QObject
     Q_PROPERTY(DBusImageVector AttentionIconPixmap READ AttentionIconPixmap)
     Q_PROPERTY(QString AttentionMovieName READ AttentionMovieName)
     Q_PROPERTY(DBusToolTipStruct ToolTip READ ToolTip)
     Q_PROPERTY(DBusImageVector AttentionIconPixmap READ AttentionIconPixmap)
     Q_PROPERTY(QString AttentionMovieName READ AttentionMovieName)
     Q_PROPERTY(DBusToolTipStruct ToolTip READ ToolTip)
+    Q_PROPERTY(QString IconThemePath READ IconThemePath)
+    Q_PROPERTY(QDBusObjectPath Menu READ Menu)
 
     friend class StatusNotifierItem;
 public:
     StatusNotifierItemDBus(StatusNotifierItem *parent);
     ~StatusNotifierItemDBus();
 
 
     friend class StatusNotifierItem;
 public:
     StatusNotifierItemDBus(StatusNotifierItem *parent);
     ~StatusNotifierItemDBus();
 
+    /**
+     * @return the dbus connection used by this object
+     */
+    QDBusConnection dbusConnection() const;
+
     /**
      * Register the service to DBus
      */
     /**
      * Register the service to DBus
      */
@@ -155,6 +162,15 @@ public:
      */
     DBusToolTipStruct ToolTip() const;
 
      */
     DBusToolTipStruct ToolTip() const;
 
+    /**
+     * @return path to extra icon theme, to load application specific icons
+     */
+    QString IconThemePath() const;
+
+    /**
+     * @return object path to the dbusmenu object
+     */
+    QDBusObjectPath Menu() const;
 
 public Q_SLOTS:
     //interaction
 
 public Q_SLOTS:
     //interaction