diff options
-rw-r--r-- | libqmenumodel/QMenuModel/plugin.cpp | 2 | ||||
-rw-r--r-- | libqmenumodel/src/CMakeLists.txt | 5 | ||||
-rw-r--r-- | libqmenumodel/src/gtk/gtksimpleactionobserver.c | 160 | ||||
-rw-r--r-- | libqmenumodel/src/gtk/gtksimpleactionobserver.h | 67 | ||||
-rw-r--r-- | libqmenumodel/src/unitymenuaction.cpp | 149 | ||||
-rw-r--r-- | libqmenumodel/src/unitymenuaction.h | 77 | ||||
-rw-r--r-- | libqmenumodel/src/unitymenuactionevents.cpp | 46 | ||||
-rw-r--r-- | libqmenumodel/src/unitymenuactionevents.h | 65 | ||||
-rw-r--r-- | libqmenumodel/src/unitymenumodel.cpp | 175 | ||||
-rw-r--r-- | libqmenumodel/src/unitymenumodel.h | 11 |
10 files changed, 756 insertions, 1 deletions
diff --git a/libqmenumodel/QMenuModel/plugin.cpp b/libqmenumodel/QMenuModel/plugin.cpp index 0629099..117a37a 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 "unitythemediconprovider.h" @@ -44,4 +45,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 10f59c6..5d4a16a 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 unitythemediconprovider.cpp @@ -20,6 +22,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 @@ -59,6 +63,7 @@ set(QMENUMODEL_HEADERS qdbusobject.h qmenumodel.h qstateaction.h + unitymenuaction.h unitymenumodel.h unitythemediconprovider.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 3ea61ec..cc6d317 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; @@ -461,7 +501,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()); @@ -698,3 +738,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, ¶meter_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 |