on xenial help sign in
Refactor AbstractDBusServiceMonitor to allow inheritor to create something other than a QDBusInterface when service appears. DashCommunicator uses this to create non-blocking interface, which is suited to push communication it needs
commit1acbc969b63c72965887701d94d7a874d192aa58 authorGerry Boland <gerry.boland@canonical.com> dateWed 17 Dec 2014, 13:23 (12 years ago) parent5a7139e
4 files changed+61−24
plugins/Unity/DashCommunicator/dashconnection.cpp+30 plugins/Unity/DashCommunicator/dashconnection.h+4−1 src/libunity8-private/abstractdbusservicemonitor.cpp+20−21 src/libunity8-private/abstractdbusservicemonitor.h+7−2
plugins/Unity/DashCommunicator/dashconnection.cpp+30
@@ -19,12 +19,42 @@
1919#include <QDBusInterface>
2020#include <QDBusPendingCall>
2121
22+/* The default implementation of QDBusAbstractInterface creates a QDBusInterface when the service
23+ * appears on the bus.
24+ *
25+ * On construction QDBusInterface synchronously introspects the service, which will block the GUI
26+ * thread of this process if the service is busy. QDBusAbstractInterface does not perform this
27+ * introspection, so let's subclass that and avoid the blocking scenario.
28+ *
29+ * However we loose Qt's wrapping of the DBus service with a MetaObject, with the result that we
30+ * cannot easily connect to DBus signals with the usual connect() calls. So this approach only
31+ * suited to push communication with the DBus service.
32+ */
33+class AsyncDBusInterface : public QDBusAbstractInterface
34+{
35+public:
36+ AsyncDBusInterface(const QString &service, const QString &path,
37+ const QString &interface, const QDBusConnection &connection,
38+ QObject *parent = 0)
39+ : QDBusAbstractInterface(service, path, interface.toLatin1().data(), connection, parent)
40+ {}
41+ ~AsyncDBusInterface() = default;
42+};
43+
44+
2245DashConnection::DashConnection(const QString &service, const QString &path, const QString &interface, QObject *parent):
2346 AbstractDBusServiceMonitor(service, path, interface, SessionBus, parent)
2447{
2548
2649}
2750
51+/* Override the default implementation to create a non-blocking DBus interface (see note above). */
52+QDBusAbstractInterface* DashConnection::createInterface(const QString &service, const QString &path,
53+ const QString &interface, const QDBusConnection &connection)
54+{
55+ return new AsyncDBusInterface(service, path, interface, connection);
56+}
57+
2858void DashConnection::setCurrentScope(int index, bool animate, bool isSwipe)
2959{
3060 if (dbusInterface()) {
plugins/Unity/DashCommunicator/dashconnection.h+4−1
@@ -20,7 +20,6 @@
2020// local
2121#include "abstractdbusservicemonitor.h"
2222
23−
2423class DashConnection: public AbstractDBusServiceMonitor
2524{
2625 Q_OBJECT
@@ -29,6 +28,10 @@ public:
2928
3029public Q_SLOTS:
3130 void setCurrentScope(int index, bool animate, bool isSwipe);
31+
32+private:
33+ QDBusAbstractInterface* createInterface(const QString &service, const QString &path,
34+ const QString &interface, const QDBusConnection &connection) override;
3235};
3336
3437#endif
src/libunity8-private/abstractdbusservicemonitor.cpp+20−21
@@ -25,20 +25,6 @@
2525#include <QDBusConnectionInterface>
2626#include <QDBusReply>
2727
28−// On construction QDBusInterface synchronously introspects the service, which will block the GUI
29−// thread if the service is busy. QDBusAbstractInterface does not perform this introspection, so
30−// let's subclass that and avoid the blocking scenario.
31−class AsyncDBusInterface : public QDBusAbstractInterface
32−{
33−public:
34− AsyncDBusInterface(const QString &service, const QString &path,
35− const QString &interface, const QDBusConnection &connection,
36− QObject *parent = 0)
37− : QDBusAbstractInterface(service, path, interface.toLatin1().data(), connection, parent)
38− {}
39− ~AsyncDBusInterface() = default;
40−};
41−
4228AbstractDBusServiceMonitor::AbstractDBusServiceMonitor(const QString &service, const QString &path,
4329 const QString &interface, const Bus bus,
4430 QObject *parent)
@@ -46,19 +32,20 @@ AbstractDBusServiceMonitor::AbstractDBusServiceMonitor(const QString &service, c
4632 , m_service(service)
4733 , m_path(path)
4834 , m_interface(interface)
35+ , m_bus(bus)
4936 , m_watcher(new QDBusServiceWatcher(service,
5037 (bus == SystemBus) ? QDBusConnection::systemBus()
5138 : QDBusConnection::sessionBus()))
5239 , m_dbusInterface(nullptr)
5340{
54− connect(m_watcher, &QDBusServiceWatcher::serviceRegistered, this, &AbstractDBusServiceMonitor::createInterface);
55− connect(m_watcher, &QDBusServiceWatcher::serviceUnregistered, this, &AbstractDBusServiceMonitor::destroyInterface);
41+ connect(m_watcher, &QDBusServiceWatcher::serviceRegistered, this, &AbstractDBusServiceMonitor::onServiceRegistered);
42+ connect(m_watcher, &QDBusServiceWatcher::serviceUnregistered, this, &AbstractDBusServiceMonitor::onServiceUnregistered);
5643
5744 // Connect to the service if it's up already
5845 QDBusConnectionInterface* sessionBus = QDBusConnection::sessionBus().interface();
5946 QDBusReply<bool> reply = sessionBus->isServiceRegistered(m_service);
6047 if (reply.isValid() && reply.value()) {
61− createInterface(m_service);
48+ onServiceRegistered(m_service);
6249 }
6350}
6451
@@ -68,19 +55,31 @@ AbstractDBusServiceMonitor::~AbstractDBusServiceMonitor()
6855 delete m_dbusInterface;
6956}
7057
71−void AbstractDBusServiceMonitor::createInterface(const QString &)
58+void AbstractDBusServiceMonitor::onServiceRegistered(const QString &)
7259{
7360 if (m_dbusInterface != nullptr) {
7461 delete m_dbusInterface;
7562 m_dbusInterface = nullptr;
7663 }
7764
78− m_dbusInterface = new AsyncDBusInterface(m_service, m_path, m_interface,
79− QDBusConnection::sessionBus());
65+ m_dbusInterface = createInterface(m_service, m_path, m_interface,
66+ (m_bus == SystemBus) ? QDBusConnection::systemBus()
67+ : QDBusConnection::sessionBus());
8068 Q_EMIT serviceAvailableChanged(true);
8169}
8270
83−void AbstractDBusServiceMonitor::destroyInterface(const QString &)
71+/*
72+ * Default implementation creates a QDBusInterface. This performs blocking introspection of the
73+ * service at initialization, which may be undesirable if the service is slow/blocked.
74+ */
75+QDBusAbstractInterface*
76+AbstractDBusServiceMonitor::createInterface(const QString &service, const QString &path,
77+ const QString &interface, const QDBusConnection &connection)
78+{
79+ return new QDBusInterface(service, path, interface, connection);
80+}
81+
82+void AbstractDBusServiceMonitor::onServiceUnregistered(const QString &)
8483{
8584 if (m_dbusInterface != nullptr) {
8685 delete m_dbusInterface;
src/libunity8-private/abstractdbusservicemonitor.h+7−2
@@ -22,6 +22,7 @@
2222
2323#include <QObject>
2424#include <QString>
25+#include <QScopedPointer>
2526#include <QDBusConnection>
2627
2728class QDBusAbstractInterface;
@@ -52,13 +53,17 @@ Q_SIGNALS:
5253 void serviceAvailableChanged(bool available);
5354
5455private Q_SLOTS:
55− void createInterface(const QString &service);
56− void destroyInterface(const QString &service);
56+ void onServiceRegistered(const QString &service);
57+ void onServiceUnregistered(const QString &service);
5758
5859protected:
60+ virtual QDBusAbstractInterface* createInterface(const QString &service, const QString &path,
61+ const QString &interface, const QDBusConnection &connection);
62+
5963 const QString m_service;
6064 const QString m_path;
6165 const QString m_interface;
66+ const Bus m_bus;
6267 QDBusServiceWatcher* m_watcher;
6368 QDBusAbstractInterface* m_dbusInterface;
6469};