[gedit/wip/redesign2: 13/35] Add get_gear_menu to window and menu extension points



commit 33d9048d9f3f9eb78def9d249dfa4f377acc1e74
Author: Ignacio Casal Quinteiro <icq gnome org>
Date:   Wed Dec 25 20:43:02 2013 +0100

    Add get_gear_menu to window and menu extension points

 gedit/Makefile.am                       |    2 +
 gedit/gedit-menu-extension.c            |  200 +++++++++++++++++++++++++++++++
 gedit/gedit-menu-extension.h            |   65 ++++++++++
 gedit/gedit-window-activatable.c        |   38 ++++++
 gedit/gedit-window-activatable.h        |   13 ++
 gedit/gedit-window-private.h            |    1 +
 gedit/gedit-window.c                    |   17 +++
 gedit/gedit-window.h                    |    2 +
 gedit/gedit-window.ui                   |   30 ++++-
 plugins/quickopen/quickopen/__init__.py |   49 ++++----
 10 files changed, 387 insertions(+), 30 deletions(-)
---
diff --git a/gedit/Makefile.am b/gedit/Makefile.am
index e68240c..dbf8bd7 100644
--- a/gedit/Makefile.am
+++ b/gedit/Makefile.am
@@ -133,6 +133,7 @@ INST_H_FILES =                              \
        gedit-document.h                \
        gedit-encodings.h               \
        gedit-encodings-combo-box.h     \
+       gedit-menu-extension.h          \
        gedit-message-bus.h             \
        gedit-message.h                 \
        gedit-panel.h                   \
@@ -161,6 +162,7 @@ libgedit_private_la_SOURCES =               \
        gedit-app-activatable.c         \
        gedit-view-activatable.c        \
        gedit-window-activatable.c      \
+       gedit-menu-extension.c          \
        gedit-resources.c
 
 libgedit_c_files =                     \
diff --git a/gedit/gedit-menu-extension.c b/gedit/gedit-menu-extension.c
new file mode 100644
index 0000000..d7f1c5d
--- /dev/null
+++ b/gedit/gedit-menu-extension.c
@@ -0,0 +1,200 @@
+/*
+ * gedit-menu-extension.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "gedit-menu-extension.h"
+#include <string.h>
+
+static guint last_merge_id = 0;
+
+
+typedef struct _GeditMenuExtensionPrivate
+{
+       GMenu *menu;
+       guint merge_id;
+       gboolean dispose_has_run;
+} GeditMenuExtensionPrivate;
+
+enum
+{
+       PROP_0,
+       PROP_MENU
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GeditMenuExtension, gedit_menu_extension, G_TYPE_OBJECT)
+
+static void
+gedit_menu_extension_dispose (GObject *object)
+{
+       GeditMenuExtension *menu = GEDIT_MENU_EXTENSION (object);
+       GeditMenuExtensionPrivate *priv = gedit_menu_extension_get_instance_private (menu);
+
+       if (!priv->dispose_has_run)
+       {
+               gedit_menu_extension_remove_items (menu);
+               priv->dispose_has_run = TRUE;
+       }
+
+       g_clear_object (&priv->menu);
+
+       G_OBJECT_CLASS (gedit_menu_extension_parent_class)->dispose (object);
+}
+
+static void
+gedit_menu_extension_get_property (GObject    *object,
+                                   guint       prop_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+       GeditMenuExtension *menu = GEDIT_MENU_EXTENSION (object);
+       GeditMenuExtensionPrivate *priv = gedit_menu_extension_get_instance_private (menu);
+
+       switch (prop_id)
+       {
+               case PROP_MENU:
+                       g_value_set_object (value, priv->menu);
+                       break;
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                       break;
+       }
+}
+
+static void
+gedit_menu_extension_set_property (GObject     *object,
+                                   guint         prop_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+       GeditMenuExtension *menu = GEDIT_MENU_EXTENSION (object);
+       GeditMenuExtensionPrivate *priv = gedit_menu_extension_get_instance_private (menu);
+
+       switch (prop_id)
+       {
+               case PROP_MENU:
+                       priv->menu = g_value_dup_object (value);
+                       break;
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                       break;
+       }
+}
+
+static void
+gedit_menu_extension_class_init (GeditMenuExtensionClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->dispose = gedit_menu_extension_dispose;
+       object_class->get_property = gedit_menu_extension_get_property;
+       object_class->set_property = gedit_menu_extension_set_property;
+
+       g_object_class_install_property (object_class,
+                                        PROP_MENU,
+                                        g_param_spec_object ("menu",
+                                                             "Menu",
+                                                             "The main menu",
+                                                             G_TYPE_MENU,
+                                                             G_PARAM_READWRITE |
+                                                             G_PARAM_CONSTRUCT_ONLY |
+                                                             G_PARAM_STATIC_STRINGS));
+}
+
+static void
+gedit_menu_extension_init (GeditMenuExtension *menu)
+{
+       GeditMenuExtensionPrivate *priv;
+
+       priv = gedit_menu_extension_get_instance_private (menu);
+
+       priv->merge_id = ++last_merge_id;
+}
+
+GeditMenuExtension *
+_gedit_menu_extension_new (GMenu *menu)
+{
+       return g_object_new (GEDIT_TYPE_MENU, "menu", menu, NULL);
+}
+
+void
+gedit_menu_extension_append_menu_item (GeditMenuExtension *menu,
+                                       GMenuItem       *item)
+{
+       GeditMenuExtensionPrivate *priv;
+
+       g_return_if_fail (GEDIT_IS_MENU (menu));
+       g_return_if_fail (G_IS_MENU_ITEM (item));
+
+       priv = gedit_menu_extension_get_instance_private (menu);
+
+       if (priv->menu != NULL)
+       {
+               g_menu_item_set_attribute (item, "gedit-merge-id", "u", priv->merge_id);
+               g_menu_append_item (priv->menu, item);
+       }
+}
+
+void
+gedit_menu_extension_prepend_menu_item (GeditMenuExtension *menu,
+                                        GMenuItem       *item)
+{
+       GeditMenuExtensionPrivate *priv;
+
+       g_return_if_fail (GEDIT_IS_MENU (menu));
+       g_return_if_fail (G_IS_MENU_ITEM (item));
+
+       priv = gedit_menu_extension_get_instance_private (menu);
+
+       if (priv->menu != NULL)
+       {
+               g_menu_item_set_attribute (item, "gedit-merge-id", "u", priv->merge_id);
+               g_menu_prepend_item (priv->menu, item);
+       }
+}
+
+void
+gedit_menu_extension_remove_items (GeditMenuExtension *menu)
+{
+       GeditMenuExtensionPrivate *priv;
+       gint i, n_items;
+
+       priv = gedit_menu_extension_get_instance_private (menu);
+
+       n_items = g_menu_model_get_n_items (G_MENU_MODEL (priv->menu));
+       i = 0;
+       while (i < n_items)
+       {
+               guint id = 0;
+
+               if (g_menu_model_get_item_attribute (G_MENU_MODEL (priv->menu),
+                                                    i, "gedit-merge-id", "u", &id) &&
+                   id == priv->merge_id)
+               {
+                       g_menu_remove (priv->menu, i);
+                       n_items--;
+               }
+               else
+               {
+                       i++;
+               }
+       }
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-menu-extension.h b/gedit/gedit-menu-extension.h
new file mode 100644
index 0000000..039c965
--- /dev/null
+++ b/gedit/gedit-menu-extension.h
@@ -0,0 +1,65 @@
+/*
+ * gedit-menu-extension.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2014 - Ignacio Casal Quinteiro
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __GEDIT_MENU_EXTENSION_H__
+#define __GEDIT_MENU_EXTENSION_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_MENU                                (gedit_menu_extension_get_type ())
+#define GEDIT_MENU_EXTENSION(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MENU, 
GeditMenuExtension))
+#define GEDIT_MENU_EXTENSION_CONST(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MENU, 
GeditMenuExtension const))
+#define GEDIT_MENU_EXTENSION_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_MENU, 
GeditMenuExtensionClass))
+#define GEDIT_IS_MENU(obj)                     (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_MENU))
+#define GEDIT_IS_MENU_CLASS(klass)             (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_MENU))
+#define GEDIT_MENU_EXTENSION_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_MENU, 
GeditMenuExtensionClass))
+
+typedef struct _GeditMenuExtension      GeditMenuExtension;
+typedef struct _GeditMenuExtensionClass         GeditMenuExtensionClass;
+
+struct _GeditMenuExtension
+{
+       GObject parent;
+};
+
+struct _GeditMenuExtensionClass
+{
+       GObjectClass parent_class;
+};
+
+GType                     gedit_menu_extension_get_type            (void) G_GNUC_CONST;
+
+GeditMenuExtension      *_gedit_menu_extension_new                 (GMenu                *menu);
+
+void                      gedit_menu_extension_append_menu_item    (GeditMenuExtension   *menu,
+                                                                    GMenuItem            *item);
+
+void                      gedit_menu_extension_prepend_menu_item   (GeditMenuExtension   *menu,
+                                                                    GMenuItem            *item);
+
+void                      gedit_menu_extension_remove_items        (GeditMenuExtension   *menu);
+
+G_END_DECLS
+
+#endif /* __GEDIT_MENU_EXTENSION_H__ */
diff --git a/gedit/gedit-window-activatable.c b/gedit/gedit-window-activatable.c
index ce7ee41..416c401 100644
--- a/gedit/gedit-window-activatable.c
+++ b/gedit/gedit-window-activatable.c
@@ -25,6 +25,7 @@
 
 #include "gedit-window-activatable.h"
 #include "gedit-window.h"
+#include <string.h>
 
 /**
  * SECTION:gedit-window-activatable
@@ -124,3 +125,40 @@ gedit_window_activatable_update_state (GeditWindowActivatable *activatable)
        }
 }
 
+GeditMenuExtension *
+gedit_window_activatable_extend_gear_menu (GeditWindowActivatable *activatable,
+                                           const gchar            *extension_point)
+{
+       GeditMenuExtension *menu = NULL;
+       GeditWindow *window;
+       GMenuModel *model;
+       gint i, n_items;
+
+       g_return_val_if_fail (GEDIT_IS_WINDOW_ACTIVATABLE (activatable), NULL);
+       g_return_val_if_fail (extension_point != NULL, NULL);
+
+       g_object_get (G_OBJECT (activatable), "window", &window, NULL);
+       model = _gedit_window_get_gear_menu (window);
+       g_object_unref (window);
+
+       n_items = g_menu_model_get_n_items (model);
+
+       for (i = 0; i < n_items; i++)
+       {
+               gchar *id = NULL;
+
+               if (g_menu_model_get_item_attribute (model, i, "id", "s", &id) &&
+                   strcmp (id, extension_point) == 0)
+               {
+                       GMenuModel *section;
+
+                       section = g_menu_model_get_item_link (model, i, G_MENU_LINK_SECTION);
+                       menu = _gedit_menu_extension_new (G_MENU (section));
+               }
+
+               g_free (id);
+       }
+
+       return menu;
+}
+
diff --git a/gedit/gedit-window-activatable.h b/gedit/gedit-window-activatable.h
index b55509e..440a8c7 100644
--- a/gedit/gedit-window-activatable.h
+++ b/gedit/gedit-window-activatable.h
@@ -23,6 +23,7 @@
 #define __GEDIT_WINDOW_ACTIVATABLE_H__
 
 #include <glib-object.h>
+#include <gedit/gedit-menu-extension.h>
 
 G_BEGIN_DECLS
 
@@ -57,6 +58,18 @@ void  gedit_window_activatable_activate      (GeditWindowActivatable *activatable);
 void    gedit_window_activatable_deactivate    (GeditWindowActivatable *activatable);
 void    gedit_window_activatable_update_state  (GeditWindowActivatable *activatable);
 
+/**
+ * gedit_window_activatable_extend_gear_menu:
+ * @activatable: A #GeditWindowActivatable.
+ * @extension_point: the extension point section of the menu to get.
+ *
+ * Gets the #GeditMenuExtension for the gear menu @extension_point.
+ *
+ * Returns: (transfer full): a #GeditMenuExtension for the specific section or %NULL if not found.
+ */
+GeditMenuExtension *gedit_window_activatable_extend_gear_menu (GeditWindowActivatable *activatable,
+                                                                const gchar            *extension_point);
+
 G_END_DECLS
 
 #endif /* __GEDIT_WINDOW_ACTIVATABLE_H__ */
diff --git a/gedit/gedit-window-private.h b/gedit/gedit-window-private.h
index e61974b..a5229f7 100644
--- a/gedit/gedit-window-private.h
+++ b/gedit/gedit-window-private.h
@@ -92,6 +92,7 @@ struct _GeditWindowPrivate
        GtkWidget      *headerbar;
        GtkWidget      *open_button;
        GtkWidget      *open_menu;
+       GMenuModel     *gear_menu;
 
        /* recent files */
        guint           update_documents_list_menu_id;
diff --git a/gedit/gedit-window.c b/gedit/gedit-window.c
index 5704bb0..c683097 100644
--- a/gedit/gedit-window.c
+++ b/gedit/gedit-window.c
@@ -432,6 +432,7 @@ gedit_window_class_init (GeditWindowClass *klass)
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, side_headerbar);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, headerbar);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, open_menu);
+       gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, gear_menu);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, hpaned);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, side_panel);
        gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, vpaned);
@@ -4120,4 +4121,20 @@ gedit_window_get_message_bus (GeditWindow *window)
        return window->priv->message_bus;
 }
 
+/**
+ * _gedit_window_get_gear_menu:
+ * @window: a #GeditWindow.
+ *
+ * Gets the gear menu.
+ *
+ * Returns: (transfer none): the #GMenuModel of the gear menu button.
+ */
+GMenuModel *
+_gedit_window_get_gear_menu (GeditWindow *window)
+{
+       g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
+
+       return window->priv->gear_menu;
+}
+
 /* ex:set ts=8 noet: */
diff --git a/gedit/gedit-window.h b/gedit/gedit-window.h
index 9ed77dd..6dba3ef 100644
--- a/gedit/gedit-window.h
+++ b/gedit/gedit-window.h
@@ -150,6 +150,8 @@ GeditTab        *gedit_window_get_tab_from_location (GeditWindow         *window
 /* Message bus */
 GeditMessageBus        *gedit_window_get_message_bus           (GeditWindow         *window);
 
+GMenuModel       *_gedit_window_get_gear_menu           (GeditWindow         *window);
+
 /*
  * Non exported functions
  */
diff --git a/gedit/gedit-window.ui b/gedit/gedit-window.ui
index 6920356..8336d77 100644
--- a/gedit/gedit-window.ui
+++ b/gedit/gedit-window.ui
@@ -1,8 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.8 -->
-  <menu id="gear-menu">
+  <menu id="gear_menu">
     <section>
+      <attribute name="id">ext1</attribute>
+    </section>
+    <section>
+      <attribute name="id">ext2</attribute>
       <item>
         <attribute name="label" translatable="yes">_Save As…</attribute>
         <attribute name="action">win.save_as</attribute>
@@ -14,6 +18,10 @@
       </item>
     </section>
     <section>
+      <attribute name="id">ext3</attribute>
+    </section>
+    <section>
+      <attribute name="id">ext4</attribute>
       <item>
         <attribute name="label" translatable="yes">_Print…</attribute>
         <attribute name="action">win.print</attribute>
@@ -21,6 +29,10 @@
       </item>
     </section>
     <section>
+      <attribute name="id">ext5</attribute>
+    </section>
+    <section>
+      <attribute name="id">ext6</attribute>
       <item>
         <attribute name="label" translatable="yes">_Fullscreen</attribute>
         <attribute name="action">win.fullscreen</attribute>
@@ -28,6 +40,10 @@
       </item>
     </section>
     <section>
+      <attribute name="id">ext7</attribute>
+    </section>
+    <section>
+      <attribute name="id">ext8</attribute>
       <item>
         <attribute name="label" translatable="yes">_Find…</attribute>
         <attribute name="action">win.find</attribute>
@@ -50,12 +66,20 @@
       </item>
     </section>
     <section>
+      <attribute name="id">ext9</attribute>
+    </section>
+    <section>
+      <attribute name="id">ext10</attribute>
       <item>
         <attribute name="label" translatable="yes">_Highlight Mode…</attribute>
         <attribute name="action">win.highlight_mode</attribute>
       </item>
     </section>
     <section>
+      <attribute name="id">ext11</attribute>
+    </section>
+    <section>
+      <attribute name="id">ext12</attribute>
       <item>
         <attribute name="label" translatable="yes">_Close</attribute>
         <attribute name="action">win.close</attribute>
@@ -167,7 +191,7 @@
               <object class="GtkMenuButton" id="gear_button">
                 <property name="visible">True</property>
                 <property name="valign">center</property>
-                <property name="menu_model">gear-menu</property>
+                <property name="menu_model">gear_menu</property>
                 <style>
                   <class name="image-button"/>
                 </style>
@@ -367,7 +391,7 @@
           <object class="GtkMenuButton" id="fullscreen_gear_button">
             <property name="visible">True</property>
             <property name="valign">center</property>
-            <property name="menu_model">gear-menu</property>
+            <property name="menu_model">gear_menu</property>
             <style>
               <class name="image-button"/>
             </style>
diff --git a/plugins/quickopen/quickopen/__init__.py b/plugins/quickopen/quickopen/__init__.py
index 2ff4054..efab0d4 100644
--- a/plugins/quickopen/quickopen/__init__.py
+++ b/plugins/quickopen/quickopen/__init__.py
@@ -19,20 +19,21 @@
 
 from .popup import Popup
 import os
-from gi.repository import GObject, Gio, Gtk, Gedit
+from gi.repository import GObject, Gio, GLib, Gtk, Gedit
 from .virtualdirs import RecentDocumentsDirectory
 from .virtualdirs import CurrentDocumentsDirectory
 
-ui_str = """<ui>
-  <menubar name="MenuBar">
-    <menu name="FileMenu" action="File">
-      <placeholder name="FileOps_2">
-        <menuitem name="QuickOpen" action="QuickOpen"/>
-      </placeholder>
-    </menu>
-  </menubar>
-</ui>
-"""
+class QuickOpenAppActivatable(GObject.Object, Gedit.AppActivatable):
+    app = GObject.property(type=Gedit.App)
+
+    def __init__(self):
+        GObject.Object.__init__(self)
+
+    def do_activate(self):
+        self.app.add_accelerator("<Primary><Alt>O", "win.quickopen", None)
+
+    def do_deactivate(self):
+        self.app.remove_accelerator("win.quickopen", None)
 
 class QuickOpenPlugin(GObject.Object, Gedit.WindowActivatable):
     __gtype_name__ = "QuickOpenPlugin"
@@ -57,24 +58,18 @@ class QuickOpenPlugin(GObject.Object, Gedit.WindowActivatable):
         self._popup_size = size
 
     def _uninstall_menu(self):
-        manager = self.window.get_ui_manager()
-
-        manager.remove_ui(self._ui_id)
-        manager.remove_action_group(self._action_group)
-
-        manager.ensure_update()
+        self.window.remove_action("quickopen")
 
     def _install_menu(self):
-        manager = self.window.get_ui_manager()
-        self._action_group = Gtk.ActionGroup(name="GeditQuickOpenPluginActions")
-        self._action_group.add_actions([
-            ("QuickOpen", Gtk.STOCK_OPEN, _("Quick Open..."),
-             '<Primary><Alt>o', _("Quickly open documents"),
-             self.on_quick_open_activate)
-        ])
+        action = Gio.SimpleAction(name="quickopen")
+        action.connect('activate', self.on_quick_open_activate)
+        self.window.add_action(action)
+
+        item = Gio.MenuItem.new(_("Quick Open..."), "win.quickopen")
+        item.set_attribute_value("accel", GLib.Variant.new_string("<Primary><Alt>O"))
 
-        manager.insert_action_group(self._action_group)
-        self._ui_id = manager.add_ui_from_string(ui_str)
+        self.menu = self.extend_gear_menu("ext2")
+        self.menu.prepend_menu_item(item)
 
     def _create_popup(self):
         paths = []
@@ -174,7 +169,7 @@ class QuickOpenPlugin(GObject.Object, Gedit.WindowActivatable):
         return desktopdir
 
     # Callbacks
-    def on_quick_open_activate(self, action, user_data=None):
+    def on_quick_open_activate(self, action, parameter, user_data=None):
         if not self._popup:
             self._create_popup()
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]