aboutsummaryrefslogtreecommitdiff
path: root/libqmenumodel
diff options
context:
space:
mode:
authorNick Dedekind <nicholas.dedekind@gmail.com>2013-08-26 14:19:38 +0000
committerTarmac <>2013-08-26 14:19:38 +0000
commitaaa82529fb8d8601e47ae27b60814c744f1f75a3 (patch)
tree1c3a8404f9d1d3e4439a63e1d8b204aadc99799c /libqmenumodel
parent50563a1ab243436c8c8fa86f88ef4a4b25b9a107 (diff)
parentdb47d077dcd9ee6761de828c9194d3fa2331f9ea (diff)
downloadqmenumodel-aaa82529fb8d8601e47ae27b60814c744f1f75a3.tar.gz
qmenumodel-aaa82529fb8d8601e47ae27b60814c744f1f75a3.tar.bz2
qmenumodel-aaa82529fb8d8601e47ae27b60814c744f1f75a3.zip
Adds qt event spawning to direct glib main loop callbacks. Fixes: https://bugs.launchpad.net/bugs/1183065, https://bugs.launchpad.net/bugs/1206991.
Approved by Lars Uebernickel, PS Jenkins bot.
Diffstat (limited to 'libqmenumodel')
-rw-r--r--libqmenumodel/src/CMakeLists.txt1
-rw-r--r--libqmenumodel/src/menunode.cpp15
-rw-r--r--libqmenumodel/src/qdbusactiongroup.cpp42
-rw-r--r--libqmenumodel/src/qdbusactiongroup.h4
-rw-r--r--libqmenumodel/src/qdbusmenumodel.cpp27
-rw-r--r--libqmenumodel/src/qdbusmenumodel.h2
-rw-r--r--libqmenumodel/src/qdbusobject.cpp37
-rw-r--r--libqmenumodel/src/qdbusobject.h6
-rw-r--r--libqmenumodel/src/qmenumodel.cpp41
-rw-r--r--libqmenumodel/src/qmenumodel.h5
-rw-r--r--libqmenumodel/src/qmenumodelevents.cpp96
-rw-r--r--libqmenumodel/src/qmenumodelevents.h99
12 files changed, 328 insertions, 47 deletions
diff --git a/libqmenumodel/src/CMakeLists.txt b/libqmenumodel/src/CMakeLists.txt
index ad7c6ab..10f59c6 100644
--- a/libqmenumodel/src/CMakeLists.txt
+++ b/libqmenumodel/src/CMakeLists.txt
@@ -9,6 +9,7 @@ set(QMENUMODEL_SRC
qdbusobject.cpp
qdbusmenumodel.cpp
qdbusactiongroup.cpp
+ qmenumodelevents.cpp
qstateaction.cpp
unitymenumodel.cpp
unitymenumodelevents.cpp
diff --git a/libqmenumodel/src/menunode.cpp b/libqmenumodel/src/menunode.cpp
index ed9a984..f244f40 100644
--- a/libqmenumodel/src/menunode.cpp
+++ b/libqmenumodel/src/menunode.cpp
@@ -18,9 +18,11 @@
*/
#include "menunode.h"
+#include "qmenumodelevents.h"
#include <QMetaMethod>
#include <QDebug>
+#include <QCoreApplication>
MenuNode::MenuNode(const QString &linkType, GMenuModel *model, MenuNode *parent, int pos, QObject *listener)
: m_model(model),
@@ -242,15 +244,8 @@ void MenuNode::onItemsChanged(GMenuModel *model, gint position, gint removed, gi
self->m_currentOpAdded = added;
self->m_currentOpRemoved = removed;
- const QMetaObject *mobj = self->m_listener->metaObject();
- if (!mobj->invokeMethod(self->m_listener,
- "onItemsChanged",
- Q_ARG(MenuNode*, self),
- Q_ARG(int, position),
- Q_ARG(int, removed),
- Q_ARG(int, added)))
- {
- qWarning() << "Slot 'onItemsChanged(MenuNode*, int, int, int)' not found in" << self->m_listener;
- }
+ MenuNodeItemChangeEvent mnice(self, position, added, removed);
+ QCoreApplication::sendEvent(self->m_listener, &mnice);
+
self->commitOperation();
}
diff --git a/libqmenumodel/src/qdbusactiongroup.cpp b/libqmenumodel/src/qdbusactiongroup.cpp
index 824b5f0..5000470 100644
--- a/libqmenumodel/src/qdbusactiongroup.cpp
+++ b/libqmenumodel/src/qdbusactiongroup.cpp
@@ -20,6 +20,10 @@
#include "qdbusactiongroup.h"
#include "qstateaction.h"
#include "converter.h"
+#include "qmenumodelevents.h"
+
+// Qt
+#include <QCoreApplication>
extern "C" {
#include <glib.h>
@@ -53,7 +57,8 @@ extern "C" {
/*! \internal */
QDBusActionGroup::QDBusActionGroup(QObject *parent)
:QObject(parent),
- m_actionGroup(NULL)
+ QDBusObject(this),
+ m_actionGroup(NULL)
{
}
@@ -184,7 +189,8 @@ void QDBusActionGroup::setActionGroup(GDBusActionGroup *ag)
gchar **actions = g_action_group_list_actions(m_actionGroup);
for(guint i=0; i < g_strv_length(actions); i++) {
- Q_EMIT actionAppear(actions[i]);
+ DBusActionVisiblityEvent dave(actions[i], true);
+ QCoreApplication::sendEvent(this, &dave);
}
g_strfreev(actions);
}
@@ -218,23 +224,49 @@ void QDBusActionGroup::activateAction(const QString &name, const QVariant &param
}
}
+bool QDBusActionGroup::event(QEvent* e)
+{
+ if (QDBusObject::event(e)) {
+ return true;
+ } else if (e->type() == DBusActionVisiblityEvent::eventType) {
+ DBusActionVisiblityEvent *dave = static_cast<DBusActionVisiblityEvent*>(e);
+
+ if (dave->visible) {
+ Q_EMIT actionAppear(dave->name);
+ } else {
+ Q_EMIT actionVanish(dave->name);
+ }
+ } else if (e->type() == DBusActionStateEvent::eventType) {
+ DBusActionStateEvent *dase = static_cast<DBusActionStateEvent*>(e);
+
+ Q_EMIT actionStateChanged(dase->name, dase->state);
+ }
+ return QObject::event(e);
+}
+
/*! \internal */
void QDBusActionGroup::onActionAdded(GDBusActionGroup *, gchar *name, gpointer data)
{
QDBusActionGroup *self = reinterpret_cast<QDBusActionGroup*>(data);
- Q_EMIT self->actionAppear(name);
+
+ DBusActionVisiblityEvent dave(name, true);
+ QCoreApplication::sendEvent(self, &dave);
}
/*! \internal */
void QDBusActionGroup::onActionRemoved(GDBusActionGroup *, gchar *name, gpointer data)
{
QDBusActionGroup *self = reinterpret_cast<QDBusActionGroup*>(data);
- Q_EMIT self->actionVanish(name);
+
+ DBusActionVisiblityEvent dave(name, false);
+ QCoreApplication::sendEvent(self, &dave);
}
/*! \internal */
void QDBusActionGroup::onActionStateChanged(GDBusActionGroup *, gchar *name, GVariant *value, gpointer data)
{
QDBusActionGroup *self = reinterpret_cast<QDBusActionGroup*>(data);
- Q_EMIT self->actionStateChanged(name, Converter::toQVariant(value));
+
+ DBusActionStateEvent dase(name, Converter::toQVariant(value));
+ QCoreApplication::sendEvent(self, &dase);
}
diff --git a/libqmenumodel/src/qdbusactiongroup.h b/libqmenumodel/src/qdbusactiongroup.h
index 0292a8f..f369a4e 100644
--- a/libqmenumodel/src/qdbusactiongroup.h
+++ b/libqmenumodel/src/qdbusactiongroup.h
@@ -69,6 +69,8 @@ protected:
virtual void serviceAppear(GDBusConnection *connection);
virtual void serviceVanish(GDBusConnection *connection);
+ virtual bool event(QEvent* e);
+
private:
GActionGroup *m_actionGroup;
int m_signalActionAddId;
@@ -89,4 +91,4 @@ private:
static void onActionStateChanged(GDBusActionGroup *ag, gchar *name, GVariant *value, gpointer data);
};
-#endif
+#endif // QDBUSACTIONGROUP_H
diff --git a/libqmenumodel/src/qdbusmenumodel.cpp b/libqmenumodel/src/qdbusmenumodel.cpp
index 284b08b..f8b4a51 100644
--- a/libqmenumodel/src/qdbusmenumodel.cpp
+++ b/libqmenumodel/src/qdbusmenumodel.cpp
@@ -22,6 +22,9 @@ extern "C" {
}
#include "qdbusmenumodel.h"
+#include "qmenumodelevents.h"
+
+#include <QCoreApplication>
/*!
\qmltype QDBusMenuModel
@@ -49,7 +52,8 @@ extern "C" {
\endcode
*/
QDBusMenuModel::QDBusMenuModel(QObject *parent)
- : QMenuModel(0, parent)
+ : QMenuModel(0, parent),
+ QDBusObject(this)
{
}
@@ -83,13 +87,24 @@ void QDBusMenuModel::start()
void QDBusMenuModel::stop()
{
QDBusObject::disconnect();
- setMenuModel(NULL);
+
+ MenuModelEvent mme(NULL);
+ QCoreApplication::sendEvent(this, &mme);
+}
+
+bool QDBusMenuModel::event(QEvent* e)
+{
+ if (QDBusObject::event(e)) {
+ return true;
+ }
+ return QMenuModel::event(e);
}
/*! \internal */
void QDBusMenuModel::serviceVanish(GDBusConnection *)
{
- setMenuModel(NULL);
+ MenuModelEvent mme(NULL);
+ QCoreApplication::sendEvent(this, &mme);
}
/*! \internal */
@@ -98,8 +113,10 @@ void QDBusMenuModel::serviceAppear(GDBusConnection *connection)
GMenuModel *model = G_MENU_MODEL(g_dbus_menu_model_get(connection,
busName().toUtf8().data(),
objectPath().toUtf8().data()));
- setMenuModel(model);
- //setModel take care of the ref
+
+ MenuModelEvent mme(model);
+ QCoreApplication::sendEvent(this, &mme);
+ //event handling takes care of the ref
g_object_unref(model);
}
diff --git a/libqmenumodel/src/qdbusmenumodel.h b/libqmenumodel/src/qdbusmenumodel.h
index 6943613..3474ce0 100644
--- a/libqmenumodel/src/qdbusmenumodel.h
+++ b/libqmenumodel/src/qdbusmenumodel.h
@@ -49,6 +49,8 @@ protected:
virtual void serviceAppear(GDBusConnection *connection);
virtual void serviceVanish(GDBusConnection *connection);
+ virtual bool event(QEvent* e);
+
private:
// workaround to support int as busType
void setIntBusType(int busType);
diff --git a/libqmenumodel/src/qdbusobject.cpp b/libqmenumodel/src/qdbusobject.cpp
index c586972..be9fb93 100644
--- a/libqmenumodel/src/qdbusobject.cpp
+++ b/libqmenumodel/src/qdbusobject.cpp
@@ -23,8 +23,10 @@ extern "C" {
}
#include "qdbusobject.h"
+#include "qmenumodelevents.h"
#include <QDebug>
+#include <QCoreApplication>
/*!
\qmltype QDBusObject
@@ -73,8 +75,9 @@ extern "C" {
\endlist
*/
-QDBusObject::QDBusObject()
- :m_watchId(0),
+QDBusObject::QDBusObject(QObject* listener)
+ :m_listener(listener),
+ m_watchId(0),
m_busType(DBusEnums::None),
m_status(DBusEnums::Disconnected)
{
@@ -181,14 +184,34 @@ void QDBusObject::onServiceAppeared(GDBusConnection *connection, const gchar *,
{
QDBusObject *self = reinterpret_cast<QDBusObject*>(data);
- self->serviceAppear(connection);
- self->setStatus(DBusEnums::Connected);
+ if (self->m_listener) {
+ DbusObjectServiceEvent dose(connection, true);
+ QCoreApplication::sendEvent(self->m_listener, &dose);
+ }
}
void QDBusObject::onServiceVanished(GDBusConnection *connection, const gchar *, gpointer data)
{
- QDBusObject *self = reinterpret_cast<QDBusObject*>(data);
+ QDBusObject *self = reinterpret_cast<QDBusObject*>(data);
- self->setStatus(DBusEnums::Connecting);
- self->serviceVanish(connection);
+ if (self->m_listener) {
+ DbusObjectServiceEvent dose(connection, false);
+ QCoreApplication::sendEvent(self->m_listener, &dose);
+ }
+}
+
+bool QDBusObject::event(QEvent* e)
+{
+ if (e->type() == DbusObjectServiceEvent::eventType) {
+ DbusObjectServiceEvent *dose = static_cast<DbusObjectServiceEvent*>(e);
+ if (dose->visible) {
+ serviceAppear(dose->connection);
+ setStatus(DBusEnums::Connected);
+ } else {
+ setStatus(DBusEnums::Connecting);
+ serviceVanish(dose->connection);
+ }
+ return true;
+ }
+ return false;
}
diff --git a/libqmenumodel/src/qdbusobject.h b/libqmenumodel/src/qdbusobject.h
index 324d3fd..1a87844 100644
--- a/libqmenumodel/src/qdbusobject.h
+++ b/libqmenumodel/src/qdbusobject.h
@@ -32,7 +32,7 @@ typedef struct _GDBusConnection GDBusConnection;
class QDBusObject
{
public:
- QDBusObject();
+ QDBusObject(QObject* listener);
~QDBusObject();
DBusEnums::BusType busType() const;
@@ -59,7 +59,11 @@ protected:
virtual void objectPathChanged(const QString &objectPath) = 0;
virtual void statusChanged(DBusEnums::ConnectionStatus status) = 0;
+ // This is not a Qbject, but we are passed events from superclass qobjects.
+ virtual bool event(QEvent* e);
+
private:
+ QObject* m_listener;
guint m_watchId;
DBusEnums::BusType m_busType;
QString m_busName;
diff --git a/libqmenumodel/src/qmenumodel.cpp b/libqmenumodel/src/qmenumodel.cpp
index 9bc9e02..e77419f 100644
--- a/libqmenumodel/src/qmenumodel.cpp
+++ b/libqmenumodel/src/qmenumodel.cpp
@@ -25,6 +25,8 @@ extern "C" {
#include "qmenumodel.h"
#include "menunode.h"
#include "converter.h"
+#include "qmenumodelevents.h"
+
#include <QCoreApplication>
#include <QThread>
@@ -225,28 +227,37 @@ QVariant QMenuModel::getExtraProperties(MenuNode *node, int row) const
return extra;
}
-/*! \internal */
-void QMenuModel::onItemsChanged(MenuNode *node,
- int position,
- int removed,
- int added)
+bool QMenuModel::event(QEvent* e)
{
- QModelIndex index = indexFromNode(node);
- if (removed > 0) {
- beginRemoveRows(index, position, position + removed - 1);
+ if (e->type() == MenuNodeItemChangeEvent::eventType) {
+ MenuNodeItemChangeEvent *mnice = static_cast<MenuNodeItemChangeEvent*>(e);
- node->commitOperation();
+ QModelIndex index = indexFromNode(mnice->node);
+ if (mnice->removed > 0) {
+ beginRemoveRows(index, mnice->position, mnice->position + mnice->removed - 1);
- endRemoveRows();
- }
+ mnice->node->commitOperation();
+
+ endRemoveRows();
+ }
+
+ if (mnice->added > 0) {
+ beginInsertRows(index, mnice->position, mnice->position + mnice->added - 1);
+
+ mnice->node->commitOperation();
+
+ endInsertRows();
+ }
+ return true;
- if (added > 0) {
- beginInsertRows(index, position, position + added - 1);
+ } else if (e->type() == MenuModelEvent::eventType) {
- node->commitOperation();
+ MenuModelEvent *mme = static_cast<MenuModelEvent*>(e);
- endInsertRows();
+ setMenuModel(mme->model);
+ return true;
}
+ return QAbstractItemModel::event(e);
}
/*! \internal */
diff --git a/libqmenumodel/src/qmenumodel.h b/libqmenumodel/src/qmenumodel.h
index 8887c81..bbb35a0 100644
--- a/libqmenumodel/src/qmenumodel.h
+++ b/libqmenumodel/src/qmenumodel.h
@@ -52,14 +52,13 @@ public:
Q_SIGNALS:
void countChanged();
-public Q_SLOTS:
- void onItemsChanged(MenuNode *node, int position, int removed, int added);
-
protected:
QMenuModel(GMenuModel *other=0, QObject *parent=0);
void setMenuModel(GMenuModel *model);
GMenuModel *menuModel() const;
+ virtual bool event(QEvent* e);
+
private:
MenuNode *m_root;
diff --git a/libqmenumodel/src/qmenumodelevents.cpp b/libqmenumodel/src/qmenumodelevents.cpp
new file mode 100644
index 0000000..c705d5c
--- /dev/null
+++ b/libqmenumodel/src/qmenumodelevents.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Nicholas Dedekind <nick.dedekind@canonical.com
+ */
+
+extern "C" {
+#include <glib-object.h>
+#include <gio/gio.h>
+}
+
+#include "qmenumodelevents.h"
+
+const QEvent::Type MenuNodeItemChangeEvent::eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
+const QEvent::Type DBusActionStateEvent::eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
+const QEvent::Type DBusActionVisiblityEvent::eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
+const QEvent::Type MenuModelEvent::eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
+const QEvent::Type DbusObjectServiceEvent::eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
+
+MenuNodeItemChangeEvent::MenuNodeItemChangeEvent(MenuNode* _node, int _position, int _removed, int _added)
+ : QEvent(MenuNodeItemChangeEvent::eventType),
+ node(_node),
+ position(_position),
+ removed(_removed),
+ added(_added)
+{}
+
+
+DBusActionEvent::DBusActionEvent(const QString& _name, QEvent::Type type)
+ : QEvent(type),
+ name(_name)
+{
+}
+
+
+DBusActionVisiblityEvent::DBusActionVisiblityEvent(const QString& _name, bool _visible)
+ : DBusActionEvent(_name, DBusActionVisiblityEvent::eventType),
+ visible(_visible)
+{
+}
+
+
+DBusActionStateEvent::DBusActionStateEvent(const QString& _name, const QVariant& _state)
+ : DBusActionEvent(_name, DBusActionStateEvent::eventType),
+ state(_state)
+{
+}
+
+
+DbusObjectServiceEvent::DbusObjectServiceEvent(GDBusConnection* _connection, bool _visible)
+ : QEvent(DbusObjectServiceEvent::eventType),
+ connection(_connection),
+ visible(_visible)
+{
+ if (connection) {
+ g_object_ref(connection);
+ }
+}
+
+
+DbusObjectServiceEvent::~DbusObjectServiceEvent()
+{
+ if (connection) {
+ g_object_unref(connection);
+ }
+}
+
+
+MenuModelEvent::MenuModelEvent(GMenuModel* _model)
+ : QEvent(MenuModelEvent::eventType),
+ model(_model)
+{
+ if (model) {
+ g_object_ref(model);
+ }
+}
+
+MenuModelEvent::~MenuModelEvent()
+{
+ if (model) {
+ g_object_unref(model);
+ }
+}
diff --git a/libqmenumodel/src/qmenumodelevents.h b/libqmenumodel/src/qmenumodelevents.h
new file mode 100644
index 0000000..be8f80d
--- /dev/null
+++ b/libqmenumodel/src/qmenumodelevents.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Nicholas Dedekind <nick.dedekind@canonical.com
+ */
+
+#ifndef QMENUMODELEVENTS_H
+#define QMENUMODELEVENTS_H
+
+#include <QEvent>
+#include <QVariant>
+
+class MenuNode;
+typedef struct _GDBusConnection GDBusConnection;
+typedef struct _GMenuModel GMenuModel;
+
+/* Event for a connection update for a dbus object */
+class DbusObjectServiceEvent : public QEvent
+{
+public:
+ static const QEvent::Type eventType;
+ DbusObjectServiceEvent(GDBusConnection* connection, bool visible);
+ ~DbusObjectServiceEvent();
+
+ GDBusConnection* connection;
+ bool visible;
+};
+
+/* Event for an update to the gmenumodel */
+class MenuModelEvent : public QEvent
+{
+public:
+ static const QEvent::Type eventType;
+
+ MenuModelEvent(GMenuModel *model);
+ ~MenuModelEvent();
+
+ GMenuModel *model;
+};
+
+/* Event for a GAction (base) */
+class DBusActionEvent : public QEvent
+{
+public:
+ QString name;
+
+protected:
+ DBusActionEvent(const QString& name, QEvent::Type type);
+};
+
+/* Event for a GAction add/remove */
+class DBusActionVisiblityEvent : public DBusActionEvent
+{
+public:
+ static const QEvent::Type eventType;
+ DBusActionVisiblityEvent(const QString& name, bool visible);
+
+ bool visible;
+};
+
+/* Event for a GAction state value update */
+class DBusActionStateEvent : public DBusActionEvent
+{
+public:
+ static const QEvent::Type eventType;
+
+ DBusActionStateEvent(const QString& name, const QVariant& state);
+
+ QVariant state;
+};
+
+/* Event for changing gmenumodel entries */
+class MenuNodeItemChangeEvent : public QEvent
+{
+public:
+ static const QEvent::Type eventType;
+
+ MenuNodeItemChangeEvent(MenuNode* node, int position, int removed, int added);
+
+ MenuNode* node;
+ int position;
+ int removed;
+ int added;
+};
+
+#endif //QMENUMODELEVENTS_H