diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/CMakeLists.txt | 42 | ||||
-rw-r--r-- | src/common/qdbusactiongroup.cpp | 193 | ||||
-rw-r--r-- | src/common/qdbusactiongroup.h | 63 | ||||
-rw-r--r-- | src/common/qdbusmenumodel.cpp | 66 | ||||
-rw-r--r-- | src/common/qdbusmenumodel.h | 47 | ||||
-rw-r--r-- | src/common/qdbusobject.cpp | 127 | ||||
-rw-r--r-- | src/common/qdbusobject.h | 65 | ||||
-rw-r--r-- | src/common/qmenumodel.cpp | 241 | ||||
-rw-r--r-- | src/common/qmenumodel.h | 45 |
9 files changed, 889 insertions, 0 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt new file mode 100644 index 0000000..1428000 --- /dev/null +++ b/src/common/CMakeLists.txt @@ -0,0 +1,42 @@ +project(qmenumodelcommon) + +set(QMENUMODELCOMMON_SRC + qmenumodel.cpp + qdbusobject.cpp + qdbusmenumodel.cpp + qdbusactiongroup.cpp +) + +set(QMENUMODELCOMMON_HEADERS + qmenumodel.h + qdbusobject.h + qdbusmenumodel.h + qdbusactiongroup.h +) + +qt4_wrap_cpp(QMENUMODELCOMMON_MOC + ${QMENUMODELCOMMON_HEADERS} +) + +add_library(qmenumodelcommon STATIC + ${QMENUMODELCOMMON_SRC} + ${QMENUMODELCOMMON_MOC} +) + +set_target_properties(qmenumodelcommon PROPERTIES COMPILE_FLAGS -fPIC) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${QT_INCLUDE_DIR} + ${QT_QTCORE_INCLUDE_DIR} + ${QT_QTGUI_INCLUDE_DIR} + ${GLIB_INCLUDE_DIRS} + ${GIO_INCLUDE_DIRS} +) + +target_link_libraries(qmenumodelcommon + ${QT_QTCORE_LIBRARY} + ${QT_QTGUI_LIBRARY} + ${GLIB_LDFLAGS} + ${GIO_LDFLAGS} +) diff --git a/src/common/qdbusactiongroup.cpp b/src/common/qdbusactiongroup.cpp new file mode 100644 index 0000000..8475c29 --- /dev/null +++ b/src/common/qdbusactiongroup.cpp @@ -0,0 +1,193 @@ +#include "qdbusactiongroup.h" + +#include <QDebug> + +#include <gio/gio.h> + +QDBusActionGroup::QDBusActionGroup(QObject *parent) + :QObject(parent), + m_actionGroup(NULL) +{ +} + +QDBusActionGroup::~QDBusActionGroup() +{ + clear(); +} + +QAction *QDBusActionGroup::getAction(const QString &actionName) +{ + Q_FOREACH(QAction *act, m_actions) { + if (act->text() == actionName) { + return act; + } + } + + return NULL; +} + +void QDBusActionGroup::serviceVanish(GDBusConnection *) +{ + clear(); +} + +void QDBusActionGroup::serviceAppear(GDBusConnection *connection) +{ + GDBusActionGroup *ag = g_dbus_action_group_get(connection, + busName().toLatin1(), + objectPath().toLatin1()); + setActionGroup(ag); + if (ag == NULL) { + stop(); + } +} + +void QDBusActionGroup::start() +{ + QDBusObject::connect(); +} + +void QDBusActionGroup::stop() +{ + QDBusObject::disconnect(); +} + +void QDBusActionGroup::busTypeChanged(BusType) +{ + busTypeChanged(); +} + +void QDBusActionGroup::busNameChanged(const QString &) +{ + busNameChanged(); +} + +void QDBusActionGroup::objectPathChanged(const QString &objectPath) +{ + objectPathChanged(); +} + +void QDBusActionGroup::statusChanged(ConnectionStatus status) +{ + statusChanged(); +} + +void QDBusActionGroup::setIntBusType(int busType) +{ + if ((busType > None) && (busType < LastBusType)) { + setBusType(static_cast<BusType>(busType)); + } +} + +void QDBusActionGroup::setActionGroup(GDBusActionGroup *ag) +{ + if (m_actionGroup == reinterpret_cast<GActionGroup*>(ag)) { + return; + } + + if (m_actionGroup) { + g_signal_handler_disconnect(m_actionGroup, m_signalActionAddId); + g_signal_handler_disconnect(m_actionGroup, m_signalActionRemovedId); + m_signalActionAddId = m_signalActionRemovedId = 0; + g_object_unref(m_actionGroup); + } + + m_actionGroup = reinterpret_cast<GActionGroup*>(ag); + + if (m_actionGroup) { + + m_signalActionAddId = g_signal_connect(m_actionGroup, + "action-add", + G_CALLBACK(QDBusActionGroup::onActionAdded), + this); + + m_signalActionRemovedId = g_signal_connect(m_actionGroup, + "action-removed", + G_CALLBACK(QDBusActionGroup::onActionRemoved), + this); + + gchar **actionNames = g_action_group_list_actions(m_actionGroup); + for(int i=0; actionNames[i] != NULL; i++) { + addAction(actionNames[i]); + } + g_strfreev(actionNames); + } +} + +void QDBusActionGroup::addAction(const char *actionName) +{ + QAction *act = new QAction(actionName, this); + + act->setEnabled(g_action_group_get_action_enabled(m_actionGroup, actionName)); + + const GVariantType *stateType = g_action_group_get_action_state_type(m_actionGroup, actionName); + if (stateType == G_VARIANT_TYPE_BOOLEAN) { + act->setCheckable(true); + + GVariant *actState = g_action_group_get_action_state(m_actionGroup, actionName); + if (actState != NULL) { + act->setChecked(g_variant_get_boolean(actState)); + g_variant_unref(actState); + } + } + + // remove any older action with the same name + removeAction(actionName); + + m_actions.insert(act); +} + +void QDBusActionGroup::removeAction(const char *actionName) +{ + Q_FOREACH(QAction *act, m_actions) { + if (act->text() == actionName) { + m_actions.remove(act); + delete act; + break; + } + } +} + +void QDBusActionGroup::updateAction(const char *actionName, GVariant *state) +{ + QAction *action = getAction(actionName); + if ((action != NULL) && (state != NULL)) { + + const GVariantType *stateType = g_variant_get_type(state); + if (stateType == G_VARIANT_TYPE_BOOLEAN) { + action->setChecked(g_variant_get_boolean(state)); + } + } +} + +void QDBusActionGroup::clear() +{ + Q_FOREACH(QAction *act, m_actions) { + delete act; + } + m_actions.clear(); + + if (m_actionGroup != NULL) { + g_object_unref(m_actionGroup); + m_actionGroup = NULL; + } +} + +void QDBusActionGroup::onActionAdded(GDBusActionGroup *, gchar *actionName, gpointer data) +{ + QDBusActionGroup *self = reinterpret_cast<QDBusActionGroup*>(data); + self->addAction(actionName); +} + +void QDBusActionGroup::onActionRemoved(GDBusActionGroup *, gchar *actionName, gpointer data) +{ + QDBusActionGroup *self = reinterpret_cast<QDBusActionGroup*>(data); + self->removeAction(actionName); + +} + +void QDBusActionGroup::onActionStateChanged(GDBusActionGroup *ag, gchar *actionName, GVariant *value, gpointer data) +{ + QDBusActionGroup *self = reinterpret_cast<QDBusActionGroup*>(data); + self->updateAction(actionName, value); +} diff --git a/src/common/qdbusactiongroup.h b/src/common/qdbusactiongroup.h new file mode 100644 index 0000000..fe743b6 --- /dev/null +++ b/src/common/qdbusactiongroup.h @@ -0,0 +1,63 @@ +#ifndef QDBUSACTIONGROUP_H +#define QDBUSACTIONGROUP_H + +#include "qdbusobject.h" + +#include <QObject> +#include <QAction> +#include <QSet> + +class QDBusActionGroup : public QObject, public QDBusObject +{ + Q_OBJECT + Q_PROPERTY(int busType READ busType WRITE setIntBusType NOTIFY busTypeChanged) + Q_PROPERTY(QString busName READ busName WRITE setBusName NOTIFY busNameChanged) + Q_PROPERTY(QString objectPath READ objectPath WRITE setObjectPath NOTIFY objectPathChanged) + Q_PROPERTY(int status READ status NOTIFY statusChanged) + +public: + QDBusActionGroup(QObject *parent=0); + ~QDBusActionGroup(); + +Q_SIGNALS: + void busTypeChanged(); + void busNameChanged(); + void objectPathChanged(); + void statusChanged(); + +public Q_SLOTS: + void start(); + void stop(); + QAction *getAction(const QString &actionName); + +protected: + virtual void serviceAppear(GDBusConnection *connection); + virtual void serviceVanish(GDBusConnection *connection); + + virtual void busTypeChanged(BusType type); + virtual void busNameChanged(const QString &busNameChanged); + virtual void objectPathChanged(const QString &objectPath); + virtual void statusChanged(ConnectionStatus status); + +private: + GActionGroup *m_actionGroup; + QSet<QAction*> m_actions; + int m_signalActionAddId; + int m_signalActionRemovedId; + + // workaround to support int as bustType + void setIntBusType(int busType); + + void setActionGroup(GDBusActionGroup *ag); + void addAction(const char *actionName); + void removeAction(const char *actionName); + void updateAction(const char *actionName, GVariant *state); + void clear(); + + // glib slots + static void onActionAdded(GDBusActionGroup *ag, gchar *actionName, gpointer data); + static void onActionRemoved(GDBusActionGroup *ag, gchar *actionName, gpointer data); + static void onActionStateChanged(GDBusActionGroup *ag, gchar *actionName, GVariant *value, gpointer data); +}; + +#endif diff --git a/src/common/qdbusmenumodel.cpp b/src/common/qdbusmenumodel.cpp new file mode 100644 index 0000000..6e35c85 --- /dev/null +++ b/src/common/qdbusmenumodel.cpp @@ -0,0 +1,66 @@ +#include "qdbusmenumodel.h" +#include <QDebug> + +QDBusMenuModel::QDBusMenuModel(QObject *parent) + :QMenuModel(0, parent) +{ +} + +QDBusMenuModel::~QDBusMenuModel() +{ +} + +void QDBusMenuModel::start() +{ + QDBusObject::connect(); +} + +void QDBusMenuModel::stop() +{ + QDBusObject::disconnect(); +} + +void QDBusMenuModel::serviceVanish(GDBusConnection *) +{ + setMenuModel(NULL); +} + +void QDBusMenuModel::serviceAppear(GDBusConnection *connection) +{ + GMenuModel *model = reinterpret_cast<GMenuModel*>(g_dbus_menu_model_get(connection, + busName().toLatin1(), + objectPath().toLatin1())); + setMenuModel(model); + if (model == NULL) { + stop(); + } +} + +/* +void QDBusMenuModel::busTypeChanged(BusType) +{ + busTypeChanged(); +} + +void QDBusMenuModel::busNameChanged(const QString &) +{ + busNameChanged(); +} + +void QDBusMenuModel::objectPathChanged(const QString &objectPath) +{ + objectPathChanged(); +} + +void QDBusMenuModel::statusChanged(ConnectionStatus status) +{ + statusChanged(); +} +*/ + +void QDBusMenuModel::setIntBusType(int busType) +{ + if ((busType > None) && (busType < LastBusType)) { + setBusType(static_cast<BusType>(busType)); + } +} diff --git a/src/common/qdbusmenumodel.h b/src/common/qdbusmenumodel.h new file mode 100644 index 0000000..4fc439d --- /dev/null +++ b/src/common/qdbusmenumodel.h @@ -0,0 +1,47 @@ +#ifndef QDBUSMENUMODEL_H +#define QDBUSMENUMODEL_H + +#include "qdbusobject.h" +#include "qmenumodel.h" + +#include <gio/gio.h> + +class QDBusMenuModel : public QMenuModel, public QDBusObject +{ + Q_OBJECT + Q_PROPERTY(int busType READ busType WRITE setIntBusType NOTIFY busTypeChanged) + Q_PROPERTY(QString busName READ busName WRITE setBusName NOTIFY busNameChanged) + Q_PROPERTY(QString objectPath READ objectPath WRITE setObjectPath NOTIFY objectPathChanged) + Q_PROPERTY(int status READ status NOTIFY statusChanged) + +public: + QDBusMenuModel(QObject *parent=0); + ~QDBusMenuModel(); + +Q_SIGNALS: + void busTypeChanged(BusType type); + void busNameChanged(const QString &busNameChanged); + void objectPathChanged(const QString &objectPath); + void statusChanged(QDBusObject::ConnectionStatus status); + +public Q_SLOTS: + void start(); + void stop(); + +protected: + virtual void serviceAppear(GDBusConnection *connection); + virtual void serviceVanish(GDBusConnection *connection); + + /* + virtual void busTypeChanged(BusType type); + virtual void busNameChanged(const QString &busNameChanged); + virtual void objectPathChanged(const QString &objectPath); + virtual void statusChanged(ConnectionStatus status); + */ + +private: + // workaround to support int as bustType + void setIntBusType(int busType); +}; + +#endif diff --git a/src/common/qdbusobject.cpp b/src/common/qdbusobject.cpp new file mode 100644 index 0000000..6dec6d9 --- /dev/null +++ b/src/common/qdbusobject.cpp @@ -0,0 +1,127 @@ +#include "qdbusobject.h" + +#include <QDebug> + + + +QDBusObject::QDBusObject() + :m_watchId(0), + m_busType(None), + m_status(QDBusObject::Disconnected) +{ + qDebug() << "DBUS CREATED"; + qRegisterMetaType<QDBusObject::ConnectionStatus>("QDBusObject::ConnectionStatus"); +} + +QDBusObject::~QDBusObject() +{ + if (m_watchId != 0) { + g_bus_unwatch_name (m_watchId); + m_watchId = 0; + } +} + +QDBusObject::BusType QDBusObject::busType() const +{ + return m_busType; +} + +void QDBusObject::setBusType(QDBusObject::BusType type) +{ + if (m_busType != type) { + if (m_status != QDBusObject::Disconnected) + disconnect(); + m_busType = type; + busTypeChanged(m_busType); + } +} + +QString QDBusObject::busName() const +{ + return m_busName; +} + +void QDBusObject::setBusName(const QString &busName) +{ + if (m_busName != busName) { + if (m_status != QDBusObject::Disconnected) + disconnect(); + m_busName = busName; + busNameChanged(m_busName); + } +} + +QString QDBusObject::objectPath() const +{ + return m_objectPath; +} + +void QDBusObject::setObjectPath(const QString &objectPath) +{ + if (m_objectPath != objectPath) { + if (m_status != QDBusObject::Disconnected) + disconnect(); + m_objectPath = objectPath; + objectPathChanged(m_objectPath); + } +} + +void QDBusObject::setStatus(QDBusObject::ConnectionStatus status) +{ + if (m_status != status) { + m_status = status; + statusChanged(m_status); + } +} + +QDBusObject::ConnectionStatus QDBusObject::status() const +{ + return m_status; +} + +void QDBusObject::connect() +{ + if (m_status != QDBusObject::Disconnected) { + return; + } else if ((m_busType > None) && !m_objectPath.isEmpty() && !m_busName.isEmpty()) { + GBusType type = m_busType == SessionBus ? G_BUS_TYPE_SESSION : G_BUS_TYPE_SYSTEM; + m_watchId = g_bus_watch_name (type, + m_busName.toLatin1(), + G_BUS_NAME_WATCHER_FLAGS_NONE, + QDBusObject::onServiceAppeared, + QDBusObject::onServiceFanished, + this, + NULL); + + setStatus(QDBusObject::Connecting); + } else { + qWarning() << "Invalid dbus connection args"; + } +} + +void QDBusObject::disconnect() +{ + if (m_status != QDBusObject::Disconnected) { + g_bus_unwatch_name (m_watchId); + m_watchId = 0; + setStatus(QDBusObject::Disconnected); + } +} + +void QDBusObject::onServiceAppeared(GDBusConnection *connection, const gchar *, const gchar *, gpointer data) +{ + QDBusObject *self = reinterpret_cast<QDBusObject*>(data); + qDebug() << "service appear"; + + self->setStatus(QDBusObject::Connected); + self->serviceAppear(connection); +} + +void QDBusObject::onServiceFanished(GDBusConnection *connection, const gchar *, gpointer data) +{ + QDBusObject *self = reinterpret_cast<QDBusObject*>(data); + qDebug() << "service disappear"; + + self->setStatus(QDBusObject::Connecting); + self->serviceVanish(connection); +} diff --git a/src/common/qdbusobject.h b/src/common/qdbusobject.h new file mode 100644 index 0000000..a2dc91c --- /dev/null +++ b/src/common/qdbusobject.h @@ -0,0 +1,65 @@ +#ifndef QDBUSOBJECT_H +#define QDBUSOBJECT_H + +#include <QObject> + +#include <gio/gio.h> + +class QDBusObject +{ +public: + enum BusType { + None = 0, + SessionBus, + SystemBus, + LastBusType + }; + + enum ConnectionStatus { + Disconnected = 0, + Connecting, + Connected + }; + + QDBusObject(); + ~QDBusObject(); + + BusType busType() const; + void setBusType(BusType type); + + QString busName() const; + void setBusName(const QString &busName); + + QString objectPath() const; + void setObjectPath(const QString &busName); + + ConnectionStatus status() const; + + void connect(); + void disconnect(); + +protected: + virtual void serviceAppear(GDBusConnection *connection) = 0; + virtual void serviceVanish(GDBusConnection *connection) = 0; + + // notify functions + virtual void busTypeChanged(BusType type) = 0; + virtual void busNameChanged(const QString &busNameChanged) = 0; + virtual void objectPathChanged(const QString &objectPath) = 0; + virtual void statusChanged(ConnectionStatus status) = 0; + +private: + guint m_watchId; + BusType m_busType; + QString m_busName; + QString m_objectPath; + ConnectionStatus m_status; + + void setStatus(ConnectionStatus status); + + // glib slots + static void onServiceAppeared(GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer data); + static void onServiceFanished(GDBusConnection *connection, const gchar *name, gpointer data); +}; + +#endif diff --git a/src/common/qmenumodel.cpp b/src/common/qmenumodel.cpp new file mode 100644 index 0000000..6e7483c --- /dev/null +++ b/src/common/qmenumodel.cpp @@ -0,0 +1,241 @@ +#include "qmenumodel.h" + +#include <QDebug> + +QMenuModel::QMenuModel(GMenuModel *other, QObject *parent) + : QAbstractListModel(parent), + m_menuModel(0), + m_signalChangedId(0) +{ + static QHash<int, QByteArray> rolesNames; + if (rolesNames.empty()) { + rolesNames[Action] = "action"; + rolesNames[Label] = "label"; + rolesNames[LinkSection] = "linkSection"; + rolesNames[LinkSubMenu] = "linkSubMenu"; + rolesNames[Extra] = "extra"; + } + setRoleNames(rolesNames); + setMenuModel(other); +} + +QMenuModel::~QMenuModel() +{ + setMenuModel(NULL); +} + +void QMenuModel::setMenuModel(GMenuModel *other) +{ + if (m_menuModel == other) { + return; + } + + beginResetModel(); + + if (m_menuModel) { + g_signal_handler_disconnect(m_menuModel, m_signalChangedId); + m_signalChangedId = 0; + g_object_unref(m_menuModel); + } + + m_menuModel = other; + + if (m_menuModel) { + // this will trigger the menu load + (void) g_menu_model_get_n_items(m_menuModel); + //qDebug() << "Menu size:" << g_menu_model_get_n_items(m_menuModel); + m_signalChangedId = g_signal_connect(m_menuModel, + "items-changed", + G_CALLBACK(QMenuModel::onItemsChanged), + this); + } + + endResetModel(); +} + +GMenuModel *QMenuModel::menuModel() const +{ + return m_menuModel; +} + +/* QAbstractItemModel */ +int QMenuModel::columnCount(const QModelIndex &) const +{ + return 1; +} + +QVariant QMenuModel::data(const QModelIndex &index, int role) const +{ + QVariant attribute; + int rowCountValue = rowCount(); + + if ((rowCountValue > 0) && (index.row() >= 0) && (index.row() < rowCountValue)) { + if (m_menuModel) { + switch (role) { + case Action: + attribute = getStringAttribute(index, G_MENU_ATTRIBUTE_ACTION); + break; + case Label: + attribute = getStringAttribute(index, G_MENU_ATTRIBUTE_LABEL); + break; + case LinkSection: + attribute = getLink(index, G_MENU_LINK_SECTION); + break; + case LinkSubMenu: + attribute = getLink(index, G_MENU_LINK_SUBMENU); + break; + case Extra: + attribute = getExtraProperties(index); + break; + default: + break; + } + } + } + return attribute; +} + +QModelIndex QMenuModel::parent(const QModelIndex &index) const +{ + return QModelIndex(); +} + +int QMenuModel::rowCount(const QModelIndex &) const +{ + if (m_menuModel) { + return g_menu_model_get_n_items(m_menuModel); + } + return 0; +} + +QVariant QMenuModel::getStringAttribute(const QModelIndex &index, + const QString &attribute) const +{ + QVariant result; + gchar* value = NULL; + g_menu_model_get_item_attribute(m_menuModel, + index.row(), + attribute.toLatin1(), + "s", &value); + if (value) { + result = QVariant(QString::fromLatin1(value)); + g_free(value); + } + return result; +} + +QVariant QMenuModel::getLink(const QModelIndex &index, + const QString &linkName) const +{ + GMenuModel *link; + + link = g_menu_model_get_item_link(m_menuModel, + index.row(), + linkName.toLatin1()); + + if (link) { + QMenuModel *other = new QMenuModel(link, const_cast<QMenuModel*>(this)); + return QVariant::fromValue<QObject*>(other); + } + + return QVariant(); +} + +QVariant QMenuModel::getExtraProperties(const QModelIndex &index) const +{ + GMenuAttributeIter *iter = g_menu_model_iterate_item_attributes(m_menuModel, index.row()); + if (iter == NULL) { + return QVariant(); + } + + QObject *extra = new QObject(const_cast<QMenuModel*>(this)); + const gchar *attrName = NULL; + GVariant *value = NULL; + while (g_menu_attribute_iter_get_next (iter, &attrName, &value)) { + qDebug() << "Set property:" << attrName; + if (strncmp("x-", attrName, 2) == 0) { + extra->setProperty(attrName, parseGVariant(value)); + } + } + + return QVariant::fromValue<QObject*>(extra); +} + + +void QMenuModel::onItemsChanged(GMenuModel *, + gint position, + gint removed, + gint added, + gpointer data) +{ + QMenuModel *self = reinterpret_cast<QMenuModel*>(data); + //qDebug() << "Item Changed" << position << removed << added; + + if (removed > 0) { + self->beginRemoveRows(QModelIndex(), position, position + removed - 1); + self->endRemoveRows(); + } + + if (added > 0) { + self->beginInsertRows(QModelIndex(), position, position + added - 1); + self->endInsertRows(); + } +} + +QVariant QMenuModel::parseGVariant(GVariant *value) +{ + QVariant result; + if (value == NULL) { + return result; + } + + const GVariantType *type = g_variant_get_type(value); + if (g_variant_type_equal(type, G_VARIANT_TYPE_BOOLEAN)) { + result.setValue((bool)g_variant_get_boolean(value)); + } else if (g_variant_type_equal(type, G_VARIANT_TYPE_BYTE)) { + result.setValue(g_variant_get_byte(value)); + } else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT16)) { + result.setValue(g_variant_get_int16(value)); + } else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT16)) { + result.setValue(g_variant_get_uint16(value)); + } else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT32)) { + result.setValue(g_variant_get_int32(value)); + } else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT32)) { + result.setValue(g_variant_get_uint32(value)); + } else if (g_variant_type_equal(type, G_VARIANT_TYPE_INT64)) { + result.setValue(g_variant_get_int64(value)); + } else if (g_variant_type_equal(type, G_VARIANT_TYPE_UINT64)) { + result.setValue(g_variant_get_uint64(value)); + } else if (g_variant_type_equal(type, G_VARIANT_TYPE_DOUBLE)) { + result.setValue(g_variant_get_double(value)); + } else if (g_variant_type_equal(type, G_VARIANT_TYPE_STRING)) { + gsize size = 0; + const gchar *v = g_variant_get_string(value, &size); + result.setValue(QString::fromLatin1(v, size)); + } else { + qWarning() << "Unsupported GVariant value"; + } + + /* TODO: implement convertions to others types + * G_VARIANT_TYPE_HANDLE + * G_VARIANT_TYPE_OBJECT_PATH + * G_VARIANT_TYPE_SIGNATURE + * G_VARIANT_TYPE_VARIANT + * G_VARIANT_TYPE_ANY + * G_VARIANT_TYPE_BASIC + * G_VARIANT_TYPE_MAYBE + * G_VARIANT_TYPE_ARRAY + * G_VARIANT_TYPE_TUPLE + * 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 + * G_VARIANT_TYPE_VARDICT + */ + + return result; +} + diff --git a/src/common/qmenumodel.h b/src/common/qmenumodel.h new file mode 100644 index 0000000..f1e0b61 --- /dev/null +++ b/src/common/qmenumodel.h @@ -0,0 +1,45 @@ +#ifndef QMENUMODEL_H +#define QMENUMODEL_H + +#include <QAbstractListModel> +#include <gio/gio.h> + +class QMenuModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum MenuRoles { + Action = 0, + Label, + LinkSection, + LinkSubMenu, + Extra + }; + + ~QMenuModel(); + + /* QAbstractItemModel */ + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QModelIndex parent (const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + +protected: + QMenuModel(GMenuModel *other=0, QObject *parent=0); + void setMenuModel(GMenuModel *model); + GMenuModel *menuModel() const; + +private: + GMenuModel *m_menuModel; + guint m_signalChangedId; + + QVariant getStringAttribute(const QModelIndex &index, const QString &attribute) const; + QVariant getLink(const QModelIndex &index, const QString &linkName) const; + QVariant getExtraProperties(const QModelIndex &index) const; + + static void onItemsChanged(GMenuModel *model, gint position, gint removed, gint added, gpointer data); + static QVariant parseGVariant(GVariant *value); +}; + +#endif |