Skip to content
Snippets Groups Projects
Commit aa2b04bb authored by Giacomo Strangolino's avatar Giacomo Strangolino
Browse files

imported from github cumbia-libs/qumbia-plugins/cumbia-dbus v2.2.1

parents
No related branches found
No related tags found
No related merge requests found
This diff is collapsed.
README 0 → 100644
These classes have been introduced with QTango version 4.2.0
They provide adaptors and interfaces to the DBus session bus,
to allow QTango applications to interact with each other.
TApplicationAdaptor.xml provides the interface to TApplication.
From TApplicationAdaptor.xml it is possible to generate TApplicationAdaptor.h,
TApplicationInterface.h and TApplicationInterface.cpp, by means
of the qdbusxml2cpp utility.
Since the arguments involved in many methods of the interface are
of QDBusVariant type, it is not possible to correctly and straightforward
generate the cpp implementation for TApplicationAdaptor.
So the command line used to generate the interface is
qdbusxml2cpp TApplicationAdaptor.xml -c TApplicationInterface -p TApplicationInterface
while to generate the adaptor, use
qdbusxml2cpp TApplicationAdaptor.xml -a TApplicationAdaptor.h -c TApplicationAdaptor
Using "-a TApplicationAdaptor.h" makes qdbusxml2cpp generate the class declaration AND
implementation inside the TApplicationAdaptor.h generated file.
You must then manually remove the implementation from the .h file, and add it to the
.cpp when the interface is updted adding or removing methods.
NOTE:
qdbusxml2cpp TApplicationAdaptor.xml -a TApplicationAdaptor -c TApplicationAdaptor
would generate .h and .cpp separate files, but the .cpp file would overwrite the
current implementation thus preventing things from working because of QDBusVariant
arguments, as hinted above.
NOTE (II):
Interface generation changes from Qt 4.3 to later releases. On Qt 4.6 qdbusxml2cpp
generates QDBusPendingReply instead of QDBusReply, and this is not backward compatible.
NOTE (III): when generating interface, note that QDBusReply<> is not accepted.
You must reply <> with <void>
# $Id: dbus.pro,v 1.9 2014-08-28 13:23:45 giacomo Exp $
# $Name $
include(../qumbia-plugins.pri)
include ($${INSTALL_ROOT}/include/cumbia-qtcontrols/cumbia-qtcontrols.pri)
TEMPLATE = lib
CONFIG += plugin
isEmpty(buildtype) {
buildtype = release
} else {
equals(buildtype, debug) {
message("")
message("debug build")
message("")
}
}
CONFIG += $${buildtype}
QT += dbus xml
INCLUDEPATH = src $${INCLUDEPATH}
DBUS_ADAPTORS += src/cumbiadbus.xml
DBUS_INTERFACES += src/cumbiadbus.xml
TARGET = $$qtLibraryTarget(cumbia-dbus-plugin)
DEFINES -= QT_NO_DEBUG_OUTPUT
# Input
HEADERS += \
src/cumbiadbusplugin.h \
src/quappdbus.h \
src/quappdbuscontroller.h
SOURCES += \
src/cumbiadbusplugin.cpp \
src/quappdbus.cpp \
src/quappdbuscontroller.cpp
inc.files += $${HEADERS} cumbiadbus_interface.h
DISTFILES += \
quapplication.xml
# qumbia-plugins.pri defines default INSTALLS for target inc and doc
# doc commands, target.path and inc.path are defined there as well.
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="local.QuApplication">
<signal name="dbusRegistered">
<arg name="exename" type="s" direction="out"/>
<arg name="args" type="as" direction="out"/>
<arg name="dbus_servicenam" type="s" direction="out"/>
<arg name="display_host" type="s" direction="out"/>
<arg name="display_number" type="i" direction="out"/>
<arg name="screen_number" type="i" direction="out"/>
<arg name="is_plat_x11" type="b" direction="out"/>
</signal>
<signal name="dbusUnregistered">
<arg name="exename" type="s" direction="out"/>
<arg name="args" type="as" direction="out"/>
<arg name="dbus_servicenam" type="s" direction="out"/>
<arg name="display_host" type="s" direction="out"/>
<arg name="display_number" type="i" direction="out"/>
<arg name="screen_number" type="i" direction="out"/>
<arg name="is_plat_x11" type="b" direction="out"/>
</signal>
<method name="raise">
</method>
<method name="minimize">
</method>
<method name="quit">
</method>
<method name="arguments">
<arg type="as" direction="out"/>
</method>
<method name="exename">
<arg type="s" direction="out"/>
</method>
<method name="cmdOpt">
<arg type="as" direction="out"/>
</method>
<method name="display_host">
<arg type="s" direction="out"/>
</method>
<method name="display_number">
<arg type="i" direction="out"/>
</method>
<method name="screen_number">
<arg type="i" direction="out"/>
</method>
<method name="isPlatformX11">
<arg type="b" direction="out"/>
</method>
</interface>
</node>
#include "cumbiadbusplugin.h"
#include "quappdbus.h"
#include "quappdbuscontroller.h"
#include <cumacros.h>
#include <QtDebug>
#include <QDBusConnection>
#include <QDBusError>
#include <errno.h>
#include <QUrl>
#include <QStringList>
#include <unistd.h>
#include "cumbiadbus_adaptor.h"
CumbiaDBusPlugin::CumbiaDBusPlugin(QObject *parent) : QObject(parent)
{
}
QuAppDBusInterface *CumbiaDBusPlugin::getAppIface() const
{
return new QuAppDBus();
}
QuAppDBusControllerInterface *CumbiaDBusPlugin::getAppCtrlIface() const
{
return new QuAppDBusController();
}
#ifndef CUMBIADBUSPLUGIN_H
#define CUMBIADBUSPLUGIN_H
#include <QObject>
#include <QtPlugin>
#include "quapplication.h"
#include "qudbusplugininterface.h"
class CumbiaDBusPlugin : public QObject, QuDBusPluginInterface
{
Q_OBJECT
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "eu.elettra.qudbus.QuDBusPluginInterface" FILE "cumbiadbusplugin.json")
#endif
Q_INTERFACES(QuDBusPluginInterface)
public:
explicit CumbiaDBusPlugin(QObject *parent = NULL);
// QuDBusPluginInterface interface
public:
QuAppDBusInterface *getAppIface() const;
QuAppDBusControllerInterface *getAppCtrlIface() const;
};
#endif // CUMBIADBUSPLUGIN_H
{}
#include "quappdbus.h"
#include <quapplication.h>
#include <cumacros.h>
#include <QtDebug>
#include <QDBusConnection>
#include <QApplication>
#include <QDBusError>
#include <errno.h>
#include <QUrl>
#include <QStringList>
#include <unistd.h>
#include "../cumbiadbus_adaptor.h"
QuAppDBus::QuAppDBus(QObject *parent) : QObject(parent)
{
}
/** \brief Register a QuApplication on the DBus service.
*
* @param app a reference to the QuApplication to be registered.
*
* The application is registered with a service name formed by:
* "eu.elettra." + hostname + ".display" + $DISPLAY + ".quapplication.pid" + getpid() + "." + appname
*
* The getServiceName method provides the service name string.
*
* @see unregisterApp
*
*/
void QuAppDBus::registerApp(QuApplication *app)
{
QStringList args = app->arguments();
args.removeFirst();
new QuApplicationAdaptor(app);
QDBusConnection connection = QDBusConnection::sessionBus();
QString serviceName = getServiceName(app);
bool ret = connection.registerObject("/QuApplication", app);
if(ret)
ret = connection.registerService(serviceName);
if(!ret)
perr("QuAppDBus.registerApp: failed to register app \%s\" with DBus (\"%s\"): %s [%s]",
qstoc(app->applicationName()), qstoc(getServiceName(app)),
qstoc(connection.lastError().name()), qstoc(connection.lastError().message()));
if(ret)
emit onAppRegistered(app->arguments().first(), args, serviceName);
}
/** \brief unregister the QuApplication from the DBus service
*
* Unregisters the application with the service name returned by getServiceName, which is the
* same method used by registerApp in the registration phase.
*
* @see registerApp
*/
void QuAppDBus::unregisterApp(QuApplication *app)
{
QStringList args = app->arguments();
args.removeFirst();
emit onAppUnregistered(app->arguments().first(), args, getServiceName(app));
}
QString QuAppDBus::getServiceName(QuApplication* app) const
{
QString dbus_servicenam;
char hostname[256] = "unknown_host";
char *display;
QString qsdisplay;
QString appname;
QStringList params(app->arguments());
params.removeFirst();
appname = app->arguments().at(0);
if(appname.contains("/"))
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
appname = appname.split("/", Qt::SkipEmptyParts).last();
#else
appname = appname.split("/", QString::SkipEmptyParts).last();
#endif
if(gethostname(hostname, 256))
perr("QuAppDBus.getServiceName: hostname unavailable");
display = getenv("DISPLAY");
if(!display)
printf("QuAppDBus.getServiceName: DISPLAY env variable unavailable");
else
qsdisplay = QString(display).remove(QRegularExpression("\\.\\d*")).remove(":");
dbus_servicenam = "eu.elettra." + QString(hostname) + ".display" + qsdisplay +
".quapplication.pid" + QString::number(getpid()) + "." + appname ;
cuprintf("QuAppDBus.getServiceName: service name \"%s\"\n", qstoc(dbus_servicenam));
return dbus_servicenam;
}
#ifndef QUAPPDBUS_H
#define QUAPPDBUS_H
#include <qudbusplugininterface.h>
#include <QString>
class QuApplication;
/** \brief An implementation of QuAppDBusInterface to register and unregister an application.
*
*/
class QuAppDBus : public QObject, public QuAppDBusInterface
{
Q_OBJECT
public:
QuAppDBus(QObject* parent = NULL);
// QuAppDBusInterface interface
public:
void registerApp(QuApplication *app);
void unregisterApp(QuApplication *app);
QString getServiceName(QuApplication *app) const;
signals:
void onAppRegistered(const QString &name, const QStringList &args, const QString& dbusServiceNam);
void onAppUnregistered(const QString& name, const QStringList& args, const QString& dbusServiceNam);
private:
};
#endif // QUAPPDBUS_H
#include "quappdbuscontroller.h"
#include "quappdbus.h"
#include "cumbiadbus_interface.h"
#include <QDBusReply>
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusInterface>
#include <QList>
#include <cumacros.h>
#define SERVICE_NAME "eu.elettra.quappdbus.controller"
class QuAppDBusControllerPrivate
{
public:
QDBusConnectionInterface *dbus_if;
QList<QuAppDBusControllerListener *> ctrl_listeners;
};
QuAppDBusController::QuAppDBusController(QObject *parent) : QObject(parent)
{
d = new QuAppDBusControllerPrivate;
d->dbus_if = NULL;
d->dbus_if = m_getDbusConnectionInterface();
}
QuAppDBusController::~QuAppDBusController()
{
if(d->dbus_if)
d->dbus_if->unregisterService(SERVICE_NAME);
delete d;
}
QStringList QuAppDBusController::args_noPath(const QStringList &args) const
{
QStringList ret;
if(args.size() > 0)
{
QString exe = args.first();
if(exe.count('/') > 0)
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
exe = exe.split('/', Qt::SkipEmptyParts).last();
#else
exe = exe.split('/', QString::SkipEmptyParts).last();
#endif
ret << exe;
}
for(int i = 1; i < args.size(); i++)
ret << args[i];
return ret;
}
/** Find information about a cumbia-qtcontrols QuApplication currently in execution with the given arguments
*
* @param args a the application arguments, including argv[0].
* If the first argument contains the full path, this is discarded, so that only the executable
* name is taken into account.
* The following arguments are argv[1], argv[2], ...
* If args is an empty list, then all applications registered as <em>quapplication</em> in the
* session bus are returned.
*
* @return a list of QuAppInfo with the list of applications matching args
*
*/
QList<QuAppInfo> QuAppDBusController::findApps(const QStringList &search_app_args)
{
QList<QuAppInfo> il;
if(!d->dbus_if)
return il;
QDBusReply<QStringList> services = d->dbus_if->registeredServiceNames();
if(services.isValid())
{
/* populate the refreshed information list */
foreach(QString service, services.value())
{
if(service.contains("quapplication"))
{
LocalQuApplicationInterface quappdbusi(service, "/QuApplication", QDBusConnection::sessionBus(), this);
if(quappdbusi.isValid())
{
/* retrieve pid from service */
QDBusReply<QStringList> argsReply = quappdbusi.arguments();
QString display_host = quappdbusi.display_host();
int display_number = quappdbusi.display_number();
int screen_number = quappdbusi.screen_number();
bool is_plat_x11 = quappdbusi.isPlatformX11();
if(!argsReply.isValid())
perr("QuAppDBusController.findApps: reply error: %s", qstoc(argsReply.error().message()));
else
{
QStringList in_args(search_app_args);
if(in_args.size() > 0 && in_args.first().count("/") > 0)
in_args = args_noPath(in_args);
QStringList arguments = args_noPath(argsReply.value());
if(search_app_args.isEmpty() || arguments == args_noPath(search_app_args))
il.append(QuAppInfo(arguments, service, display_host, display_number, screen_number, is_plat_x11));
}
}
}
}
}
return il;
}
void QuAppDBusController::close(const QuAppInfo &ai)
{
LocalQuApplicationInterface quappdbusi(ai.dbusServiceName(), "/QuApplication", QDBusConnection::sessionBus(), this);
quappdbusi.quit();
}
void QuAppDBusController::raise(const QuAppInfo &ai)
{
LocalQuApplicationInterface quappdbusi(ai.dbusServiceName(), "/QuApplication", QDBusConnection::sessionBus(), this);
quappdbusi.raise();
}
void QuAppDBusController::start_monitor(const QString &serviceName)
{
LocalQuApplicationInterface *quappdbusi =
new LocalQuApplicationInterface(serviceName, "/QuApplication", QDBusConnection::sessionBus(), this);
connect(quappdbusi, SIGNAL(dbusRegistered(QString,QStringList,QString,QString,int,int,bool)), this,
SLOT(onAppRegistered(QString,QStringList,QString,QString,int,int,bool)));
connect(quappdbusi, SIGNAL(dbusUnregistered(QString,QStringList,QString,QString,int,int,bool)), this,
SLOT(onAppUnregistered(QString,QStringList,QString,QString,int,int,bool)));
quappdbusi->setObjectName(serviceName);
qDebug() << __FUNCTION__ << "mapped signals to monitor " << serviceName;
if(!d->dbus_if)
return;
QDBusReply<QStringList> services = d->dbus_if->registeredServiceNames();
int idx = services.value().indexOf(serviceName);
if(idx > -1)
{
LocalQuApplicationInterface quappdbusi(serviceName, "/QuApplication", QDBusConnection::sessionBus(), this);
if(quappdbusi.isValid())
{
/* retrieve pid from service */
QDBusReply<QStringList> argsReply = quappdbusi.arguments();
if(!argsReply.isValid())
perr("QuAppDBusController.findApps: reply error: %s", qstoc(argsReply.error().message()));
else
{
QStringList arguments = args_noPath(argsReply.value());
QString disp_host = quappdbusi.display_host();
int disp_n = quappdbusi.display_number();
int screen_n = quappdbusi.screen_number();
bool is_plat_x11 = quappdbusi.isPlatformX11();
QuAppInfo ai(arguments, serviceName, disp_host, disp_n, screen_n, is_plat_x11);
onAppRegistered(ai.exename(), ai.args(), serviceName, disp_host, disp_n, screen_n, is_plat_x11);
}
}
}
}
void QuAppDBusController::stop_monitor(const QString &serviceName)
{
LocalQuApplicationInterface *quappdbusi = findChild<LocalQuApplicationInterface *>(serviceName);
if(quappdbusi)
{
qDebug() << __FUNCTION__ << "deleting monitored interface " << quappdbusi->objectName();
delete quappdbusi;
}
}
void QuAppDBusController::addCtrlListener(QuAppDBusControllerListener *l)
{
d->ctrl_listeners.append(l);
}
void QuAppDBusController::removeCtrlListener(QuAppDBusControllerListener *l)
{
d->ctrl_listeners.removeAll(l);
}
void QuAppDBusController::onAppRegistered(const QString &exenam, const QStringList &args, const QString &dbus_servicenam,
const QString& display_h, int disp_num, int screen_num, bool is_plat_x11)
{
qDebug() << "QuAppDBusController::" << __FUNCTION__ << exenam << args << dbus_servicenam;
QuAppInfo ai(exenam, args, dbus_servicenam, display_h, disp_num, screen_num, is_plat_x11);
foreach(QuAppDBusControllerListener *l, d->ctrl_listeners)
l->onAppRegistered(ai);
}
void QuAppDBusController::onAppUnregistered(const QString &exenam, const QStringList &args, const QString &dbus_servicenam,
const QString& display_h, int disp_num, int screen_num, bool is_plat_x11)
{
qDebug() << __FUNCTION__ << exenam << args << dbus_servicenam;
QuAppInfo ai(exenam, args, dbus_servicenam, display_h, disp_num, screen_num, is_plat_x11);
foreach(QuAppDBusControllerListener *l, d->ctrl_listeners)
l->onAppUnregistered(ai);
}
QDBusConnectionInterface *QuAppDBusController::m_getDbusConnectionInterface()
{
if(d->dbus_if)
return d->dbus_if;
QDBusConnection connection = QDBusConnection::sessionBus();
if(connection.isConnected()) {
}
else if(!connection.registerService(SERVICE_NAME)) {
perr("QuAppDBusController: failed to register service \"%s\": %s: %s", SERVICE_NAME, qstoc(connection.lastError().name()), qstoc(connection.lastError().message()));
}
else if(!connection.registerObject("/QuAppDBusController", this))
perr("QuAppDBusController: failed to register object with path \"%s\" %s: %s:", SERVICE_NAME, qstoc(connection.lastError().name()), qstoc(connection.lastError().message()));
if(connection.isConnected()) {
d->dbus_if = connection.interface();
}
return d->dbus_if;
}
#ifndef QAPPDBUSCONTROLLER_H
#define QAPPDBUSCONTROLLER_H
#include <QObject>
#include <QList>
#include <qudbusplugininterface.h>
class QDBusConnectionInterface;
class QuAppDBusControllerPrivate;
/** \brief This class implements the QuAppDBusControllerInterface and can be used
* as a proxy to communicate to a cumbia application (QuApplication) using
* DBus
*
* This class provides a very basic functionality to close an application, to raise its
* window (window manager dependent behaviour), monitor an application subscription to
* the DBus server.
*
* A QuAppDBusControllerListener implementation can be registered to QuAppDBusController
* in order to receive notifications when an application is registered and unregistered from DBus.
* start_monitor and stop_monitor have to be called in order to receive notifications
* by QuAppDBusControllerListener.
*
* @see QuAppDBus
*
*/
class QuAppDBusController : public QObject, public QuAppDBusControllerInterface
{
Q_OBJECT
public:
explicit QuAppDBusController(QObject *parent = nullptr);
virtual ~QuAppDBusController();
void close(const QuAppInfo &ai);
void raise(const QuAppInfo &ai);
QStringList args_noPath(const QStringList& args) const;
// QuAppDBusControllerInterface interface
void start_monitor(const QString& serviceName);
void stop_monitor(const QString& serviceName);
void addCtrlListener(QuAppDBusControllerListener *l);
void removeCtrlListener(QuAppDBusControllerListener *l);
public slots:
void onAppRegistered(const QString& exenam, const QStringList &args, const QString& dbus_servicenam,
const QString &display_h, int disp_num, int screen_num, bool is_plat_x11);
void onAppUnregistered(const QString& exenam, const QStringList &args, const QString& dbus_servicenam,
const QString& display_h, int disp_num, int screen_num, bool is_plat_x11);
private:
QList<QuAppInfo> findApps(const QStringList &args = QStringList());
QDBusConnectionInterface *m_getDbusConnectionInterface();
QuAppDBusControllerPrivate *d;
};
#endif // QAPPDBUSCONTROLLER_H
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment