diff options
Diffstat (limited to 'libqmenumodel')
-rw-r--r-- | libqmenumodel/QMenuModel/CMakeLists.txt | 6 | ||||
-rw-r--r-- | libqmenumodel/src/converter.cpp | 194 | ||||
-rw-r--r-- | libqmenumodel/src/converter.h | 2 | ||||
-rw-r--r-- | libqmenumodel/src/logging.h | 23 | ||||
-rw-r--r-- | libqmenumodel/src/qdbusobject.cpp | 1 | ||||
-rw-r--r-- | libqmenumodel/src/qstateaction.cpp | 20 | ||||
-rw-r--r-- | libqmenumodel/src/qstateaction.h | 2 | ||||
-rw-r--r-- | libqmenumodel/src/unitymenumodel.cpp | 25 | ||||
-rw-r--r-- | libqmenumodel/src/unitymenumodel.h | 2 |
9 files changed, 195 insertions, 80 deletions
diff --git a/libqmenumodel/QMenuModel/CMakeLists.txt b/libqmenumodel/QMenuModel/CMakeLists.txt index 78e062b..eb4d463 100644 --- a/libqmenumodel/QMenuModel/CMakeLists.txt +++ b/libqmenumodel/QMenuModel/CMakeLists.txt @@ -24,11 +24,7 @@ qt5_use_modules(qmenumodel-qml Qml Quick) execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" "${CMAKE_CURRENT_BINARY_DIR}/qmldir") -execute_process( - COMMAND qmake -query QT_INSTALL_QML - OUTPUT_VARIABLE QT_IMPORTS_DIR - OUTPUT_STRIP_TRAILING_WHITESPACE -) +set(QT_IMPORTS_DIR "${CMAKE_INSTALL_LIBDIR}/qt5/qml") set(QMLPLUGIN_INSTALL_PREFIX "${QT_IMPORTS_DIR}/QMenuModel") install(TARGETS qmenumodel-qml DESTINATION ${QMLPLUGIN_INSTALL_PREFIX}) install(FILES qmldir DESTINATION ${QMLPLUGIN_INSTALL_PREFIX}) diff --git a/libqmenumodel/src/converter.cpp b/libqmenumodel/src/converter.cpp index 69e6629..459e77f 100644 --- a/libqmenumodel/src/converter.cpp +++ b/libqmenumodel/src/converter.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012 Canonical Ltd. + * Copyright 2012-2016 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 @@ -15,6 +15,7 @@ * * Authors: * Renato Araujo Oliveira Filho <renato@canonical.com> + * Marco Trevisan <marco.trevisan@canonical.com> */ extern "C" { @@ -24,6 +25,7 @@ extern "C" { #include "converter.h" #include <QDebug> +#include <QString> #include <QVariant> /*! \internal */ @@ -57,6 +59,26 @@ QVariant Converter::toQVariant(GVariant *value) gsize size = 0; const gchar *v = g_variant_get_string(value, &size); result.setValue(QString::fromUtf8(v, size)); + } else if (g_variant_type_equal(type, G_VARIANT_TYPE_STRING_ARRAY)) { + gsize size = 0; + const gchar **sa = g_variant_get_strv(value, &size); + QStringList list; + for (gsize i = 0; i < size; ++i) { + list << QString::fromUtf8(sa[i]); + } + result.setValue(list); + g_free(sa); + } else if (g_variant_type_equal(type, G_VARIANT_TYPE_BYTESTRING)) { + result.setValue(QByteArray(g_variant_get_bytestring(value))); + } else if (g_variant_type_equal(type, G_VARIANT_TYPE_BYTESTRING_ARRAY)) { + gsize size = 0; + const gchar **bsa = g_variant_get_bytestring_array(value, &size); + QByteArrayList list; + for (gsize i = 0; i < size; ++i) { + list << bsa[i]; + } + result.setValue(list); + g_free(bsa); } else if (g_variant_type_equal(type, G_VARIANT_TYPE_VARIANT)) { GVariant *var = g_variant_get_variant(value); result = toQVariant(var); @@ -109,32 +131,33 @@ QVariant Converter::toQVariant(GVariant *value) * G_VARIANT_TYPE_UNIT * G_VARIANT_TYPE_DICT_ENTRY * G_VARIANT_TYPE_DICTIONARY - * G_VARIANT_TYPE_STRING_ARRAY - * G_VARIANT_TYPE_BYTESTRING * G_VARIANT_TYPE_OBJECT_PATH_ARRAY - * G_VARIANT_TYPE_BYTESTRING_ARRAY */ return result; } -static GVariant* toGVariant(const QString &typeName, const QVariant &value) +QVariant Converter::toQVariantFromVariantString(const QString &variantString) { - if (typeName == "uchar") { - return g_variant_new_byte(value.value<uchar>()); - } else if (typeName == "short") { - return g_variant_new_int16(value.value<short>()); - } else if (typeName == "ushort") { - return g_variant_new_uint16(value.value<ushort>()); - } else if (typeName == "long") { - return g_variant_new_int64(value.value<long>()); - } else if (typeName == "ulong") { - return g_variant_new_uint64(value.value<ulong>()); - } else { - qWarning() << "QVariant type not supported:" << typeName; + GVariant *gvariant; + GError *error = NULL; + + if (variantString.isEmpty()) { + return QVariant(); } - return NULL; + gvariant = g_variant_parse (NULL, qUtf8Printable(variantString), NULL, NULL, &error); + + if (error) { + qWarning() << "Impossible to parse" << variantString << "as variant string:"<< error->message; + g_error_free (error); + return QVariant(); + } + + const QVariant& qvariant = Converter::toQVariant(gvariant); + g_variant_unref (gvariant); + + return qvariant; } GVariant* Converter::toGVariant(const QVariant &value) @@ -156,12 +179,33 @@ GVariant* Converter::toGVariant(const QVariant &value) case QVariant::Int: result = g_variant_new_int32(value.toInt()); break; + case QVariant::LongLong: + result = g_variant_new_int64(value.toLongLong()); + break; case QVariant::String: - result = g_variant_new_string(value.toString().toUtf8().data()); + result = g_variant_new_string(qUtf8Printable(value.toString())); break; case QVariant::UInt: result = g_variant_new_uint32(value.toUInt()); break; + case QVariant::ULongLong: + result = g_variant_new_uint64(value.toULongLong()); + break; + case QMetaType::UChar: + result = g_variant_new_byte(value.value<uchar>()); + break; + case QMetaType::Short: + result = g_variant_new_int16(value.value<short>()); + break; + case QMetaType::UShort: + result = g_variant_new_uint16(value.value<ushort>()); + break; + case QMetaType::Long: + result = g_variant_new_int64(value.value<long>()); + break; + case QMetaType::ULong: + result = g_variant_new_uint64(value.value<ulong>()); + break; case QVariant::Map: { GVariantBuilder *b; @@ -171,7 +215,19 @@ GVariant* Converter::toGVariant(const QVariant &value) QMapIterator<QString, QVariant> i(value.toMap()); while (i.hasNext()) { i.next(); - g_variant_builder_add(b, "{sv}", i.key().toUtf8().data(), toGVariant(i.value())); + g_variant_builder_add(b, "{sv}", qUtf8Printable(i.key()), toGVariant(i.value())); + } + result = g_variant_builder_end(b); + g_variant_builder_unref(b); + break; + } + case QMetaType::QByteArrayList: + { + const QByteArrayList &list = qvariant_cast<QByteArrayList>(value); + GVariantBuilder *b = g_variant_builder_new(G_VARIANT_TYPE_BYTESTRING_ARRAY); + + for (const QByteArray &ba : list) { + g_variant_builder_add_value(b, g_variant_new_bytestring(ba)); } result = g_variant_builder_end(b); g_variant_builder_unref(b); @@ -179,17 +235,28 @@ GVariant* Converter::toGVariant(const QVariant &value) } case QVariant::List: { - QVariantList lst = value.toList(); - GVariant **vars = g_new(GVariant*, lst.size()); - for (int i=0; i < lst.size(); i++) { - vars[i] = toGVariant(lst[i]); + GVariantBuilder *b = g_variant_builder_new(G_VARIANT_TYPE_TUPLE); + + for (const QVariant &v : value.toList()) { + g_variant_builder_add_value(b, toGVariant(v)); } - result = g_variant_new_tuple(vars, lst.size()); - g_free(vars); + result = g_variant_builder_end(b); + g_variant_builder_unref(b); + break; + } + case QVariant::StringList: + { + GVariantBuilder *b = g_variant_builder_new(G_VARIANT_TYPE_STRING_ARRAY); + + for (const QString &s : value.toStringList()) { + g_variant_builder_add(b, "s", qUtf8Printable(s)); + } + result = g_variant_builder_end(b); + g_variant_builder_unref(b); break; } default: - result = ::toGVariant(value.typeName(), value); + qWarning() << "QVariant type not supported:" << value.type(); } return result; @@ -202,8 +269,7 @@ GVariant* Converter::toGVariantWithSchema(const QVariant &value, const char* sch } GVariant* result = NULL; - const GVariantType* schema_type; - schema_type = g_variant_type_new(schema); + GVariantType* schema_type = g_variant_type_new(schema); if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_BOOLEAN)) { if (value.canConvert<bool>()) { @@ -243,80 +309,65 @@ GVariant* Converter::toGVariantWithSchema(const QVariant &value, const char* sch } } 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()); + result = g_variant_new_string(qUtf8Printable(value.toString())); } } else if (g_variant_type_equal(schema_type, G_VARIANT_TYPE_VARIANT)) { - result = Converter::toGVariant(value); + result = g_variant_new_variant(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* entryType = g_variant_type_element(schema_type); + const gchar* entryTypeString = g_variant_type_peek_string(entryType); - 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()); - + GVariantBuilder *b = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); bool ok = true; - for (int i=0; i < lst.size(); i++) { - data = Converter::toGVariantWithSchema(lst[i], entryTypeString); + + for (const QVariant &v : value.toList()) { + GVariant *data = toGVariantWithSchema(v, entryTypeString); if (data) { - vars[i] = data; - } - else { + g_variant_builder_add_value(b, 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()); + result = g_variant_builder_end(b); } - g_free(entryTypeString); - g_free(vars); + g_variant_builder_unref(b); } } 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); + const GVariantType* entryType = g_variant_type_first(schema_type); + GVariantBuilder *b = g_variant_builder_new(G_VARIANT_TYPE_TUPLE); 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); + for (const QVariant &v : value.toList()) { + gchar* entryTypeString = g_variant_type_dup_string(entryType); + GVariant *data = toGVariantWithSchema(v, entryTypeString); + g_free(entryTypeString); if (data) { - vars[i] = data; - } - else { + g_variant_builder_add_value(b, data); + entryType = g_variant_type_next(entryType); + if (!entryType) + break; + } 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) { + qWarning() << "Failed to convert list to array with schema:" << schema; break; } } if (ok) { - result = g_variant_new_tuple(vars, lst.size()); + result = g_variant_builder_end(b); } - g_free(vars); + g_variant_builder_unref(b); } } @@ -324,6 +375,9 @@ GVariant* Converter::toGVariantWithSchema(const QVariant &value, const char* sch if (!result) { result = Converter::toGVariant(value); } + + g_free(schema_type); + return result; } diff --git a/libqmenumodel/src/converter.h b/libqmenumodel/src/converter.h index f47c09e..27cdcae 100644 --- a/libqmenumodel/src/converter.h +++ b/libqmenumodel/src/converter.h @@ -21,12 +21,14 @@ #define CONVERTER_H typedef struct _GVariant GVariant; +class QString; class QVariant; class Converter { public: static QVariant toQVariant(GVariant *value); + static QVariant toQVariantFromVariantString(const QString &variantString); static GVariant* toGVariant(const QVariant &value); // This converts a QVariant to a GVariant using a provided gvariant schema as diff --git a/libqmenumodel/src/logging.h b/libqmenumodel/src/logging.h new file mode 100644 index 0000000..bd7e708 --- /dev/null +++ b/libqmenumodel/src/logging.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 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 version 3, as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, + * SATISFACTORY QUALITY, 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/>. + */ + +#ifndef QMENUMODEL_LOGGING_H +#define QMENUMODEL_LOGGING_H + +#include <QLoggingCategory> +Q_DECLARE_LOGGING_CATEGORY(unitymenumodel) + +#endif // QMENUMODEL_LOGGING_H diff --git a/libqmenumodel/src/qdbusobject.cpp b/libqmenumodel/src/qdbusobject.cpp index be9fb93..fab2df7 100644 --- a/libqmenumodel/src/qdbusobject.cpp +++ b/libqmenumodel/src/qdbusobject.cpp @@ -81,7 +81,6 @@ QDBusObject::QDBusObject(QObject* listener) m_busType(DBusEnums::None), m_status(DBusEnums::Disconnected) { - g_type_init(); qRegisterMetaType<DBusEnums::ConnectionStatus>("DBusEnums::ConnectionStatus"); } diff --git a/libqmenumodel/src/qstateaction.cpp b/libqmenumodel/src/qstateaction.cpp index 983064a..fcffa44 100644 --- a/libqmenumodel/src/qstateaction.cpp +++ b/libqmenumodel/src/qstateaction.cpp @@ -19,6 +19,7 @@ #include "qstateaction.h" +#include "converter.h" #include "qdbusactiongroup.h" /*! @@ -99,6 +100,15 @@ void QStateAction::updateState(const QVariant &state) } /*! + Request for the state of action to be changed to \a paramenter. + This call merely requests a change. The action may refuse to change its state or may change its state to something other than \a paramenter. +*/ +void QStateAction::updateStateByVariantString(const QString &state) +{ + updateState(Converter::toQVariantFromVariantString(state)); +} + +/*! Activates the action passing \a parameter. \a parameter must be the correct type of parameter for the action */ @@ -107,6 +117,16 @@ void QStateAction::activate(const QVariant ¶meter) m_group->activateAction(m_name, parameter); } +/*! + Activates the action passing \a parameter using GLib Variant String format. + \a parameter must be the correct type of parameter for the action +*/ +void QStateAction::activateByVariantString(const QString ¶meter) +{ + activate(Converter::toQVariantFromVariantString(parameter)); +} + + /*! \internal */ QString QStateAction::name() const { diff --git a/libqmenumodel/src/qstateaction.h b/libqmenumodel/src/qstateaction.h index 0fc68c2..4d05a7a 100644 --- a/libqmenumodel/src/qstateaction.h +++ b/libqmenumodel/src/qstateaction.h @@ -36,7 +36,9 @@ public: bool isValid() const; Q_INVOKABLE void activate(const QVariant ¶meter = QVariant()); + Q_INVOKABLE void activateByVariantString(const QString ¶meter = QString()); Q_INVOKABLE void updateState(const QVariant ¶meter); + Q_INVOKABLE void updateStateByVariantString(const QString ¶meter); Q_SIGNALS: void stateChanged(QVariant state); diff --git a/libqmenumodel/src/unitymenumodel.cpp b/libqmenumodel/src/unitymenumodel.cpp index 6a75f40..192ee46 100644 --- a/libqmenumodel/src/unitymenumodel.cpp +++ b/libqmenumodel/src/unitymenumodel.cpp @@ -22,6 +22,7 @@ #include "unitymenumodelevents.h" #include "unitymenuaction.h" #include "unitymenuactionevents.h" +#include "logging.h" #include <QIcon> #include <QQmlComponent> @@ -34,6 +35,8 @@ extern "C" { #include "gtk/gtksimpleactionobserver.h" } +Q_LOGGING_CATEGORY(unitymenumodel, "qmenumodel.unitymenumodel", QtCriticalMsg) + G_DEFINE_QUARK (UNITY_MENU_MODEL, unity_menu_model) G_DEFINE_QUARK (UNITY_SUBMENU_MODEL, unity_submenu_model) G_DEFINE_QUARK (UNITY_MENU_ITEM_EXTENDED_ATTRIBUTES, unity_menu_item_extended_attributes) @@ -664,15 +667,15 @@ bool UnityMenuModel::loadExtendedAttributes(int position, const QVariantMap &sch 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()); + qCWarning(unitymenumodel, "loadExtendedAttributes: menu item does not contain '%s'", it.key().toUtf8().constData()); continue; } - QVariant qvalue = attributeToQVariant(value, type); + const 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')", + qCWarning(unitymenumodel, "loadExtendedAttributes: key '%s' is of type '%s' (expected '%s')", name.toUtf8().constData(), g_variant_get_type_string(value), type.constData()); g_variant_unref (value); @@ -699,6 +702,8 @@ void UnityMenuModel::activate(int index, const QVariant& parameter) { GSequenceIter *it; GtkMenuTrackerItem *item; + GVariant *value; + const GVariantType *parameter_type; it = g_sequence_get_iter_at_pos (priv->items, index); if (g_sequence_iter_is_end (it)) { @@ -714,7 +719,9 @@ void UnityMenuModel::activate(int index, const QVariant& parameter) gchar *action; action = gtk_menu_tracker_item_get_action_name (item); - g_action_group_activate_action (G_ACTION_GROUP (priv->muxer), action, Converter::toGVariant(parameter)); + parameter_type = g_action_group_get_action_parameter_type (G_ACTION_GROUP (priv->muxer), action); + value = Converter::toGVariantWithSchema(parameter, g_variant_type_peek_string (parameter_type)); + g_action_group_activate_action (G_ACTION_GROUP (priv->muxer), action, value); g_free (action); } else { @@ -722,6 +729,16 @@ void UnityMenuModel::activate(int index, const QVariant& parameter) } } +void UnityMenuModel::activateByVariantString(int index, const QString& parameter) +{ + activate(index, Converter::toQVariantFromVariantString(parameter)); +} + +void UnityMenuModel::changeStateByVariantString(int index, const QString& parameter) +{ + changeState(index, Converter::toQVariantFromVariantString(parameter)); +} + void UnityMenuModel::changeState(int index, const QVariant& parameter) { GSequenceIter *it; diff --git a/libqmenumodel/src/unitymenumodel.h b/libqmenumodel/src/unitymenumodel.h index 8816d22..ed3bcd7 100644 --- a/libqmenumodel/src/unitymenumodel.h +++ b/libqmenumodel/src/unitymenumodel.h @@ -63,7 +63,9 @@ public: Q_INVOKABLE QVariant get(int row, const QByteArray &role); Q_INVOKABLE void activate(int index, const QVariant& parameter = QVariant()); + Q_INVOKABLE void activateByVariantString(int index, const QString& parameter = QString()); Q_INVOKABLE void changeState(int index, const QVariant& parameter); + Q_INVOKABLE void changeStateByVariantString(int index, const QString& parameter); void registerAction(UnityMenuAction* action); void unregisterAction(UnityMenuAction* action); |