From b1009a800f4e64b17e19e578deedaf0c9bd18902 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 4 Jun 2013 15:42:16 -0400 Subject: Add qml example for UnityMenuModel --- examples/exportmenu.py | 6 +++++- examples/unityqmlmenumodel.qml | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 examples/unityqmlmenumodel.qml (limited to 'examples') diff --git a/examples/exportmenu.py b/examples/exportmenu.py index 4be3deb..767d8b9 100755 --- a/examples/exportmenu.py +++ b/examples/exportmenu.py @@ -54,7 +54,7 @@ if __name__ == '__main__': GLib.Variant.new_string('lorem ipsum')) foo.set_attribute_value('x-enabled', GLib.Variant.new_boolean(True)) menu.append_item(foo) - bar = Gio.MenuItem.new('bar', 'app.bar') + bar = Gio.MenuItem.new('bar', 'bar') bar.set_attribute_value('x-defaultvalue', GLib.Variant.new_string('Hello World!')) bar.set_attribute_value('x-canonical-currentvalue', @@ -74,5 +74,9 @@ if __name__ == '__main__': menu.append('baz', 'app.baz') bus.export_menu_model(BUS_OBJECT_PATH, menu) + actions = Gio.SimpleActionGroup.new() + actions.add_action(Gio.SimpleAction.new("bar", None)) + bus.export_action_group(BUS_OBJECT_PATH, actions) + GLib.MainLoop().run() diff --git a/examples/unityqmlmenumodel.qml b/examples/unityqmlmenumodel.qml new file mode 100644 index 0000000..257866d --- /dev/null +++ b/examples/unityqmlmenumodel.qml @@ -0,0 +1,34 @@ + +import QtQuick 2.0 +import QMenuModel 0.1 + +Item { + width: 400; + height: 500; + + UnityMenuModel { + id: menu + busName: "com.canonical.testmenu" + actionObjectPath: "/com/canonical/testmenu" + menuObjectPath: "/com/canonical/testmenu" + } + + ListView { + anchors.fill: parent + anchors.margins: 10 + spacing: 3 + model: menu + delegate: Rectangle { + width: parent.width + height: 40 + color: "#ddd" + Text { + anchors.fill: parent + anchors.margins: 5 + verticalAlignment: Text.AlignVCenter + color: sensitive ? "black" : "#aaa"; + text: label + } + } + } +} -- cgit v1.2.3 From 2a01b1cba8af5891bac632683286951e2c3f95f0 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 4 Jun 2013 20:23:22 -0400 Subject: examples/exportmenu.py: use g_bus_own_name to avoid race This avoids the common d-bus race where a name is owned but objects aren't exported on it yet. --- examples/exportmenu.py | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'examples') diff --git a/examples/exportmenu.py b/examples/exportmenu.py index 767d8b9..b7c37b1 100755 --- a/examples/exportmenu.py +++ b/examples/exportmenu.py @@ -32,22 +32,7 @@ from gi.repository import GLib BUS_NAME = 'com.canonical.testmenu' BUS_OBJECT_PATH = '/com/canonical/testmenu' - -if __name__ == '__main__': - bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) - # Claim well-known bus name and ensure only one instance of self is running - # at any given time. - # http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-names - proxy = Gio.DBusProxy.new_sync(bus, 0, None, - 'org.freedesktop.DBus', - '/org/freedesktop/DBus', - 'org.freedesktop.DBus', None) - result = proxy.RequestName('(su)', BUS_NAME, 0x4) - if result != 1 : - print >> sys.stderr, ("Name '%s' is already owned on the session bus." - "Aborting.") % BUS_NAME - sys.exit(1) - +def bus_acquired(bus, name): menu = Gio.Menu() foo = Gio.MenuItem.new('foo', 'app.foo') foo.set_attribute_value('x-additionaltext', @@ -78,5 +63,6 @@ if __name__ == '__main__': actions.add_action(Gio.SimpleAction.new("bar", None)) bus.export_action_group(BUS_OBJECT_PATH, actions) +if __name__ == '__main__': + Gio.bus_own_name(Gio.BusType.SESSION, BUS_NAME, 0, bus_acquired, None, None) GLib.MainLoop().run() - -- cgit v1.2.3 From 00885c1ddd04819c44d6a0ca2c7f2af8a1298a97 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 4 Jun 2013 21:05:40 -0400 Subject: unitymenumodel: expose isSeparator --- examples/unityqmlmenumodel.qml | 37 ++++++++++++++++++++++++++---------- libqmenumodel/src/unitymenumodel.cpp | 4 ++++ libqmenumodel/src/unitymenumodel.h | 3 ++- 3 files changed, 33 insertions(+), 11 deletions(-) (limited to 'examples') diff --git a/examples/unityqmlmenumodel.qml b/examples/unityqmlmenumodel.qml index 257866d..d38d6e5 100644 --- a/examples/unityqmlmenumodel.qml +++ b/examples/unityqmlmenumodel.qml @@ -18,16 +18,33 @@ Item { anchors.margins: 10 spacing: 3 model: menu - delegate: Rectangle { - width: parent.width - height: 40 - color: "#ddd" - Text { - anchors.fill: parent - anchors.margins: 5 - verticalAlignment: Text.AlignVCenter - color: sensitive ? "black" : "#aaa"; - text: label + + delegate: Loader { + sourceComponent: isSeparator ? separator : menuitem; + + Component { + id: separator + Rectangle { + width: parent.width + height: 4 + color: "blue" + } + } + + Component { + id: menuitem + Rectangle { + width: parent.width + height: 40 + color: "#ddd" + Text { + anchors.fill: parent + anchors.margins: 5 + verticalAlignment: Text.AlignVCenter + color: sensitive ? "black" : "#aaa"; + text: label + } + } } } } diff --git a/libqmenumodel/src/unitymenumodel.cpp b/libqmenumodel/src/unitymenumodel.cpp index 926d2f1..336b72a 100644 --- a/libqmenumodel/src/unitymenumodel.cpp +++ b/libqmenumodel/src/unitymenumodel.cpp @@ -119,6 +119,9 @@ QVariant UnityMenuModelPrivate::data(int position, int role) case UnityMenuModel::SensitiveRole: return gtk_menu_tracker_item_get_sensitive (item); + case UnityMenuModel::IsSeparatorRole: + return gtk_menu_tracker_item_get_is_separator (item); + default: return QVariant(); } @@ -275,6 +278,7 @@ QHash UnityMenuModel::roleNames() const names[LabelRole] = "label"; names[ActionRole] = "action"; names[SensitiveRole] = "sensitive"; + names[IsSeparatorRole] = "isSeparator"; return names; } diff --git a/libqmenumodel/src/unitymenumodel.h b/libqmenumodel/src/unitymenumodel.h index 12a5891..75af13a 100644 --- a/libqmenumodel/src/unitymenumodel.h +++ b/libqmenumodel/src/unitymenumodel.h @@ -29,7 +29,8 @@ public: enum MenuRoles { ActionRole = Qt::DisplayRole + 1, LabelRole, - SensitiveRole + SensitiveRole, + IsSeparatorRole }; public: -- cgit v1.2.3 From e735d95e613e2ee6170799002183e0770d34590e Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 5 Jun 2013 13:50:12 -0400 Subject: unitymenumodel: add activate() --- examples/unityqmlmenumodel.qml | 9 +++++++-- libqmenumodel/src/unitymenumodel.cpp | 17 +++++++++++++++++ libqmenumodel/src/unitymenumodel.h | 3 +++ 3 files changed, 27 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/unityqmlmenumodel.qml b/examples/unityqmlmenumodel.qml index d38d6e5..a66ba8e 100644 --- a/examples/unityqmlmenumodel.qml +++ b/examples/unityqmlmenumodel.qml @@ -14,6 +14,7 @@ Item { } ListView { + id: listview anchors.fill: parent anchors.margins: 10 spacing: 3 @@ -25,7 +26,7 @@ Item { Component { id: separator Rectangle { - width: parent.width + width: listview.width height: 4 color: "blue" } @@ -34,7 +35,7 @@ Item { Component { id: menuitem Rectangle { - width: parent.width + width: listview.width height: 40 color: "#ddd" Text { @@ -44,6 +45,10 @@ Item { color: sensitive ? "black" : "#aaa"; text: label } + MouseArea { + anchors.fill: parent + onClicked: listview.model.activate(index); + } } } } diff --git a/libqmenumodel/src/unitymenumodel.cpp b/libqmenumodel/src/unitymenumodel.cpp index 336b72a..8000222 100644 --- a/libqmenumodel/src/unitymenumodel.cpp +++ b/libqmenumodel/src/unitymenumodel.cpp @@ -37,6 +37,7 @@ public: int nrItems(); QVariant data(int position, int role); + void activate(int position); private: UnityMenuModel *model; @@ -127,6 +128,14 @@ QVariant UnityMenuModelPrivate::data(int position, int role) } } +void UnityMenuModelPrivate::activate(int position) +{ + GtkMenuTrackerItem *item; + + item = (GtkMenuTrackerItem *) g_sequence_get (g_sequence_get_iter_at_pos (this->items, position)); + gtk_menu_tracker_item_activated (item); +} + void UnityMenuModelPrivate::freeMenuItem (gpointer data, gpointer user_data) { GSequenceIter *it = (GSequenceIter *) data; @@ -282,3 +291,11 @@ QHash UnityMenuModel::roleNames() const return names; } + +#include + +void UnityMenuModel::activate(int index) +{ + if (priv) + priv->activate(index); +} diff --git a/libqmenumodel/src/unitymenumodel.h b/libqmenumodel/src/unitymenumodel.h index 75af13a..38dd472 100644 --- a/libqmenumodel/src/unitymenumodel.h +++ b/libqmenumodel/src/unitymenumodel.h @@ -45,6 +45,9 @@ public: QModelIndex parent(const QModelIndex &index) const; QHash roleNames() const; +public Q_SLOTS: + void activate(int index); + protected: UnityMenuModel(QObject *parent = NULL); void init(const QByteArray &busName, const QByteArray &actionGroupObjectPath, const QByteArray &menuObjectPath); -- cgit v1.2.3 From 192e9c85e6d7441a6115d1ead859b8449cfb07ec Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 25 Jul 2013 06:28:54 +0200 Subject: examples/unitymenumodel.qml: update to newest API --- examples/unityqmlmenumodel.qml | 55 +++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 9 deletions(-) (limited to 'examples') diff --git a/examples/unityqmlmenumodel.qml b/examples/unityqmlmenumodel.qml index a66ba8e..5dcb1ff 100644 --- a/examples/unityqmlmenumodel.qml +++ b/examples/unityqmlmenumodel.qml @@ -8,9 +8,9 @@ Item { UnityMenuModel { id: menu - busName: "com.canonical.testmenu" - actionObjectPath: "/com/canonical/testmenu" - menuObjectPath: "/com/canonical/testmenu" + busName: "com.canonical.indicator.sound" + actions: { "indicator": "/com/canonical/indicator/sound" } + menuObjectPath: "/com/canonical/indicator/sound/desktop" } ListView { @@ -21,7 +21,19 @@ Item { model: menu delegate: Loader { - sourceComponent: isSeparator ? separator : menuitem; + sourceComponent: { + if (isSeparator) { + return separator; + } + else if (type == "com.canonical.unity.slider") { + listview.model.loadExtendedAttributes(index, {'min-icon': 'icon', + 'max-icon': 'icon'}); + return slider; + } + else { + return menuitem; + } + } Component { id: separator @@ -32,22 +44,47 @@ Item { } } + Component { + id: slider + Row { + anchors.fill: parent + Image { + source: ext.minIcon + } + Image { + source: ext.maxIcon + } + } + } + Component { id: menuitem Rectangle { width: listview.width height: 40 color: "#ddd" - Text { + Row { anchors.fill: parent anchors.margins: 5 - verticalAlignment: Text.AlignVCenter - color: sensitive ? "black" : "#aaa"; - text: label + Image { + source: icon + } + Text { + height: parent.height + verticalAlignment: Text.AlignVCenter + color: sensitive ? "black" : "#aaa"; + text: label + } } MouseArea { anchors.fill: parent - onClicked: listview.model.activate(index); + onClicked: { + var submenu = listview.model.submenu(index); + if (submenu) + listview.model = submenu; + else + listview.model.activate(index); + } } } } -- cgit v1.2.3 From 57f5b0730a9f001201458d2759797bba17cabaef Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 25 Jul 2013 10:18:31 +0200 Subject: examples/unityqmlmenumodel.qml: add license header --- examples/unityqmlmenumodel.qml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'examples') diff --git a/examples/unityqmlmenumodel.qml b/examples/unityqmlmenumodel.qml index 5dcb1ff..8028674 100644 --- a/examples/unityqmlmenumodel.qml +++ b/examples/unityqmlmenumodel.qml @@ -1,3 +1,20 @@ +/* + * 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 . + * + * Authors: Lars Uebernickel + */ import QtQuick 2.0 import QMenuModel 0.1 -- cgit v1.2.3 From d57caa61f787c4bd7cb0823eadbbc5d84f542f0a Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Fri, 26 Jul 2013 15:04:50 +0200 Subject: Expose the state of a menu item's action in model.actionState --- examples/unityqmlmenumodel.qml | 22 ++++++++++++------ libqmenumodel/src/gtk/gtkmenutrackeritem.c | 36 ++++++++++++++++++++++++++++++ libqmenumodel/src/gtk/gtkmenutrackeritem.h | 2 ++ libqmenumodel/src/unitymenumodel.cpp | 25 ++++++++++++++++++--- 4 files changed, 75 insertions(+), 10 deletions(-) (limited to 'examples') diff --git a/examples/unityqmlmenumodel.qml b/examples/unityqmlmenumodel.qml index 8028674..e1de3c8 100644 --- a/examples/unityqmlmenumodel.qml +++ b/examples/unityqmlmenumodel.qml @@ -63,13 +63,21 @@ Item { Component { id: slider - Row { - anchors.fill: parent - Image { - source: ext.minIcon - } - Image { - source: ext.maxIcon + Rectangle { + width: listview.width + color: "#ddd" + height: 40 + Row { + anchors.fill: parent + Image { + source: ext.minIcon + } + Text { + text: model.actionState + } + Image { + source: ext.maxIcon + } } } } diff --git a/libqmenumodel/src/gtk/gtkmenutrackeritem.c b/libqmenumodel/src/gtk/gtkmenutrackeritem.c index 356422d..fb856c9 100644 --- a/libqmenumodel/src/gtk/gtkmenutrackeritem.c +++ b/libqmenumodel/src/gtk/gtkmenutrackeritem.c @@ -91,6 +91,7 @@ struct _GtkMenuTrackerItem guint toggled : 1; guint submenu_shown : 1; guint submenu_requested : 1; + GVariant *action_state; }; enum { @@ -105,6 +106,7 @@ enum { PROP_TOGGLED, PROP_ACCEL, PROP_SUBMENU_SHOWN, + PROP_ACTION_STATE, N_PROPS }; @@ -177,6 +179,9 @@ gtk_menu_tracker_item_get_property (GObject *object, case PROP_SUBMENU_SHOWN: g_value_set_boolean (value, gtk_menu_tracker_item_get_submenu_shown (self)); break; + case PROP_ACTION_STATE: + g_value_set_variant (value, self->action_state); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -193,6 +198,9 @@ gtk_menu_tracker_item_finalize (GObject *object) if (self->observable) g_object_unref (self->observable); + if (self->action_state) + g_variant_unref (self->action_state); + g_object_unref (self->item); G_OBJECT_CLASS (gtk_menu_tracker_item_parent_class)->finalize (object); @@ -231,6 +239,8 @@ gtk_menu_tracker_item_class_init (GtkMenuTrackerItemClass *class) g_param_spec_string ("accel", "", "", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); gtk_menu_tracker_item_pspecs[PROP_SUBMENU_SHOWN] = g_param_spec_boolean ("submenu-shown", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); + gtk_menu_tracker_item_pspecs[PROP_ACTION_STATE] = + g_param_spec_boolean ("action-state", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); g_object_class_install_properties (class, N_PROPS, gtk_menu_tracker_item_pspecs); } @@ -284,6 +294,12 @@ gtk_menu_tracker_item_action_added (GtkActionObserver *observer, if (self->role != GTK_MENU_TRACKER_ITEM_ROLE_NORMAL) g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_ROLE]); + if (state != NULL) + { + self->action_state = g_variant_ref (state); + g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_ACTION_STATE]); + } + g_object_thaw_notify (G_OBJECT (self)); if (action_target) @@ -339,6 +355,11 @@ gtk_menu_tracker_item_action_state_changed (GtkActionObserver *observer, if (self->toggled != was_toggled) g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_TOGGLED]); + + if (self->action_state) + g_variant_unref (self->action_state); + self->action_state = g_variant_ref (state); + g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_ACTION_STATE]); } static void @@ -371,6 +392,12 @@ gtk_menu_tracker_item_action_removed (GtkActionObserver *observer, g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_ROLE]); } + if (self->action_state != NULL) + { + g_variant_unref (self->action_state); + g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_ACTION_STATE]); + } + g_object_thaw_notify (G_OBJECT (self)); } @@ -585,6 +612,15 @@ gtk_menu_tracker_item_get_submenu_shown (GtkMenuTrackerItem *self) return self->submenu_shown; } +GVariant * +gtk_menu_tracker_item_get_action_state (GtkMenuTrackerItem *self) +{ + if (self->action_state != NULL) + return g_variant_ref (self->action_state); + + return NULL; +} + static void gtk_menu_tracker_item_set_submenu_shown (GtkMenuTrackerItem *self, gboolean submenu_shown) diff --git a/libqmenumodel/src/gtk/gtkmenutrackeritem.h b/libqmenumodel/src/gtk/gtkmenutrackeritem.h index 7e98a55..16c4415 100644 --- a/libqmenumodel/src/gtk/gtkmenutrackeritem.h +++ b/libqmenumodel/src/gtk/gtkmenutrackeritem.h @@ -81,6 +81,8 @@ void gtk_menu_tracker_item_request_submenu_shown (GtkMenu gboolean gtk_menu_tracker_item_get_submenu_shown (GtkMenuTrackerItem *self); +GVariant * gtk_menu_tracker_item_get_action_state (GtkMenuTrackerItem *self); + gboolean gtk_menu_tracker_item_get_attribute (GtkMenuTrackerItem *self, const gchar *attribute, const gchar *format, diff --git a/libqmenumodel/src/unitymenumodel.cpp b/libqmenumodel/src/unitymenumodel.cpp index 418de61..114c985 100644 --- a/libqmenumodel/src/unitymenumodel.cpp +++ b/libqmenumodel/src/unitymenumodel.cpp @@ -17,6 +17,7 @@ */ #include "unitymenumodel.h" +#include "converter.h" extern "C" { #include "gtk/gtkactionmuxer.h" @@ -29,13 +30,13 @@ G_DEFINE_QUARK (UNITY_MENU_ITEM_ITERATOR, unity_menu_item_iterator) G_DEFINE_QUARK (UNITY_MENU_ITEM_EXTENDED_ATTRIBUTES, unity_menu_item_extended_attributes) enum MenuRoles { - ActionRole = Qt::DisplayRole + 1, - LabelRole, + LabelRole = Qt::DisplayRole + 1, SensitiveRole, IsSeparatorRole, IconRole, TypeRole, ExtendedAttributesRole, + ActionStateRole }; class UnityMenuModelPrivate @@ -48,6 +49,7 @@ public: void clearName(); void updateActions(); void updateMenuModel(); + QVariant itemState(GtkMenuTrackerItem *item); UnityMenuModel *model; GtkActionMuxer *muxer; @@ -161,6 +163,19 @@ void UnityMenuModelPrivate::updateMenuModel() } } +QVariant UnityMenuModelPrivate::itemState(GtkMenuTrackerItem *item) +{ + QVariant result; + + GVariant *state = gtk_menu_tracker_item_get_action_state (item); + if (state != NULL) { + result = Converter::toQVariant(state); + g_variant_unref (state); + } + + return result; +} + void UnityMenuModelPrivate::nameAppeared(GDBusConnection *connection, const gchar *name, const gchar *owner, gpointer user_data) { UnityMenuModelPrivate *priv = (UnityMenuModelPrivate *)user_data; @@ -367,6 +382,9 @@ QVariant UnityMenuModel::data(const QModelIndex &index, int role) const return map ? *map : QVariant(); } + case ActionStateRole: + return priv->itemState(item); + default: return QVariant(); } @@ -382,17 +400,18 @@ QModelIndex UnityMenuModel::parent(const QModelIndex &index) const return QModelIndex(); } +#include QHash UnityMenuModel::roleNames() const { QHash names; names[LabelRole] = "label"; - names[ActionRole] = "action"; names[SensitiveRole] = "sensitive"; names[IsSeparatorRole] = "isSeparator"; names[IconRole] = "icon"; names[TypeRole] = "type"; names[ExtendedAttributesRole] = "ext"; + names[ActionStateRole] = "actionState"; return names; } -- cgit v1.2.3 From 2bbdf4e2347ec566280b9d878a12b7b1e732f632 Mon Sep 17 00:00:00 2001 From: Nick Dedekind Date: Fri, 9 Aug 2013 10:50:12 +0100 Subject: glib callbacks pass events through qt. --- examples/unityqmlmenumodel.qml | 2 +- libqmenumodel/src/CMakeLists.txt | 1 + libqmenumodel/src/unitymenumodel.cpp | 95 +++++++++++++++++++++--------- libqmenumodel/src/unitymenumodel.h | 3 + libqmenumodel/src/unitymenumodelevents.cpp | 63 ++++++++++++++++++++ libqmenumodel/src/unitymenumodelevents.h | 69 ++++++++++++++++++++++ 6 files changed, 204 insertions(+), 29 deletions(-) create mode 100644 libqmenumodel/src/unitymenumodelevents.cpp create mode 100644 libqmenumodel/src/unitymenumodelevents.h (limited to 'examples') diff --git a/examples/unityqmlmenumodel.qml b/examples/unityqmlmenumodel.qml index e1de3c8..c0e5adc 100644 --- a/examples/unityqmlmenumodel.qml +++ b/examples/unityqmlmenumodel.qml @@ -108,7 +108,7 @@ Item { if (submenu) listview.model = submenu; else - listview.model.activate(index); + action.activate(); } } } diff --git a/libqmenumodel/src/CMakeLists.txt b/libqmenumodel/src/CMakeLists.txt index e0ee902..db8095a 100644 --- a/libqmenumodel/src/CMakeLists.txt +++ b/libqmenumodel/src/CMakeLists.txt @@ -12,6 +12,7 @@ set(QMENUMODEL_SRC qstateaction.cpp unitymenuaction.cpp unitymenumodel.cpp + unitymenumodelevents.cpp unitythemediconprovider.cpp gtk/gtkactionmuxer.c gtk/gtkactionmuxer.h diff --git a/libqmenumodel/src/unitymenumodel.cpp b/libqmenumodel/src/unitymenumodel.cpp index 5226747..8e0f0d1 100644 --- a/libqmenumodel/src/unitymenumodel.cpp +++ b/libqmenumodel/src/unitymenumodel.cpp @@ -20,9 +20,11 @@ #include "converter.h" #include "actionstateparser.h" #include "unitymenuaction.h" +#include "unitymenumodelevents.h" #include #include +#include extern "C" { #include "gtk/gtkactionmuxer.h" @@ -165,18 +167,8 @@ UnityMenuModelPrivate::~UnityMenuModelPrivate() void UnityMenuModelPrivate::clearItems(bool resetModel) { - GSequenceIter *begin; - GSequenceIter *end; - - if (resetModel) - model->beginResetModel(); - - begin = g_sequence_get_begin_iter (this->items); - end = g_sequence_get_end_iter (this->items); - g_sequence_remove_range (begin, end); - - if (resetModel) - model->endResetModel(); + UnityMenuModelClearEvent ummce(resetModel); + QCoreApplication::sendEvent(model, &ummce); } void UnityMenuModelPrivate::clearName() @@ -260,28 +252,17 @@ void UnityMenuModelPrivate::nameVanished(GDBusConnection *connection, const gcha void UnityMenuModelPrivate::menuItemInserted(GtkMenuTrackerItem *item, gint position, gpointer user_data) { UnityMenuModelPrivate *priv = (UnityMenuModelPrivate *)user_data; - GSequenceIter *it; - - priv->model->beginInsertRows(QModelIndex(), position, position); - - it = g_sequence_get_iter_at_pos (priv->items, position); - it = g_sequence_insert_before (it, g_object_ref (item)); - g_object_set_qdata (G_OBJECT (item), unity_menu_model_quark (), priv->model); - g_signal_connect (item, "notify", G_CALLBACK (menuItemChanged), it); - priv->model->endInsertRows(); + UnityMenuModelAddRowEvent ummare(item, position); + QCoreApplication::sendEvent(priv->model, &ummare); } void UnityMenuModelPrivate::menuItemRemoved(gint position, gpointer user_data) { UnityMenuModelPrivate *priv = (UnityMenuModelPrivate *)user_data; - GSequenceIter *it; - - priv->model->beginRemoveRows(QModelIndex(), position, position); - g_sequence_remove (g_sequence_get_iter_at_pos (priv->items, position)); - - priv->model->endRemoveRows(); + UnityMenuModelRemoveRowEvent ummrre(position); + QCoreApplication::sendEvent(priv->model, &ummrre); } void UnityMenuModelPrivate::menuItemChanged(GObject *object, GParamSpec *pspec, gpointer user_data) @@ -297,7 +278,9 @@ void UnityMenuModelPrivate::menuItemChanged(GObject *object, GParamSpec *pspec, model = (UnityMenuModel *) g_object_get_qdata (G_OBJECT (item), unity_menu_model_quark ()); position = g_sequence_iter_get_position (it); - Q_EMIT model->dataChanged(model->index(position, 0), model->index(position, 0)); + // FIXME + UnityMenuModelDataChangeEvent ummdce(position); + QCoreApplication::sendEvent(model, &ummdce); } UnityMenuModel::UnityMenuModel(QObject *parent): @@ -639,3 +622,59 @@ QVariant UnityMenuModel::get(int row, const QByteArray &role) return this->data(this->index(row, 0), priv->roles[role]); } + +bool UnityMenuModel::event(QEvent* e) +{ + if (e->type() == UnityMenuModelClearEvent::eventType) { + UnityMenuModelClearEvent *emmce = static_cast(e); + + GSequenceIter *begin; + GSequenceIter *end; + + if (emmce->reset) + beginResetModel(); + + begin = g_sequence_get_begin_iter (priv->items); + end = g_sequence_get_end_iter (priv->items); + g_sequence_remove_range (begin, end); + + if (emmce->reset) + endResetModel(); + + return true; + } else if (e->type() == UnityMenuModelAddRowEvent::eventType) { + UnityMenuModelAddRowEvent *ummrce = static_cast(e); + + GSequenceIter *it; + it = g_sequence_get_iter_at_pos (priv->items, ummrce->position); + if (it) { + beginInsertRows(QModelIndex(), ummrce->position, ummrce->position); + + it = g_sequence_insert_before (it, g_object_ref (ummrce->item)); + g_object_set_qdata (G_OBJECT (ummrce->item), unity_menu_model_quark (), this); + g_signal_connect (ummrce->item, "notify", G_CALLBACK (UnityMenuModelPrivate::menuItemChanged), it); + + endInsertRows(); + } + return true; + } else if (e->type() == UnityMenuModelRemoveRowEvent::eventType) { + UnityMenuModelRemoveRowEvent *ummrre = static_cast(e); + + GSequenceIter *it; + it = g_sequence_get_iter_at_pos (priv->items, ummrre->position); + if (it) { + beginRemoveRows(QModelIndex(), ummrre->position, ummrre->position); + + g_sequence_remove (it); + + endRemoveRows(); + } + return true; + } else if (e->type() == UnityMenuModelDataChangeEvent::eventType) { + UnityMenuModelDataChangeEvent *ummdce = static_cast(e); + + Q_EMIT dataChanged(index(ummdce->position, 0), index(ummdce->position, 0)); + return true; + } + return QAbstractListModel::event(e); +} diff --git a/libqmenumodel/src/unitymenumodel.h b/libqmenumodel/src/unitymenumodel.h index 5401331..4aaadfd 100644 --- a/libqmenumodel/src/unitymenumodel.h +++ b/libqmenumodel/src/unitymenumodel.h @@ -64,6 +64,9 @@ Q_SIGNALS: void menuObjectPathChanged(const QByteArray &path); void actionStateParserChanged(ActionStateParser* parser); +protected: + virtual bool event(QEvent* e); + private: class UnityMenuModelPrivate *priv; friend class UnityMenuModelPrivate; diff --git a/libqmenumodel/src/unitymenumodelevents.cpp b/libqmenumodel/src/unitymenumodelevents.cpp new file mode 100644 index 0000000..e03d1c7 --- /dev/null +++ b/libqmenumodel/src/unitymenumodelevents.cpp @@ -0,0 +1,63 @@ +/* + * 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 . + * + * Authors: + * Nicholas Dedekind +#include +} + +#include "unitymenumodelevents.h" +#include "unitymenumodel.h" + +const QEvent::Type UnityMenuModelClearEvent::eventType = static_cast(QEvent::registerEventType()); +const QEvent::Type UnityMenuModelAddRowEvent::eventType = static_cast(QEvent::registerEventType()); +const QEvent::Type UnityMenuModelRemoveRowEvent::eventType = static_cast(QEvent::registerEventType()); +const QEvent::Type UnityMenuModelDataChangeEvent::eventType = static_cast(QEvent::registerEventType()); + +UnityMenuModelClearEvent::UnityMenuModelClearEvent(bool _reset) + : QEvent(UnityMenuModelClearEvent::eventType), + reset(_reset) +{} + +UnityMenuModelAddRowEvent::UnityMenuModelAddRowEvent(GtkMenuTrackerItem *_item, int _position) + : QEvent(UnityMenuModelAddRowEvent::eventType), + item(_item), + position(_position) +{ + if (item) { + g_object_ref(item); + } +} + +UnityMenuModelAddRowEvent::~UnityMenuModelAddRowEvent() +{ + if (item) { + g_object_unref(item); + } +} + +UnityMenuModelRemoveRowEvent::UnityMenuModelRemoveRowEvent(int _position) + : QEvent(UnityMenuModelRemoveRowEvent::eventType), + position(_position) +{} + +UnityMenuModelDataChangeEvent::UnityMenuModelDataChangeEvent(int _position) + : QEvent(UnityMenuModelDataChangeEvent::eventType), + position(_position) +{} diff --git a/libqmenumodel/src/unitymenumodelevents.h b/libqmenumodel/src/unitymenumodelevents.h new file mode 100644 index 0000000..dcb27ff --- /dev/null +++ b/libqmenumodel/src/unitymenumodelevents.h @@ -0,0 +1,69 @@ +/* + * 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 . + * + * Authors: + * Nicholas Dedekind + +typedef struct _GtkMenuTrackerItem GtkMenuTrackerItem; + +/* Event for a unitymenumodel clear */ +class UnityMenuModelClearEvent : public QEvent +{ +public: + static const QEvent::Type eventType; + UnityMenuModelClearEvent(bool reset); + + bool reset; +}; + +/* Event for a row add for unitymenumodel */ +class UnityMenuModelAddRowEvent : public QEvent +{ +public: + static const QEvent::Type eventType; + UnityMenuModelAddRowEvent(GtkMenuTrackerItem *item, int position); + ~UnityMenuModelAddRowEvent(); + + GtkMenuTrackerItem *item; + int position; +}; + +/* Event for a row remove for unitymenumodel */ +class UnityMenuModelRemoveRowEvent : public QEvent +{ +public: + static const QEvent::Type eventType; + UnityMenuModelRemoveRowEvent(int position); + + int position; +}; + +/* Event for a row data change for unitymenumodel */ +class UnityMenuModelDataChangeEvent : public QEvent +{ +public: + static const QEvent::Type eventType; + UnityMenuModelDataChangeEvent(int position); + + int position; +}; + +#endif //UNITYMENUMODELEVENTS_H -- cgit v1.2.3