aboutsummaryrefslogtreecommitdiff
path: root/libqmenumodel
diff options
context:
space:
mode:
Diffstat (limited to 'libqmenumodel')
-rw-r--r--libqmenumodel/QMenuModel/plugin.cpp2
-rw-r--r--libqmenumodel/src/CMakeLists.txt5
-rw-r--r--libqmenumodel/src/gtk/gtksimpleactionobserver.c160
-rw-r--r--libqmenumodel/src/gtk/gtksimpleactionobserver.h67
-rw-r--r--libqmenumodel/src/unitymenuaction.cpp149
-rw-r--r--libqmenumodel/src/unitymenuaction.h77
-rw-r--r--libqmenumodel/src/unitymenuactionevents.cpp46
-rw-r--r--libqmenumodel/src/unitymenuactionevents.h65
-rw-r--r--libqmenumodel/src/unitymenumodel.cpp175
-rw-r--r--libqmenumodel/src/unitymenumodel.h11
10 files changed, 756 insertions, 1 deletions
diff --git a/libqmenumodel/QMenuModel/plugin.cpp b/libqmenumodel/QMenuModel/plugin.cpp
index 21429ec..b7a4400 100644
--- a/libqmenumodel/QMenuModel/plugin.cpp
+++ b/libqmenumodel/QMenuModel/plugin.cpp
@@ -22,6 +22,7 @@
#include "qdbusmenumodel.h"
#include "qdbusactiongroup.h"
#include "qstateaction.h"
+#include "unitymenuaction.h"
#include "unitymenumodel.h"
#include <QtQml>
@@ -42,4 +43,5 @@ void QMenuModelQmlPlugin::registerTypes(const char *uri)
qmlRegisterType<QDBusMenuModel>(uri, 0, 1, "QDBusMenuModel");
qmlRegisterType<QDBusActionGroup>(uri, 0, 1, "QDBusActionGroup");
qmlRegisterType<UnityMenuModel>(uri, 0, 1, "UnityMenuModel");
+ qmlRegisterType<UnityMenuAction>(uri, 0, 1, "UnityMenuAction");
}
diff --git a/libqmenumodel/src/CMakeLists.txt b/libqmenumodel/src/CMakeLists.txt
index c86ccb4..e8eb4c0 100644
--- a/libqmenumodel/src/CMakeLists.txt
+++ b/libqmenumodel/src/CMakeLists.txt
@@ -11,6 +11,8 @@ set(QMENUMODEL_SRC
qdbusactiongroup.cpp
qmenumodelevents.cpp
qstateaction.cpp
+ unitymenuaction.cpp
+ unitymenuactionevents.cpp
unitymenumodel.cpp
unitymenumodelevents.cpp
gtk/gtkactionmuxer.c
@@ -19,6 +21,8 @@ set(QMENUMODEL_SRC
gtk/gtkactionobservable.h
gtk/gtkactionobserver.c
gtk/gtkactionobserver.h
+ gtk/gtksimpleactionobserver.c
+ gtk/gtksimpleactionobserver.h
gtk/gtkmenutracker.c
gtk/gtkmenutracker.h
gtk/gtkmenutrackeritem.c
@@ -58,6 +62,7 @@ set(QMENUMODEL_HEADERS
qdbusobject.h
qmenumodel.h
qstateaction.h
+ unitymenuaction.h
unitymenumodel.h
)
diff --git a/libqmenumodel/src/gtk/gtksimpleactionobserver.c b/libqmenumodel/src/gtk/gtksimpleactionobserver.c
new file mode 100644
index 0000000..054b82f
--- /dev/null
+++ b/libqmenumodel/src/gtk/gtksimpleactionobserver.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright © 2013 Canonical Limited
+ *
+ * This library 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; either version 2 of the
+ * licence or (at your option) any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Nick Dedekind <nick.dedekind@canonical.com
+ */
+
+#include "gtksimpleactionobserver.h"
+
+typedef GObjectClass GtkSimpleActionObserverClass;
+
+struct _GtkSimpleActionObserver
+{
+ GObject parent_instance;
+ GtkActionObservable *observable;
+ gchar* action_name;
+
+ GtkActionAddedFunc action_added;
+ GtkActionEnabledChangedFunc action_enabled_changed;
+ GtkActionStateChangedFunc action_state_changed;
+ GtkActionRemovedFunc action_removed;
+};
+
+static void gtk_simple_action_observer_init_observer_iface (GtkActionObserverInterface *iface);
+G_DEFINE_TYPE_WITH_CODE (GtkSimpleActionObserver, gtk_simple_action_observer, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTION_OBSERVER, gtk_simple_action_observer_init_observer_iface))
+
+static void
+gtk_simple_action_observer_finalize (GObject *object)
+{
+ GtkSimpleActionObserver *self = GTK_SIMPLE_ACTION_OBSERVER (object);
+
+ g_clear_object (&self->observable);
+
+ g_free(self->action_name);
+
+ G_OBJECT_CLASS (gtk_simple_action_observer_parent_class)->finalize (object);
+}
+
+static void
+gtk_simple_action_observer_init (GtkSimpleActionObserver * self)
+{
+}
+
+static void
+gtk_simple_action_observer_class_init (GtkSimpleActionObserverClass *class)
+{
+ class->finalize = gtk_simple_action_observer_finalize;
+}
+
+static void
+gtk_simple_action_observer_action_added (GtkActionObserver *observer,
+ GtkActionObservable *observable,
+ const gchar *action_name,
+ const GVariantType *parameter_type,
+ gboolean enabled,
+ GVariant *state)
+{
+ GtkSimpleActionObserver* self;
+ self = GTK_SIMPLE_ACTION_OBSERVER (observer);
+ self->action_added(self, action_name, enabled, state);
+}
+
+static void
+gtk_simple_action_observer_action_enabled_changed (GtkActionObserver *observer,
+ GtkActionObservable *observable,
+ const gchar *action_name,
+ gboolean enabled)
+{
+ GtkSimpleActionObserver* self;
+ self = GTK_SIMPLE_ACTION_OBSERVER (observer);
+ self->action_enabled_changed(self, action_name, enabled);
+}
+
+static void
+gtk_simple_action_observer_action_state_changed (GtkActionObserver *observer,
+ GtkActionObservable *observable,
+ const gchar *action_name,
+ GVariant *state)
+{
+ GtkSimpleActionObserver* self;
+ self = GTK_SIMPLE_ACTION_OBSERVER (observer);
+ self->action_state_changed(self, action_name, state);
+}
+
+static void
+gtk_simple_action_observer_action_removed (GtkActionObserver *observer,
+ GtkActionObservable *observable,
+ const gchar *action_name)
+{
+ GtkSimpleActionObserver* self;
+ self = GTK_SIMPLE_ACTION_OBSERVER (observer);
+ self->action_removed(self, action_name);
+}
+
+static void
+gtk_simple_action_observer_init_observer_iface (GtkActionObserverInterface *iface)
+{
+ iface->action_added = gtk_simple_action_observer_action_added;
+ iface->action_enabled_changed = gtk_simple_action_observer_action_enabled_changed;
+ iface->action_state_changed = gtk_simple_action_observer_action_state_changed;
+ iface->action_removed = gtk_simple_action_observer_action_removed;
+}
+
+GtkSimpleActionObserver*
+gtk_simple_action_observer_new (GtkActionObservable *observable,
+ GtkActionAddedFunc action_added,
+ GtkActionEnabledChangedFunc action_enabled_changed,
+ GtkActionStateChangedFunc action_state_changed,
+ GtkActionRemovedFunc action_removed)
+{
+ GtkSimpleActionObserver* self;
+ self = g_object_new (GTK_TYPE_SIMPLE_ACTION_OBSERVER, NULL);
+ self->observable = g_object_ref (observable);
+ self->action_name = NULL;
+
+ self->action_added = action_added;
+ self->action_enabled_changed = action_enabled_changed;
+ self->action_state_changed = action_state_changed;
+ self->action_removed = action_removed;
+
+ return self;
+}
+
+void
+gtk_simple_action_observer_register_action (GtkSimpleActionObserver *self,
+ const gchar *action_name)
+{
+ gtk_simple_action_observer_unregister_action(self);
+
+ if (action_name && g_strcmp0(action_name, "") != 0) {
+ self->action_name = g_strdup (action_name);
+
+ if (g_strcmp0(self->action_name, "") != 0) {
+ gtk_action_observable_register_observer (self->observable, self->action_name, GTK_ACTION_OBSERVER (self));
+ }
+ }
+}
+
+void
+gtk_simple_action_observer_unregister_action (GtkSimpleActionObserver *self)
+{
+ if (self->action_name) {
+ gtk_action_observable_unregister_observer(self->observable, self->action_name, GTK_ACTION_OBSERVER (self));
+ g_free(self->action_name);
+ self->action_name = NULL;
+ }
+}
diff --git a/libqmenumodel/src/gtk/gtksimpleactionobserver.h b/libqmenumodel/src/gtk/gtksimpleactionobserver.h
new file mode 100644
index 0000000..4276786
--- /dev/null
+++ b/libqmenumodel/src/gtk/gtksimpleactionobserver.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2013 Canonical Limited
+ *
+ * This library 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; either version 2 of the
+ * licence or (at your option) any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Nick Dedekind <nick.dedekind@canonical.com
+ */
+
+#ifndef __GTK_SIMPLE_ACTION_OBSERVER_H__
+#define __GTK_SIMPLE_ACTION_OBSERVER_H__
+
+#include "gtkactionobserver.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SIMPLE_ACTION_OBSERVER (gtk_simple_action_observer_get_type ())
+#define GTK_SIMPLE_ACTION_OBSERVER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
+ GTK_TYPE_SIMPLE_ACTION_OBSERVER, GtkSimpleActionObserver))
+#define GTK_IS_SIMPLE_ACTION_OBSERVER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
+ GTK_TYPE_SIMPLE_ACTION_OBSERVER))
+
+typedef struct _GtkSimpleActionObserver GtkSimpleActionObserver;
+
+typedef void (* GtkActionAddedFunc) (GtkSimpleActionObserver *observer_item,
+ const gchar *action_name,
+ gboolean enabled,
+ GVariant *state);
+
+typedef void (* GtkActionEnabledChangedFunc) (GtkSimpleActionObserver *observer_item,
+ const gchar *action_name,
+ gboolean enabled);
+
+typedef void (* GtkActionStateChangedFunc) (GtkSimpleActionObserver *observer_item,
+ const gchar *action_name,
+ GVariant *state);
+
+typedef void (* GtkActionRemovedFunc) (GtkSimpleActionObserver *observer_item,
+ const gchar *action_name);
+
+GType gtk_simple_action_observer_get_type (void) G_GNUC_CONST;
+
+GtkSimpleActionObserver* gtk_simple_action_observer_new (GtkActionObservable *observable,
+ GtkActionAddedFunc action_added,
+ GtkActionEnabledChangedFunc action_enabled_changed,
+ GtkActionStateChangedFunc action_state_changed,
+ GtkActionRemovedFunc action_removed);
+
+
+void gtk_simple_action_observer_register_action (GtkSimpleActionObserver *self,
+ const gchar *action_name);
+
+void gtk_simple_action_observer_unregister_action (GtkSimpleActionObserver *self);
+
+G_END_DECLS
+
+#endif // __GTK_SIMPLE_ACTION_OBSERVER_H__ \ No newline at end of file
diff --git a/libqmenumodel/src/unitymenuaction.cpp b/libqmenumodel/src/unitymenuaction.cpp
new file mode 100644
index 0000000..b41fd3e
--- /dev/null
+++ b/libqmenumodel/src/unitymenuaction.cpp
@@ -0,0 +1,149 @@
+/*
+ * 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: Nick Dedekind <nick.dedekind@canonical.com>
+ */
+
+#include "unitymenuaction.h"
+#include "unitymenumodel.h"
+#include "unitymenuactionevents.h"
+
+#include <QDebug>
+
+UnityMenuAction::UnityMenuAction(QObject* parent)
+ : QObject(parent),
+ m_valid(false),
+ m_enabled(false),
+ m_model(NULL)
+{
+}
+
+UnityMenuAction::~UnityMenuAction()
+{
+ if (m_model) {
+ m_model->unregisterAction(this);
+ }
+}
+
+QString UnityMenuAction::name() const
+{
+ return m_name;
+}
+
+void UnityMenuAction::setName(const QString& name)
+{
+ if (m_name != name) {
+ m_name = name;
+ Q_EMIT nameChanged(m_name);
+ }
+}
+
+UnityMenuModel* UnityMenuAction::model() const
+{
+ return m_model;
+}
+
+void UnityMenuAction::setModel(UnityMenuModel* model)
+{
+ if (m_model != model) {
+ if (!model) {
+ unregisterAction();
+ }
+ m_model = model;
+ registerAction();
+ Q_EMIT modelChanged(model);
+ }
+}
+
+QVariant UnityMenuAction::state() const
+{
+ return m_state;
+}
+
+void UnityMenuAction::setState(const QVariant& state)
+{
+ if (m_state != state) {
+ m_state = state;
+ Q_EMIT stateChanged(m_state);
+ }
+}
+
+bool UnityMenuAction::isEnabled() const
+{
+ return m_enabled;
+}
+
+void UnityMenuAction::setEnabled(bool enabled)
+{
+ if (m_enabled != enabled) {
+ m_enabled = enabled;
+ Q_EMIT enabledChanged(m_enabled);
+ }
+}
+
+bool UnityMenuAction::isValid() const
+{
+ return m_valid;
+}
+
+void UnityMenuAction::setValid(bool valid)
+{
+ if (m_valid != valid) {
+ m_valid = valid;
+ Q_EMIT validChanged(m_valid);
+ }
+}
+
+void UnityMenuAction::registerAction()
+{
+ if (m_model) {
+ m_model->registerAction(this);
+ }
+}
+
+void UnityMenuAction::unregisterAction()
+{
+ if (m_model) {
+ m_model->unregisterAction(this);
+ }
+}
+
+bool UnityMenuAction::event(QEvent* e)
+{
+ if (e->type() == UnityMenuActionAddEvent::eventType) {
+ UnityMenuActionAddEvent *umaae = static_cast<UnityMenuActionAddEvent*>(e);
+
+ setEnabled(umaae->enabled);
+ setState(umaae->state);
+ setValid(true);
+ return true;
+ } else if (e->type() == UnityMenuActionEnabledChangedEvent::eventType) {
+ UnityMenuActionEnabledChangedEvent *umaece = static_cast<UnityMenuActionEnabledChangedEvent*>(e);
+
+ setEnabled(umaece->enabled);
+ return true;
+ } else if (e->type() == UnityMenuActionStateChangeEvent::eventType) {
+ UnityMenuActionStateChangeEvent *umasce = static_cast<UnityMenuActionStateChangeEvent*>(e);
+
+ setState(umasce->state);
+ return true;
+ } else if (e->type() == UnityMenuActionRemoveEvent::eventType) {
+ UnityMenuActionRemoveEvent *umare = static_cast<UnityMenuActionRemoveEvent*>(e);
+
+ setValid(false);
+ return true;
+ }
+ return QObject::event(e);
+}
diff --git a/libqmenumodel/src/unitymenuaction.h b/libqmenumodel/src/unitymenuaction.h
new file mode 100644
index 0000000..b8391fe
--- /dev/null
+++ b/libqmenumodel/src/unitymenuaction.h
@@ -0,0 +1,77 @@
+/*
+ * 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: Nick Dedekind <nick.dedekind@canonical.com>
+ */
+
+#ifndef UNITYMENUACTION_H
+#define UNITYMENUACTION_H
+
+#include <QObject>
+#include <QVariant>
+class UnityMenuModel;
+
+class UnityMenuAction: public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(QVariant state READ state NOTIFY stateChanged)
+ Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(bool valid READ isValid NOTIFY validChanged)
+ Q_PROPERTY(UnityMenuModel* model READ model WRITE setModel NOTIFY modelChanged)
+public:
+ UnityMenuAction(QObject* parent = 0);
+ ~UnityMenuAction();
+
+ QString name() const;
+ void setName(const QString& str);
+
+ UnityMenuModel* model() const;
+ void setModel(UnityMenuModel* model);
+
+ QVariant state() const;
+ bool isEnabled() const;
+ bool isValid() const;
+
+Q_SIGNALS:
+ Q_INVOKABLE void activate(const QVariant& parameter = QVariant());
+ Q_INVOKABLE void changeState(const QVariant& parameter);
+
+ void nameChanged(const QString& name);
+ void modelChanged(UnityMenuModel* model);
+ void stateChanged(const QVariant& name);
+ void enabledChanged(bool enabled);
+ void validChanged(bool valid);
+
+protected:
+ virtual bool event(QEvent* e);
+
+ void setState(const QVariant& state);
+ void setEnabled(bool enabled);
+ void setValid(bool valid);
+
+private:
+ void unregisterAction();
+ void registerAction();
+
+ QString m_name;
+ QVariant m_state;
+ bool m_valid;
+ bool m_enabled;
+ UnityMenuModel* m_model;
+};
+
+#endif // UNITYMENUACTIONGROUP_H
diff --git a/libqmenumodel/src/unitymenuactionevents.cpp b/libqmenumodel/src/unitymenuactionevents.cpp
new file mode 100644
index 0000000..f05e536
--- /dev/null
+++ b/libqmenumodel/src/unitymenuactionevents.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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
+ */
+
+#include "unitymenuactionevents.h"
+
+const QEvent::Type UnityMenuActionAddEvent::eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
+const QEvent::Type UnityMenuActionRemoveEvent::eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
+const QEvent::Type UnityMenuActionEnabledChangedEvent::eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
+const QEvent::Type UnityMenuActionStateChangeEvent::eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
+
+UnityMenuActionAddEvent::UnityMenuActionAddEvent(bool _enabled, const QVariant& _state)
+ : QEvent(UnityMenuActionAddEvent::eventType),
+ enabled(_enabled),
+ state(_state)
+{}
+
+UnityMenuActionRemoveEvent::UnityMenuActionRemoveEvent()
+ : QEvent(UnityMenuActionRemoveEvent::eventType)
+{
+}
+
+UnityMenuActionEnabledChangedEvent::UnityMenuActionEnabledChangedEvent(bool _enabled)
+ : QEvent(UnityMenuActionEnabledChangedEvent::eventType),
+ enabled(_enabled)
+{}
+
+UnityMenuActionStateChangeEvent::UnityMenuActionStateChangeEvent(const QVariant& _state)
+ : QEvent(UnityMenuActionStateChangeEvent::eventType),
+ state(_state)
+{}
diff --git a/libqmenumodel/src/unitymenuactionevents.h b/libqmenumodel/src/unitymenuactionevents.h
new file mode 100644
index 0000000..44cb5de
--- /dev/null
+++ b/libqmenumodel/src/unitymenuactionevents.h
@@ -0,0 +1,65 @@
+/*
+ * 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 UNITYMENUACTIONEVENTS_H
+#define UNITYMENUACTIONEVENTS_H
+
+#include <QEvent>
+#include <QVariant>
+
+/* Event for a unitymenuaction add */
+class UnityMenuActionAddEvent : public QEvent
+{
+public:
+ static const QEvent::Type eventType;
+ UnityMenuActionAddEvent(bool enabled, const QVariant& state);
+
+ bool enabled;
+ QVariant state;
+};
+
+/* Event for a unitymenuaction remove */
+class UnityMenuActionRemoveEvent : public QEvent
+{
+public:
+ static const QEvent::Type eventType;
+ UnityMenuActionRemoveEvent();
+};
+
+/* Event for change in enabled value of a unitymenuaction */
+class UnityMenuActionEnabledChangedEvent : public QEvent
+{
+public:
+ static const QEvent::Type eventType;
+ UnityMenuActionEnabledChangedEvent(bool enabled);
+
+ int enabled;
+};
+
+/* Event for change in state value of a unitymenuaction */
+class UnityMenuActionStateChangeEvent : public QEvent
+{
+public:
+ static const QEvent::Type eventType;
+ UnityMenuActionStateChangeEvent(const QVariant& state);
+
+ QVariant state;
+};
+
+#endif //UNITYMENUACTIONEVENTS_H
diff --git a/libqmenumodel/src/unitymenumodel.cpp b/libqmenumodel/src/unitymenumodel.cpp
index 93d4f4c..d457cad 100644
--- a/libqmenumodel/src/unitymenumodel.cpp
+++ b/libqmenumodel/src/unitymenumodel.cpp
@@ -20,6 +20,8 @@
#include "converter.h"
#include "actionstateparser.h"
#include "unitymenumodelevents.h"
+#include "unitymenuaction.h"
+#include "unitymenuactionevents.h"
#include <QIcon>
#include <QQmlComponent>
@@ -28,11 +30,14 @@
extern "C" {
#include "gtk/gtkactionmuxer.h"
#include "gtk/gtkmenutracker.h"
+ #include "gtk/gtksimpleactionobserver.h"
}
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)
+G_DEFINE_QUARK (UNITY_MENU_ACTION, unity_menu_action)
+
enum MenuRoles {
LabelRole = Qt::DisplayRole + 1,
@@ -52,6 +57,7 @@ class UnityMenuModelPrivate
{
public:
UnityMenuModelPrivate(UnityMenuModel *model);
+ UnityMenuModelPrivate(const UnityMenuModelPrivate& other, UnityMenuModel *model);
~UnityMenuModelPrivate();
void clearItems(bool resetModel=true);
@@ -72,12 +78,21 @@ public:
QByteArray menuObjectPath;
QHash<QByteArray, int> roles;
ActionStateParser* actionStateParser;
+ QHash<UnityMenuAction*, GtkSimpleActionObserver*> registeredActions;
static void nameAppeared(GDBusConnection *connection, const gchar *name, const gchar *owner, gpointer user_data);
static void nameVanished(GDBusConnection *connection, const gchar *name, gpointer user_data);
static void menuItemInserted(GtkMenuTrackerItem *item, gint position, gpointer user_data);
static void menuItemRemoved(gint position, gpointer user_data);
static void menuItemChanged(GObject *object, GParamSpec *pspec, gpointer user_data);
+
+ static void registeredActionAdded(GtkSimpleActionObserver *observer_item,
+ const gchar *action_name,
+ gboolean enabled,
+ GVariant *state);
+ static void registeredActionEnabledChanged(GtkSimpleActionObserver *observer_item, const gchar *action_name, gboolean enabled);
+ static void registeredActionStateChanged(GtkSimpleActionObserver *observer_item, const gchar *action_name, GVariant *state);
+ static void registeredActionRemoved(GtkSimpleActionObserver *observer_item, const gchar *action_name);
};
void menu_item_free (gpointer data)
@@ -101,6 +116,19 @@ UnityMenuModelPrivate::UnityMenuModelPrivate(UnityMenuModel *model)
this->items = g_sequence_new (menu_item_free);
}
+UnityMenuModelPrivate::UnityMenuModelPrivate(const UnityMenuModelPrivate& other, UnityMenuModel *model)
+{
+ this->model = model;
+ this->menutracker = NULL;
+ this->connection = NULL;
+ this->nameWatchId = 0;
+ this->actionStateParser = new ActionStateParser(model);
+
+ this->muxer = GTK_ACTION_MUXER( g_object_ref(other.muxer));
+
+ this->items = g_sequence_new (menu_item_free);
+}
+
UnityMenuModelPrivate::~UnityMenuModelPrivate()
{
this->clearItems(false);
@@ -109,6 +137,12 @@ UnityMenuModelPrivate::~UnityMenuModelPrivate()
g_clear_object (&this->muxer);
g_clear_object (&this->connection);
+ QHash<UnityMenuAction*, GtkSimpleActionObserver*>::const_iterator it = this->registeredActions.constBegin();
+ for (; it != this->registeredActions.constEnd(); ++it) {
+ g_object_unref(it.value());
+ }
+ this->registeredActions.clear();
+
if (this->nameWatchId)
g_bus_unwatch_name (this->nameWatchId);
}
@@ -236,6 +270,12 @@ UnityMenuModel::UnityMenuModel(QObject *parent):
priv = new UnityMenuModelPrivate(this);
}
+UnityMenuModel::UnityMenuModel(const UnityMenuModelPrivate& other, QObject *parent):
+ QAbstractListModel(parent)
+{
+ priv = new UnityMenuModelPrivate(other, this);
+}
+
UnityMenuModel::~UnityMenuModel()
{
delete priv;
@@ -458,7 +498,7 @@ QObject * UnityMenuModel::submenu(int position, QQmlComponent* actionStateParser
model = (UnityMenuModel *) g_object_get_qdata (G_OBJECT (item), unity_submenu_model_quark ());
if (model == NULL) {
- model = new UnityMenuModel(this);
+ model = new UnityMenuModel(*priv, this);
if (actionStateParser) {
ActionStateParser* parser = qobject_cast<ActionStateParser*>(actionStateParser->create());
@@ -695,3 +735,136 @@ bool UnityMenuModel::event(QEvent* e)
}
return QAbstractListModel::event(e);
}
+
+void UnityMenuModel::registerAction(UnityMenuAction* action)
+{
+ if (!priv->registeredActions.contains(action)) {
+ GtkSimpleActionObserver* observer_item;
+ observer_item = gtk_simple_action_observer_new(GTK_ACTION_OBSERVABLE (priv->muxer),
+ UnityMenuModelPrivate::registeredActionAdded,
+ UnityMenuModelPrivate::registeredActionEnabledChanged,
+ UnityMenuModelPrivate::registeredActionStateChanged,
+ UnityMenuModelPrivate::registeredActionRemoved);
+
+ g_object_set_qdata (G_OBJECT (observer_item), unity_menu_action_quark (), action);
+
+ priv->registeredActions[action] = observer_item;
+
+ connect(action, SIGNAL(nameChanged(const QString&)), SLOT(onRegisteredActionNameChanged(const QString&)));
+ connect(action, SIGNAL(activate(const QVariant&)), SLOT(onRegisteredActionActivated(const QVariant&)));
+ connect(action, SIGNAL(changeState(const QVariant&)), SLOT(onRegisteredActionStateChanged(const QVariant&)));
+ }
+}
+
+void UnityMenuModel::unregisterAction(UnityMenuAction* action)
+{
+ if (priv->registeredActions.contains(action)) {
+ GtkSimpleActionObserver* observer_item;
+ observer_item = priv->registeredActions[action];
+ g_object_unref(observer_item);
+ priv->registeredActions.remove(action);
+
+ disconnect(action);
+ }
+}
+
+void UnityMenuModel::onRegisteredActionNameChanged(const QString& name)
+{
+ UnityMenuAction* action = qobject_cast<UnityMenuAction*>(sender());
+ if (!action || !priv->registeredActions.contains(action))
+ return;
+
+ GtkSimpleActionObserver* observer_item;
+ observer_item = priv->registeredActions[action];
+
+ QByteArray nameArray = name.toUtf8();
+ const gchar* action_name = nameArray.constData();
+
+ gtk_simple_action_observer_register_action (observer_item, action_name);
+
+ const GVariantType *parameter_type;
+ gboolean enabled;
+ GVariant *state;
+
+ if (g_action_group_query_action (G_ACTION_GROUP (priv->muxer), action_name,
+ &enabled, &parameter_type, NULL, NULL, &state))
+ {
+ UnityMenuActionAddEvent umaae(enabled, Converter::toQVariant(state));
+ QCoreApplication::sendEvent(action, &umaae);
+
+ if (state) {
+ g_variant_unref (state);
+ }
+ }
+}
+
+void UnityMenuModel::onRegisteredActionActivated(const QVariant& parameter)
+{
+ UnityMenuAction* action = qobject_cast<UnityMenuAction*>(sender());
+ if (!action || action->name().isEmpty())
+ return;
+
+ QByteArray nameArray = action->name().toUtf8();
+ const gchar* action_name = nameArray.constData();
+
+ g_action_group_activate_action (G_ACTION_GROUP (priv->muxer), action_name, Converter::toGVariant(parameter));
+}
+
+void UnityMenuModel::onRegisteredActionStateChanged(const QVariant& parameter)
+{
+ UnityMenuAction* action = qobject_cast<UnityMenuAction*>(sender());
+ if (!action || action->name().isEmpty())
+ return;
+
+ QByteArray nameArray = action->name().toUtf8();
+ const gchar* action_name = nameArray.constData();
+
+ g_action_group_change_action_state (G_ACTION_GROUP (priv->muxer), action_name, Converter::toGVariant(parameter));
+}
+
+void UnityMenuModelPrivate::registeredActionAdded(GtkSimpleActionObserver *observer_item,
+ const gchar *action_name,
+ gboolean enabled,
+ GVariant *state)
+{
+ UnityMenuAction *action;
+ action = (UnityMenuAction *) g_object_get_qdata (G_OBJECT (observer_item), unity_menu_action_quark ());
+
+ if (action) {
+ UnityMenuActionAddEvent umaae(enabled, Converter::toQVariant(state));
+ QCoreApplication::sendEvent(action, &umaae);
+ }
+}
+
+void UnityMenuModelPrivate::registeredActionEnabledChanged(GtkSimpleActionObserver *observer_item, const gchar *action_name, gboolean enabled)
+{
+ UnityMenuAction *action;
+ action = (UnityMenuAction *) g_object_get_qdata (G_OBJECT (observer_item), unity_menu_action_quark ());
+
+ if (action) {
+ UnityMenuActionEnabledChangedEvent umaece(enabled);
+ QCoreApplication::sendEvent(action, &umaece);
+ }
+}
+
+void UnityMenuModelPrivate::registeredActionStateChanged(GtkSimpleActionObserver *observer_item, const gchar *action_name, GVariant *state)
+{
+ UnityMenuAction *action;
+ action = (UnityMenuAction *) g_object_get_qdata (G_OBJECT (observer_item), unity_menu_action_quark ());
+
+ if (action) {
+ UnityMenuActionStateChangeEvent umasce(Converter::toQVariant(state));
+ QCoreApplication::sendEvent(action, &umasce);
+ }
+}
+
+void UnityMenuModelPrivate::registeredActionRemoved(GtkSimpleActionObserver *observer_item, const gchar *action_name)
+{
+ UnityMenuAction *action;
+ action = (UnityMenuAction *) g_object_get_qdata (G_OBJECT (observer_item), unity_menu_action_quark ());
+
+ if (action) {
+ UnityMenuActionRemoveEvent umare;
+ QCoreApplication::sendEvent(action, &umare);
+ }
+}
diff --git a/libqmenumodel/src/unitymenumodel.h b/libqmenumodel/src/unitymenumodel.h
index df35f08..a229f09 100644
--- a/libqmenumodel/src/unitymenumodel.h
+++ b/libqmenumodel/src/unitymenumodel.h
@@ -22,6 +22,7 @@
#include <QAbstractListModel>
class ActionStateParser;
class QQmlComponent;
+class UnityMenuAction;
class UnityMenuModel: public QAbstractListModel
{
@@ -61,18 +62,28 @@ public:
Q_INVOKABLE void activate(int index, const QVariant& parameter = QVariant());
Q_INVOKABLE void changeState(int index, const QVariant& parameter);
+ void registerAction(UnityMenuAction* action);
+ void unregisterAction(UnityMenuAction* action);
+
Q_SIGNALS:
void busNameChanged(const QByteArray &name);
void actionsChanged(const QByteArray &path);
void menuObjectPathChanged(const QByteArray &path);
void actionStateParserChanged(ActionStateParser* parser);
+protected Q_SLOTS:
+ void onRegisteredActionNameChanged(const QString& name);
+ void onRegisteredActionActivated(const QVariant& parameter);
+ void onRegisteredActionStateChanged(const QVariant& parameter);
+
protected:
virtual bool event(QEvent* e);
private:
class UnityMenuModelPrivate *priv;
friend class UnityMenuModelPrivate;
+
+ UnityMenuModel(const UnityMenuModelPrivate& other, QObject *parent);
};
#endif