aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/changelog10
-rw-r--r--libqmenumodel/src/CMakeLists.txt1
-rw-r--r--libqmenumodel/src/converter.cpp132
-rw-r--r--libqmenumodel/src/converter.h4
-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
-rw-r--r--libqmenumodel/src/unitymenumodel.cpp42
-rw-r--r--tests/client/convertertest.cpp53
17 files changed, 561 insertions, 55 deletions
diff --git a/debian/changelog b/debian/changelog
index 7c46e30..b998fd3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+qmenumodel (0.2.7+13.10.20130826-0ubuntu1) saucy; urgency=low
+
+ [ Nick Dedekind ]
+ * Added int64 & variant types to UnityMenuModel ext attribute parsing.
+
+ [ Ubuntu daily release ]
+ * Automatic snapshot from revision 75
+
+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 26 Aug 2013 14:06:47 +0000
+
qmenumodel (0.2.7+13.10.20130813-0ubuntu1) saucy; urgency=low
[ Nick Dedekind ]
diff --git a/libqmenumodel/src/CMakeLists.txt b/libqmenumodel/src/CMakeLists.txt
index 84f4daa..5d4a16a 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
unitymenuaction.cpp
unitymenuactionevents.cpp
diff --git a/libqmenumodel/src/converter.cpp b/libqmenumodel/src/converter.cpp
index d9d90bd..69e6629 100644
--- a/libqmenumodel/src/converter.cpp
+++ b/libqmenumodel/src/converter.cpp
@@ -195,3 +195,135 @@ GVariant* Converter::toGVariant(const QVariant &value)
return result;
}
+GVariant* Converter::toGVariantWithSchema(const QVariant &value, const char* schema)
+{
+ if (!g_variant_type_string_is_valid(schema)) {
+ return Converter::toGVariant(value);
+ }
+
+ GVariant* result = NULL;
+ const GVariantType* schema_type;
+ schema_type = g_variant_type_new(schema);
+
+ if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_BOOLEAN)) {
+ if (value.canConvert<bool>()) {
+ result = g_variant_new_boolean (value.value<bool>());
+ }
+ } else if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_BYTE)) {
+ if (value.canConvert<uchar>()) {
+ result = g_variant_new_byte (value.value<uchar>());
+ }
+ } else if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_INT16)) {
+ if (value.canConvert<qint16>()) {
+ result = g_variant_new_int16 (value.value<qint16>());
+ }
+ } else if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_UINT16)) {
+ if (value.canConvert<quint16>()) {
+ result = g_variant_new_uint16 (value.value<quint16>());
+ }
+ } else if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_INT32)) {
+ if (value.canConvert<qint32>()) {
+ result = g_variant_new_int32 (value.value<qint32>());
+ }
+ } else if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_UINT32)) {
+ if (value.canConvert<quint32>()) {
+ result = g_variant_new_uint32 (value.value<quint32>());
+ }
+ } else if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_INT64)) {
+ if (value.canConvert<qint64>()) {
+ result = g_variant_new_int64 (value.value<qint64>());
+ }
+ } else if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_UINT64)) {
+ if (value.canConvert<quint64>()) {
+ result = g_variant_new_uint64 (value.value<quint64>());
+ }
+ } else if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_DOUBLE)) {
+ if (value.canConvert<double>()) {
+ result = g_variant_new_double (value.value<double>());
+ }
+ } else if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_STRING)) {
+ if (value.canConvert<QString>()) {
+ result = g_variant_new_string(value.toString().toUtf8().data());
+ }
+ } else if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_VARIANT)) {
+ result = Converter::toGVariant(value);
+ } else if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_VARDICT)) {
+ if (value.canConvert(QVariant::Map)) {
+ result = Converter::toGVariant(value.toMap());
+ }
+ } else if (g_variant_type_is_array(schema_type)) {
+ if (value.canConvert(QVariant::List)) {
+
+ const GVariantType* entry_type;
+ GVariant* data;
+ entry_type = g_variant_type_element(schema_type);
+ gchar* entryTypeString = g_variant_type_dup_string(entry_type);
+
+ QVariantList lst = value.toList();
+ GVariant **vars = g_new(GVariant*, lst.size());
+
+ bool ok = true;
+ for (int i=0; i < lst.size(); i++) {
+ data = Converter::toGVariantWithSchema(lst[i], entryTypeString);
+
+ if (data) {
+ vars[i] = data;
+ }
+ else {
+ ok = false;
+ qWarning() << "Failed to convert list to array with schema:" << schema;
+ break;
+ }
+ }
+ if (ok) {
+ result = g_variant_new_array(entry_type, vars, lst.size());
+ }
+ g_free(entryTypeString);
+ g_free(vars);
+ }
+ } else if (g_variant_type_is_tuple(schema_type)) {
+ if (value.canConvert(QVariant::List)) {
+ GVariant* data;
+
+ QVariantList lst = value.toList();
+ GVariant **vars = g_new(GVariant*, lst.size());
+
+ const GVariantType* entry_type = g_variant_type_first(schema_type);
+
+ bool ok = true;
+ for (int i=0; i < lst.size(); i++) {
+
+ gchar* entryTypeString = g_variant_type_dup_string(entry_type);
+
+ data = Converter::toGVariantWithSchema(lst[i], entryTypeString);
+
+ if (data) {
+ vars[i] = data;
+ }
+ else {
+ ok = false;
+ qWarning() << "Failed to convert list to tuple with schema:" << schema;
+ g_free(entryTypeString);
+ break;
+ }
+ g_free(entryTypeString);
+
+ entry_type = g_variant_type_next(entry_type);
+ if (!entry_type) {
+ break;
+ }
+ }
+ if (ok) {
+ result = g_variant_new_tuple(vars, lst.size());
+ }
+ g_free(vars);
+ }
+ }
+
+ // fallback to straight convert.
+ if (!result) {
+ result = Converter::toGVariant(value);
+ }
+ return result;
+}
+
diff --git a/libqmenumodel/src/converter.h b/libqmenumodel/src/converter.h
index 5f05bc7..f47c09e 100644
--- a/libqmenumodel/src/converter.h
+++ b/libqmenumodel/src/converter.h
@@ -28,6 +28,10 @@ class Converter
public:
static QVariant toQVariant(GVariant *value);
static GVariant* toGVariant(const QVariant &value);
+
+ // This converts a QVariant to a GVariant using a provided gvariant schema as
+ // a conversion base (it will attempt to convert to this format).
+ static GVariant* toGVariantWithSchema(const QVariant &value, const char* schema);
};
#endif // CONVERTER_H
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
diff --git a/libqmenumodel/src/unitymenumodel.cpp b/libqmenumodel/src/unitymenumodel.cpp
index 4bae374..cc6d317 100644
--- a/libqmenumodel/src/unitymenumodel.cpp
+++ b/libqmenumodel/src/unitymenumodel.cpp
@@ -531,20 +531,34 @@ static QVariant attributeToQVariant(GVariant *value, const QString &type)
QVariant result;
if (type == "int") {
- if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32))
+ if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32)) {
result = QVariant(g_variant_get_int32(value));
+ }
+ }
+ else if (type == "int64") {
+ if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT64)) {
+ result = QVariant((qlonglong)g_variant_get_int64(value));
+ }
}
- if (type == "bool") {
- if (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
+ else if (type == "bool") {
+ if (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)) {
result = QVariant(g_variant_get_boolean(value));
+ }
}
else if (type == "string") {
- if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
+ if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) {
result = QVariant(g_variant_get_string(value, NULL));
+ }
}
- if (type == "double") {
- if (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE))
+ else if (type == "double") {
+ if (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE)) {
result = QVariant(g_variant_get_double(value));
+ }
+ }
+ else if (type == "variant") {
+ if (g_variant_is_of_type (value, G_VARIANT_TYPE_VARIANT)) {
+ result = Converter::toQVariant(value);
+ }
}
else if (type == "icon") {
GIcon *icon = g_icon_deserialize (value);
@@ -647,13 +661,25 @@ void UnityMenuModel::activate(int index, const QVariant& parameter)
void UnityMenuModel::changeState(int index, const QVariant& parameter)
{
GtkMenuTrackerItem* item;
+ GVariant* data;
+ GVariant* current_state;
item = (GtkMenuTrackerItem *) g_sequence_get (g_sequence_get_iter_at_pos (priv->items, index));
if (!item) return;
- GVariant* data = Converter::toGVariant(parameter);
+ current_state = gtk_menu_tracker_item_get_action_state (item);
+ if (current_state) {
+ // Attempt to convert the parameter to the expected type
+ data = Converter::toGVariantWithSchema(parameter, g_variant_get_type_string(current_state));
+ g_variant_unref (current_state);
+ } else {
+ data = Converter::toGVariant(parameter);
+ }
+
gtk_menu_tracker_item_change_state (item, data);
- g_variant_unref(data);
+ if (data) {
+ g_variant_unref(data);
+ }
}
diff --git a/tests/client/convertertest.cpp b/tests/client/convertertest.cpp
index f382332..db2807f 100644
--- a/tests/client/convertertest.cpp
+++ b/tests/client/convertertest.cpp
@@ -45,6 +45,22 @@ private:
g_variant_unref(gv);
return result;
}
+ bool compareWithSchema(const QVariant &qv, const QString strType)
+ {
+ GVariantType* expected_type;
+ expected_type = g_variant_type_new(strType.toUtf8().data());
+
+ bool result;
+ GVariant *gv = Converter::toGVariantWithSchema(qv, strType.toUtf8().data());
+ result = g_variant_type_equal(g_variant_get_type(gv), expected_type);
+ if (!result) {
+ qWarning() << "types are different: QVariant:" << qv.typeName()
+ << "Result:" << (const char*) g_variant_get_type(gv)
+ << "Expected:"<< (const char*) expected_type;
+ }
+ g_variant_unref(gv);
+ return result;
+ }
private Q_SLOTS:
@@ -118,6 +134,43 @@ private Q_SLOTS:
g_variant_unref(gTuple);
}
+ void testSchemaConvert()
+ {
+ // convert to integer
+ compareWithSchema(QVariant::fromValue<int>(1), "i");
+ compareWithSchema(QVariant::fromValue<double>(1.1), "i");
+
+ // convert to integer
+ compareWithSchema(QVariant::fromValue<bool>(true), "b");
+ compareWithSchema(QVariant::fromValue<int>(1), "b");
+
+ // convert to double
+ compareWithSchema(QVariant::fromValue<double>(1.0), "d");
+ compareWithSchema(QVariant::fromValue<int>(1), "d");
+
+ // convert to string
+ compareWithSchema(QVariant::fromValue<int>(1), "s");
+ compareWithSchema(QVariant::fromValue<double>(1.1), "s");
+
+ // convert to tuple
+ compareWithSchema(QVariantList() << QVariant::fromValue<bool>(true) << QVariant::fromValue<int>(1) << QVariant::fromValue<int>(1) << QVariant::fromValue<QString>("test1"), "(bdis)");
+
+ // convert to array
+ compareWithSchema(QVariantList() << QVariant::fromValue<int>(1) << QVariant::fromValue<int>(1), "ad");
+ compareWithSchema(QVariantList() << QVariant::fromValue<QString>("test1") << QVariant::fromValue<QString>("test2"), "as");
+
+ // convert to array of tuple
+ QVariantList si1(QVariantList() << QVariant::fromValue<QString>("test1") << QVariant::fromValue<int>(1));
+ QVariantList si2(QVariantList() << QVariant::fromValue<QString>("test1") << QVariant::fromValue<int>(1));
+ compareWithSchema(QVariantList() << QVariant::fromValue(si1) << QVariant::fromValue(si2), "a(sd)");
+
+ // convert to vardict
+ QVariantMap map;
+ map["test1"] = QVariant::fromValue<int>(1);
+ map["test2"] = QVariant::fromValue<double>(1);
+ compareWithSchema(map, "a{sv}");
+ }
+
};
QTEST_MAIN(ConverterTest)