From ca81974f1fe8454c725e80aa943705d40398a2ad Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 25 Jul 2013 06:09:59 +0200 Subject: unitymenumodel: expose type and extended attributes to qml --- libqmenumodel/src/gtk/gtkmenutrackeritem.c | 41 +++++++++++ libqmenumodel/src/gtk/gtkmenutrackeritem.h | 9 +++ libqmenumodel/src/unitymenumodel.cpp | 114 ++++++++++++++++++++++++++++- libqmenumodel/src/unitymenumodel.h | 1 + 4 files changed, 164 insertions(+), 1 deletion(-) diff --git a/libqmenumodel/src/gtk/gtkmenutrackeritem.c b/libqmenumodel/src/gtk/gtkmenutrackeritem.c index 2d712a1..356422d 100644 --- a/libqmenumodel/src/gtk/gtkmenutrackeritem.c +++ b/libqmenumodel/src/gtk/gtkmenutrackeritem.c @@ -786,3 +786,44 @@ gtk_menu_tracker_item_request_submenu_shown (GtkMenuTrackerItem *self, else gtk_menu_tracker_item_set_submenu_shown (self, shown); } + +gboolean +gtk_menu_tracker_item_get_attribute (GtkMenuTrackerItem *self, + const gchar *attribute, + const gchar *format, + ...) +{ + gboolean success = FALSE; + GVariant *value; + + g_return_val_if_fail (GTK_IS_MENU_TRACKER_ITEM (self), FALSE); + g_return_val_if_fail (attribute != NULL, FALSE); + g_return_val_if_fail (format != NULL, FALSE); + + value = g_menu_item_get_attribute_value (self->item, attribute, NULL); + if (value) + { + if (g_variant_check_format_string (value, format, TRUE)) + { + va_list args; + + va_start (args, format); + g_variant_get_va (value, format, NULL, &args); + va_end (args); + + success = TRUE; + } + + g_variant_unref (value); + } + + return success; +} + +GVariant * +gtk_menu_tracker_item_get_attribute_value (GtkMenuTrackerItem *self, + const gchar *attribute, + const GVariantType *expected_type) +{ + return g_menu_item_get_attribute_value (self->item, attribute, expected_type); +} diff --git a/libqmenumodel/src/gtk/gtkmenutrackeritem.h b/libqmenumodel/src/gtk/gtkmenutrackeritem.h index 9db30eb..7e98a55 100644 --- a/libqmenumodel/src/gtk/gtkmenutrackeritem.h +++ b/libqmenumodel/src/gtk/gtkmenutrackeritem.h @@ -81,4 +81,13 @@ void gtk_menu_tracker_item_request_submenu_shown (GtkMenu gboolean gtk_menu_tracker_item_get_submenu_shown (GtkMenuTrackerItem *self); +gboolean gtk_menu_tracker_item_get_attribute (GtkMenuTrackerItem *self, + const gchar *attribute, + const gchar *format, + ...); + +GVariant * gtk_menu_tracker_item_get_attribute_value (GtkMenuTrackerItem *self, + const gchar *attribute, + const GVariantType *expected_type); + #endif diff --git a/libqmenumodel/src/unitymenumodel.cpp b/libqmenumodel/src/unitymenumodel.cpp index db70936..0fc5612 100644 --- a/libqmenumodel/src/unitymenumodel.cpp +++ b/libqmenumodel/src/unitymenumodel.cpp @@ -26,13 +26,16 @@ extern "C" { G_DEFINE_QUARK (UNITY_MENU_MODEL, unity_menu_model) G_DEFINE_QUARK (UNITY_SUBMENU_MODEL, unity_submenu_model) 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, SensitiveRole, IsSeparatorRole, - IconRole + IconRole, + TypeRole, + ExtendedAttributesRole, }; class UnityMenuModelPrivate @@ -348,6 +351,22 @@ QVariant UnityMenuModel::data(const QModelIndex &index, int role) const return QString(); } + case TypeRole: { + gchar *type; + if (gtk_menu_tracker_item_get_attribute (item, "x-canonical-type", "s", &type)) { + QVariant v(type); + g_free (type); + return v; + } + else + return QVariant(); + } + + case ExtendedAttributesRole: { + QVariantMap *map = (QVariantMap *) g_object_get_qdata (G_OBJECT (item), unity_menu_item_extended_attributes_quark ()); + return map ? *map : QVariant(); + } + default: return QVariant(); } @@ -372,6 +391,8 @@ QHash UnityMenuModel::roleNames() const names[SensitiveRole] = "sensitive"; names[IsSeparatorRole] = "isSeparator"; names[IconRole] = "icon"; + names[TypeRole] = "type"; + names[ExtendedAttributesRole] = "ext"; return names; } @@ -411,3 +432,94 @@ void UnityMenuModel::activate(int index) item = (GtkMenuTrackerItem *) g_sequence_get (g_sequence_get_iter_at_pos (priv->items, index)); gtk_menu_tracker_item_activated (item); } + +static void freeExtendedAttrs(gpointer data) +{ + QVariantMap *extendedAttrs = (QVariantMap *) data; + delete extendedAttrs; +} + +static QVariant attributeToQVariant(GVariant *value, const QString &type) +{ + QVariant result; + + if (type == "int") { + if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32)) + result = QVariant(g_variant_get_int32(value)); + } + if (type == "bool") { + if (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)) + result = QVariant(g_variant_get_int32(value)); + } + else if (type == "string") { + if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) + result = QVariant(g_variant_get_string(value, NULL)); + } + else if (type == "icon") { + GIcon *icon = g_icon_deserialize (value); + if (icon) { + result = iconUri(icon); + g_object_unref (icon); + } + else { + result = QVariant(""); + } + } + + return result; +} + +/* convert 'some-key' to 'someKey' or 'SomeKey'. (from dconf-qt) */ +static QString qtify_name(const char *name) +{ + bool next_cap = false; + QString result; + + while (*name) { + if (*name == '-') { + next_cap = true; + } else if (next_cap) { + result.append(toupper(*name)); + next_cap = false; + } else { + result.append(*name); + } + + name++; + } + + return result; +} + +bool UnityMenuModel::loadExtendedAttributes(int position, const QVariantMap &schema) +{ + GtkMenuTrackerItem *item; + QVariantMap *extendedAttrs; + + item = (GtkMenuTrackerItem *) g_sequence_get (g_sequence_get_iter_at_pos (priv->items, position)); + + extendedAttrs = new QVariantMap; + + for (QVariantMap::const_iterator it = schema.constBegin(); it != schema.constEnd(); ++it) { + QString name = it.key(); + QString type = it.value().toString(); + + GVariant *value = gtk_menu_tracker_item_get_attribute_value (item, name.toUtf8(), NULL); + if (value == NULL) { + qWarning("loadExtendedAttributes: menu item does not contain '%s'", it.key().toUtf8().constData()); + continue; + } + + QVariant qvalue = attributeToQVariant(value, type); + if (qvalue.isValid()) + extendedAttrs->insert(qtify_name (name.toUtf8()), qvalue); + else + qWarning("loadExtendedAttributes: key '%s' is of type '%s' (expected '%s')", + name.toUtf8().constData(), g_variant_get_type_string(value), type.constData()); + + g_variant_unref (value); + } + + g_object_set_qdata_full (G_OBJECT (item), unity_menu_item_extended_attributes_quark (), + extendedAttrs, freeExtendedAttrs); +} diff --git a/libqmenumodel/src/unitymenumodel.h b/libqmenumodel/src/unitymenumodel.h index 896c806..9151217 100644 --- a/libqmenumodel/src/unitymenumodel.h +++ b/libqmenumodel/src/unitymenumodel.h @@ -49,6 +49,7 @@ public: QHash roleNames() const; Q_INVOKABLE QObject * submenu(int position); + Q_INVOKABLE bool loadExtendedAttributes(int position, const QVariantMap &schema); Q_SIGNALS: void busNameChanged(const QByteArray &name); -- cgit v1.2.3