Refactor DBus IPC to allow for further extensibility

This commit is contained in:
Mike Gelfand
2015-12-16 17:57:05 +00:00
parent 9853eb6715
commit dfc32f3ecd
6 changed files with 156 additions and 95 deletions

View File

@@ -11,9 +11,8 @@
#include <iostream> #include <iostream>
#include <QDBusConnection> #include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusError>
#include <QDBusMessage> #include <QDBusMessage>
#include <QDBusReply>
#include <QIcon> #include <QIcon>
#include <QLibraryInfo> #include <QLibraryInfo>
#include <QMessageBox> #include <QMessageBox>
@@ -28,7 +27,7 @@
#include "AddData.h" #include "AddData.h"
#include "Application.h" #include "Application.h"
#include "DBusAdaptor.h" #include "DBusInteropHelper.h"
#include "Formatter.h" #include "Formatter.h"
#include "MainWindow.h" #include "MainWindow.h"
#include "OptionsDialog.h" #include "OptionsDialog.h"
@@ -39,10 +38,6 @@
namespace namespace
{ {
const QString DBUS_SERVICE = QString::fromUtf8 ("com.transmissionbt.Transmission" );
const QString DBUS_OBJECT_PATH = QString::fromUtf8 ("/com/transmissionbt/Transmission");
const QString DBUS_INTERFACE = QString::fromUtf8 ("com.transmissionbt.Transmission" );
const QLatin1String MY_CONFIG_NAME ("transmission"); const QLatin1String MY_CONFIG_NAME ("transmission");
const QLatin1String MY_READABLE_NAME ("transmission-qt"); const QLatin1String MY_READABLE_NAME ("transmission-qt");
@@ -162,41 +157,38 @@ Application::Application (int& argc, char ** argv):
// try to delegate the work to an existing copy of Transmission // try to delegate the work to an existing copy of Transmission
// before starting ourselves... // before starting ourselves...
QDBusConnection bus = QDBusConnection::sessionBus (); DBusInteropHelper interopClient;
if (bus.isConnected ()) if (interopClient.isConnected ())
{ {
bool delegated = false; bool delegated = false;
for (const QString& filename: filenames) for (const QString& filename: filenames)
{ {
QDBusMessage request = QDBusMessage::createMethodCall (DBUS_SERVICE, QString metainfo;
DBUS_OBJECT_PATH,
DBUS_INTERFACE,
QString::fromUtf8 ("AddMetainfo"));
QList<QVariant> arguments;
AddData a (filename);
switch (a.type)
{
case AddData::URL: arguments.push_back (a.url.toString ()); break;
case AddData::MAGNET: arguments.push_back (a.magnet); break;
case AddData::FILENAME: arguments.push_back (QString::fromLatin1 (a.toBase64 ())); break;
case AddData::METAINFO: arguments.push_back (QString::fromLatin1 (a.toBase64 ())); break;
default: break;
}
request.setArguments (arguments);
QDBusMessage response = bus.call (request); AddData a (filename);
//std::cerr << qPrintable (response.errorName ()) << std::endl; switch (a.type)
//std::cerr << qPrintable (response.errorMessage ()) << std::endl; {
arguments = response.arguments (); case AddData::URL: metainfo = a.url.toString (); break;
delegated |= (arguments.size ()==1) && arguments[0].toBool (); case AddData::MAGNET: metainfo = a.magnet; break;
} case AddData::FILENAME: metainfo = QString::fromLatin1 (a.toBase64 ()); break;
case AddData::METAINFO: metainfo = QString::fromLatin1 (a.toBase64 ()); break;
default: break;
}
if (delegated) if (metainfo.isEmpty ())
{ continue;
quitLater ();
return; const QVariant result = interopClient.addMetainfo (metainfo);
} if (result.isValid () && result.toBool ())
} delegated = true;
}
if (delegated)
{
quitLater ();
return;
}
}
// set the fallback config dir // set the fallback config dir
if (configDir.isNull ()) if (configDir.isNull ())
@@ -302,15 +294,7 @@ Application::Application (int& argc, char ** argv):
for (const QString& filename: filenames) for (const QString& filename: filenames)
addTorrent (filename); addTorrent (filename);
// register as the dbus handler for Transmission DBusInteropHelper::registerObject (this);
if (bus.isConnected ())
{
new DBusAdaptor (this);
if (!bus.registerService (DBUS_SERVICE))
std::cerr << "couldn't register " << qPrintable (DBUS_SERVICE) << std::endl;
if (!bus.registerObject (DBUS_OBJECT_PATH, this))
std::cerr << "couldn't register " << qPrintable (DBUS_OBJECT_PATH) << std::endl;
}
} }
void void
@@ -558,32 +542,31 @@ Application::raise ()
bool bool
Application::notifyApp (const QString& title, const QString& body) const Application::notifyApp (const QString& title, const QString& body) const
{ {
const QLatin1String dbusServiceName ("org.freedesktop.Notifications");
const QLatin1String dbusInterfaceName ("org.freedesktop.Notifications");
const QLatin1String dbusPath ("/org/freedesktop/Notifications");
QDBusConnection bus = QDBusConnection::sessionBus (); QDBusConnection bus = QDBusConnection::sessionBus ();
if (!bus.isConnected ()) if (bus.isConnected ())
{ {
myWindow->trayIcon ().showMessage (title, body); QDBusMessage m = QDBusMessage::createMethodCall (dbusServiceName, dbusPath, dbusInterfaceName, QLatin1String ("Notify"));
return true; QVariantList args;
args.append (QLatin1String ("Transmission")); // app_name
args.append (0U); // replaces_id
args.append (QLatin1String ("transmission")); // icon
args.append (title); // summary
args.append (body); // body
args.append (QStringList ()); // actions - unused for plain passive popups
args.append (QVariantMap ()); // hints - unused atm
args.append (static_cast<int32_t> (-1)); // use the default timeout period
m.setArguments (args);
const QDBusReply<quint32> replyMsg = bus.call (m);
if (replyMsg.isValid () && replyMsg.value () > 0)
return true;
} }
const QString dbusServiceName = QString::fromUtf8 ("org.freedesktop.Notifications"); myWindow->trayIcon ().showMessage (title, body);
const QString dbusInterfaceName = QString::fromUtf8 ("org.freedesktop.Notifications"); return true;
const QString dbusPath = QString::fromUtf8 ("/org/freedesktop/Notifications");
QDBusMessage m = QDBusMessage::createMethodCall (dbusServiceName, dbusPath, dbusInterfaceName, QString::fromUtf8 ("Notify"));
QList<QVariant> args;
args.append (QString::fromUtf8 ("Transmission")); // app_name
args.append (0U); // replaces_id
args.append (QString::fromUtf8 ("transmission")); // icon
args.append (title); // summary
args.append (body); // body
args.append (QStringList ()); // actions - unused for plain passive popups
args.append (QVariantMap ()); // hints - unused atm
args.append (static_cast<int32_t> (-1)); // use the default timeout period
m.setArguments (args);
QDBusMessage replyMsg = bus.call (m);
//std::cerr << qPrintable (replyMsg.errorName ()) << std::endl;
//std::cerr << qPrintable (replyMsg.errorMessage ()) << std::endl;
return (replyMsg.type () == QDBusMessage::ReplyMessage) && !replyMsg.arguments ().isEmpty ();
} }
FaviconCache& Application::faviconCache () FaviconCache& Application::faviconCache ()

View File

@@ -29,7 +29,7 @@ set(${PROJECT_NAME}_SOURCES
AddData.cc AddData.cc
Application.cc Application.cc
ColumnResizer.cc ColumnResizer.cc
DBusAdaptor.cc DBusInteropHelper.cc
DetailsDialog.cc DetailsDialog.cc
FaviconCache.cc FaviconCache.cc
FileTreeDelegate.cc FileTreeDelegate.cc
@@ -44,6 +44,7 @@ set(${PROJECT_NAME}_SOURCES
Formatter.cc Formatter.cc
FreeSpaceLabel.cc FreeSpaceLabel.cc
IconToolButton.cc IconToolButton.cc
InteropObject.cc
LicenseDialog.cc LicenseDialog.cc
MainWindow.cc MainWindow.cc
MakeDialog.cc MakeDialog.cc
@@ -77,7 +78,7 @@ set(${PROJECT_NAME}_HEADERS
BaseDialog.h BaseDialog.h
ColumnResizer.h ColumnResizer.h
CustomVariantType.h CustomVariantType.h
DBusAdaptor.h DBusInteropHelper.h
DetailsDialog.h DetailsDialog.h
FaviconCache.h FaviconCache.h
FileTreeDelegate.h FileTreeDelegate.h
@@ -92,6 +93,7 @@ set(${PROJECT_NAME}_HEADERS
Formatter.h Formatter.h
FreeSpaceLabel.h FreeSpaceLabel.h
IconToolButton.h IconToolButton.h
InteropObject.h
LicenseDialog.h LicenseDialog.h
MainWindow.h MainWindow.h
MakeDialog.h MakeDialog.h

56
qt/DBusInteropHelper.cc Normal file
View File

@@ -0,0 +1,56 @@
/*
* This file Copyright (C) 2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
*
* $Id$
*/
#include <iostream>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusReply>
#include <QString>
#include <QVariant>
#include "DBusInteropHelper.h"
#include "InteropObject.h"
namespace
{
const QLatin1String DBUS_SERVICE ("com.transmissionbt.Transmission");
const QLatin1String DBUS_OBJECT_PATH ("/com/transmissionbt/Transmission");
const QLatin1String DBUS_INTERFACE ("com.transmissionbt.Transmission");
}
bool
DBusInteropHelper::isConnected () const
{
return !QDBusConnection::sessionBus ().isConnected ();
}
QVariant
DBusInteropHelper::addMetainfo (const QString& metainfo)
{
QDBusMessage request = QDBusMessage::createMethodCall (DBUS_SERVICE, DBUS_OBJECT_PATH,
DBUS_INTERFACE, QLatin1String ("AddMetainfo"));
request.setArguments (QVariantList () << metainfo);
const QDBusReply<bool> response = QDBusConnection::sessionBus ().call (request);
return response.isValid () ? QVariant (response.value ()) : QVariant ();
}
void
DBusInteropHelper::registerObject (QObject * parent)
{
QDBusConnection bus = QDBusConnection::sessionBus ();
if (!bus.isConnected ())
return;
if (!bus.registerService (DBUS_SERVICE))
std::cerr << "couldn't register " << qPrintable (DBUS_SERVICE) << std::endl;
if (!bus.registerObject (DBUS_OBJECT_PATH, new InteropObject (parent), QDBusConnection::ExportAllSlots))
std::cerr << "couldn't register " << qPrintable (DBUS_OBJECT_PATH) << std::endl;
}

27
qt/DBusInteropHelper.h Normal file
View File

@@ -0,0 +1,27 @@
/*
* This file Copyright (C) 2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
*
* $Id$
*/
#ifndef QTR_DBUS_INTEROP_HELPER_H
#define QTR_DBUS_INTEROP_HELPER_H
class QObject;
class QString;
class QVariant;
class DBusInteropHelper
{
public:
bool isConnected () const;
QVariant addMetainfo (const QString& metainfo);
static void registerObject (QObject * parent);
};
#endif // QTR_DBUS_INTEROP_HELPER_H

View File

@@ -9,28 +9,27 @@
#include "AddData.h" #include "AddData.h"
#include "Application.h" #include "Application.h"
#include "DBusAdaptor.h" #include "InteropObject.h"
DBusAdaptor::DBusAdaptor (Application* app): InteropObject::InteropObject (QObject * parent):
QDBusAbstractAdaptor (app), QObject (parent)
myApp (app)
{ {
} }
bool bool
DBusAdaptor::PresentWindow () InteropObject::PresentWindow ()
{ {
myApp->raise (); qApp->raise ();
return true; return true;
} }
bool bool
DBusAdaptor::AddMetainfo (const QString& key) InteropObject::AddMetainfo (const QString& metainfo)
{ {
AddData addme (key); AddData addme (metainfo);
if (addme.type != addme.NONE) if (addme.type != addme.NONE)
myApp->addTorrent (addme); qApp->addTorrent (addme);
return true; return true;
} }

View File

@@ -7,28 +7,22 @@
* $Id$ * $Id$
*/ */
#ifndef QTR_DBUS_ADAPTOR_H #ifndef QTR_INTEROP_OBJECT_H
#define QTR_DBUS_ADAPTOR_H #define QTR_INTEROP_OBJECT_H
#include <QDBusAbstractAdaptor> #include <QObject>
class Application; class InteropObject: public QObject
class DBusAdaptor: public QDBusAbstractAdaptor
{ {
Q_OBJECT Q_OBJECT
Q_CLASSINFO ("D-Bus Interface", "com.transmissionbt.Transmission") Q_CLASSINFO ("D-Bus Interface", "com.transmissionbt.Transmission")
public: public:
DBusAdaptor (Application *); InteropObject (QObject * parent = nullptr);
virtual ~DBusAdaptor () {}
public slots: public slots:
bool PresentWindow (); bool PresentWindow ();
bool AddMetainfo (const QString&); bool AddMetainfo (const QString& metainfo);
private:
Application * myApp;
}; };
#endif // QTR_DBUS_ADAPTOR_H #endif // QTR_INTEROP_OBJECT_H