[gedit/wip/appmenuext] Move menu extension to the app-activatable



commit 0ce7982b003085858a6587892d0f6ed37108d7e4
Author: Paolo Borelli <pborelli gnome org>
Date:   Tue Feb 4 15:30:05 2014 +0100

    Move menu extension to the app-activatable
    
    It is important that the menu-model for the gear menu is a single
    instance shared among all the windows. This makes it consistent
    with the app-menu model and plugins can extend them in the same
    way without causing items to be added multiple times when there
    is more than a window.
    The extension API is thus moved to the app activatable interface
    and the plugins are adapted to use the new api.

 docs/reference/gedit-sections.txt              |    1 +
 gedit/gedit-app-activatable.c                  |   18 ++
 gedit/gedit-app-activatable.h                  |   21 ++-
 gedit/gedit-app.c                              |  134 +++++++++++----
 gedit/gedit-app.h                              |    6 +-
 gedit/gedit-menu.ui                            |  218 ++++++++++++++++++++++++
 gedit/gedit-window-activatable.c               |   57 ------
 gedit/gedit-window-activatable.h               |   15 --
 gedit/gedit-window-private.h                   |    3 -
 gedit/gedit-window.c                           |   35 +----
 gedit/gedit-window.ui                          |  218 ------------------------
 plugins/docinfo/gedit-docinfo-plugin.c         |   84 +++++++--
 plugins/quickopen/quickopen/__init__.py        |   25 +--
 plugins/snippets/snippets/appactivatable.py    |   17 ++
 plugins/snippets/snippets/windowactivatable.py |   21 ---
 plugins/sort/gedit-sort-plugin.c               |   82 +++++++--
 plugins/spell/gedit-spell-app-activatable.c    |   25 +++-
 plugins/spell/gedit-spell-plugin.c             |   19 +--
 plugins/time/gedit-time-plugin.c               |   84 +++++++--
 19 files changed, 609 insertions(+), 474 deletions(-)
---
diff --git a/docs/reference/gedit-sections.txt b/docs/reference/gedit-sections.txt
index f3194fc..8938fa5 100644
--- a/docs/reference/gedit-sections.txt
+++ b/docs/reference/gedit-sections.txt
@@ -24,6 +24,7 @@ GEDIT_APP_GET_CLASS
 GeditAppActivatable
 gedit_app_activatable_activate
 gedit_app_activatable_deactivate
+gedit_app_activatable_extend_menu
 <SUBSECTION Standard>
 GEDIT_TYPE_APP_ACTIVATABLE
 GEDIT_APP_ACTIVATABLE
diff --git a/gedit/gedit-app-activatable.c b/gedit/gedit-app-activatable.c
index 54a9d39..d7e2e1b 100644
--- a/gedit/gedit-app-activatable.c
+++ b/gedit/gedit-app-activatable.c
@@ -105,3 +105,21 @@ gedit_app_activatable_deactivate (GeditAppActivatable *activatable)
                iface->deactivate (activatable);
        }
 }
+
+GeditMenuExtension *
+gedit_app_activatable_extend_menu (GeditAppActivatable *activatable,
+                                  const gchar *extension_point)
+{
+       GeditApp *app;
+       GeditMenuExtension *ext;
+
+       g_return_val_if_fail (GEDIT_IS_APP_ACTIVATABLE (activatable), NULL);
+
+       g_object_get (G_OBJECT (activatable), "app", &app, NULL);
+       ext = _gedit_app_extend_menu (app, extension_point);
+       g_object_unref (app);
+
+       return ext;
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-app-activatable.h b/gedit/gedit-app-activatable.h
index 018ed19..d39884f 100644
--- a/gedit/gedit-app-activatable.h
+++ b/gedit/gedit-app-activatable.h
@@ -23,6 +23,7 @@
 #define __GEDIT_APP_ACTIVATABLE_H__
 
 #include <glib-object.h>
+#include <gedit/gedit-menu-extension.h>
 
 G_BEGIN_DECLS
 
@@ -52,9 +53,25 @@ struct _GeditAppActivatableInterface
  */
 GType   gedit_app_activatable_get_type (void)  G_GNUC_CONST;
 
-void    gedit_app_activatable_activate (GeditAppActivatable *activatable);
-void    gedit_app_activatable_deactivate       (GeditAppActivatable *activatable);
+void    gedit_app_activatable_activate                 (GeditAppActivatable *activatable);
+void    gedit_app_activatable_deactivate               (GeditAppActivatable *activatable);
+
+/**
+ * gedit_app_activatable_extend_menu:
+ * @activatable: A #GeditAppActivatable.
+ * @extension_point: the extension point section of the menu to get.
+ *
+ * Gets the #GeditMenuExtension for the menu @extension_point. Note that
+ * the extension point could be in different menus (gear menu, app menu, etc)
+ * depending on the platform.
+ *
+ * Returns: (transfer full): a #GeditMenuExtension for the specific section
+ * or %NULL if not found.
+ */
+GeditMenuExtension     *gedit_app_activatable_extend_menu      (GeditAppActivatable *activatable,
+                                                                const gchar *extension_point);
 
 G_END_DECLS
 
 #endif /* __GEDIT_APP_ACTIVATABLE_H__ */
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-app.c b/gedit/gedit-app.c
index 2684bab..f9d10d5 100644
--- a/gedit/gedit-app.c
+++ b/gedit/gedit-app.c
@@ -86,6 +86,8 @@ struct _GeditAppPrivate
        GSettings         *ui_settings;
        GSettings         *window_settings;
 
+       GMenuModel        *window_menu;
+
        PeasExtensionSet  *extensions;
        GNetworkMonitor   *monitor;
 };
@@ -216,6 +218,8 @@ gedit_app_dispose (GObject *object)
 
        g_clear_object (&app->priv->engine);
 
+       g_clear_object (&app->priv->window_menu);
+
        G_OBJECT_CLASS (gedit_app_parent_class)->dispose (object);
 }
 
@@ -414,6 +418,27 @@ extension_removed (PeasExtensionSet *extensions,
        gedit_app_activatable_deactivate (GEDIT_APP_ACTIVATABLE (exten));
 }
 
+static gboolean
+gedit_app_has_app_menu (GeditApp *app)
+{
+       GtkSettings *gtk_settings;
+       gboolean show_app_menu;
+       gboolean show_menubar;
+
+       /* We have three cases:
+        * - GNOME 3: show-app-menu true, show-menubar false -> use the app menu
+        * - Unity, OSX: show-app-menu and show-menubar true -> use the normal menu
+        * - Other WM, Windows: show-app-menu and show-menubar false -> use the normal menu
+        */
+       gtk_settings = gtk_settings_get_default ();
+       g_object_get (G_OBJECT (gtk_settings),
+                     "gtk-shell-shows-app-menu", &show_app_menu,
+                     "gtk-shell-shows-menubar", &show_menubar,
+                     NULL);
+
+       return show_app_menu && !show_menubar;
+}
+
 static void
 gedit_app_startup (GApplication *application)
 {
@@ -428,6 +453,7 @@ gedit_app_startup (GApplication *application)
        GError *error = NULL;
        GFile *css_file;
        GtkCssProvider *provider;
+       GtkBuilder *builder;
 
        G_APPLICATION_CLASS (gedit_app_parent_class)->startup (application);
 
@@ -478,31 +504,35 @@ gedit_app_startup (GApplication *application)
                                         G_N_ELEMENTS (app_entries),
                                         app);
 
-       /* app menu */
-       if (_gedit_app_has_app_menu (app))
+       /* load menu model */
+       builder = gtk_builder_new ();
+       if (!gtk_builder_add_from_resource (builder,
+                                           "/org/gnome/gedit/ui/gedit-menu.ui",
+                                           &error))
+       {
+               g_warning ("loading menu builder file: %s", error->message);
+               g_error_free (error);
+       }
+       else
        {
-               GtkBuilder *builder;
 
-               builder = gtk_builder_new ();
-               if (!gtk_builder_add_from_resource (builder,
-                                                   "/org/gnome/gedit/ui/gedit-menu.ui",
-                                                   &error))
+               if (gedit_app_has_app_menu (app))
                {
-                       g_warning ("loading menu builder file: %s", error->message);
-                       g_error_free (error);
+                       GMenuModel *appmenu;
+
+                       appmenu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu"));
+                       gtk_application_set_app_menu (GTK_APPLICATION (application), appmenu);
+
+                       app->priv->window_menu = G_MENU_MODEL (gtk_builder_get_object (builder, 
"gear_menu_withappmenu"));
                }
                else
                {
-                       GMenuModel *app_menu;
-
-                       app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu"));
-                       gtk_application_set_app_menu (GTK_APPLICATION (application),
-                                                     app_menu);
+                       app->priv->window_menu = G_MENU_MODEL (gtk_builder_get_object (builder, 
"gear_menu_noappmenu"));
                }
-
-               g_object_unref (builder);
        }
 
+       g_object_unref (builder);
+
        /* Accelerators */
        gtk_application_add_accelerator (GTK_APPLICATION (application),
                                         "<Primary>Q", "app.quit", NULL);
@@ -1570,6 +1600,32 @@ gedit_app_process_window_event (GeditApp    *app,
     return FALSE;
 }
 
+
+static GMenuModel *
+find_extension_point_section (GMenuModel  *model,
+                              const gchar *extension_point)
+{
+       gint i, n_items;
+       GMenuModel *section = NULL;
+
+       n_items = g_menu_model_get_n_items (model);
+
+       for (i = 0; i < n_items && !section; i++)
+       {
+               gchar *id = NULL;
+
+               if (g_menu_model_get_item_attribute (model, i, "id", "s", &id) &&
+                   strcmp (id, extension_point) == 0)
+               {
+                       section = g_menu_model_get_item_link (model, i, G_MENU_LINK_SECTION);
+               }
+
+               g_free (id);
+       }
+
+       return section;
+}
+
 static void
 app_lockdown_changed (GeditApp *app)
 {
@@ -1669,27 +1725,39 @@ _gedit_app_get_settings (GeditApp *app)
        return app->priv->settings;
 }
 
-gboolean
-_gedit_app_has_app_menu (GeditApp *app)
+GMenuModel *
+_gedit_app_get_window_menu (GeditApp *app)
 {
-       GtkSettings *gtk_settings;
-       gboolean show_app_menu;
-       gboolean show_menubar;
+       g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
 
-       g_return_val_if_fail (GEDIT_IS_APP (app), FALSE);
+       return app->priv->window_menu;
+}
 
-       /* We have three cases:
-        * - GNOME 3: show-app-menu true, show-menubar false -> use the app menu
-        * - Unity, OSX: show-app-menu and show-menubar true -> use the normal menu
-        * - Other WM, Windows: show-app-menu and show-menubar false -> use the normal menu
-        */
-       gtk_settings = gtk_settings_get_default ();
-       g_object_get (G_OBJECT (gtk_settings),
-                     "gtk-shell-shows-app-menu", &show_app_menu,
-                     "gtk-shell-shows-menubar", &show_menubar,
-                     NULL);
+GeditMenuExtension *
+_gedit_app_extend_menu (GeditApp    *app,
+                       const gchar *extension_point)
+{
+       GMenuModel *model;
+       GMenuModel *section;
 
-       return show_app_menu && !show_menubar;
+       g_return_val_if_fail (GEDIT_IS_APP (app), NULL);
+       g_return_val_if_fail (extension_point != NULL, NULL);
+
+       /* First look in the window menu */
+       section = find_extension_point_section (app->priv->window_menu, extension_point);
+
+       /* otherwise look in the app menu */
+       if (section == NULL)
+       {
+               model = gtk_application_get_app_menu (GTK_APPLICATION (app));
+
+               if (model != NULL)
+               {
+                       section = find_extension_point_section (model, extension_point);
+               }
+       }
+
+       return section != NULL ? _gedit_menu_extension_new (G_MENU (section)) : NULL;
 }
 
 /* ex:set ts=8 noet: */
diff --git a/gedit/gedit-app.h b/gedit/gedit-app.h
index 5a8cbc9..939bfee 100644
--- a/gedit/gedit-app.h
+++ b/gedit/gedit-app.h
@@ -32,6 +32,7 @@
 #include <gtk/gtk.h>
 
 #include <gedit/gedit-window.h>
+#include <gedit/gedit-menu-extension.h>
 
 G_BEGIN_DECLS
 
@@ -142,7 +143,10 @@ void                        _gedit_app_set_default_print_settings  (GeditApp         
*app,
 
 GObject                        *_gedit_app_get_settings                (GeditApp  *app);
 
-gboolean                _gedit_app_has_app_menu                (GeditApp  *app);
+GMenuModel             *_gedit_app_get_window_menu             (GeditApp  *app);
+
+GeditMenuExtension     *_gedit_app_extend_menu                 (GeditApp    *app,
+                                                                const gchar *extension_point);
 
 G_END_DECLS
 
diff --git a/gedit/gedit-menu.ui b/gedit/gedit-menu.ui
index 9c7288a..2e0901e 100644
--- a/gedit/gedit-menu.ui
+++ b/gedit/gedit-menu.ui
@@ -32,4 +32,222 @@
       </item>
     </section>
   </menu>
+  <menu id="gear_menu_withappmenu">
+    <section>
+      <attribute name="id">ext1</attribute>
+    </section>
+    <section>
+      <attribute name="id">ext2</attribute>
+      <item>
+        <attribute name="label" translatable="yes">_Reload</attribute>
+        <attribute name="action">win.revert</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Save As…</attribute>
+        <attribute name="action">win.save-as</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">Save _All</attribute>
+        <attribute name="action">win.save-all</attribute>
+      </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>
+      </item>
+    </section>
+    <section>
+      <attribute name="id">ext5</attribute>
+    </section>
+    <section>
+      <attribute name="id">ext6</attribute>
+      <item>
+        <attribute name="label" translatable="yes">Side _Panel</attribute>
+        <attribute name="action">win.side-panel</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Bottom Panel</attribute>
+        <attribute name="action">win.bottom-panel</attribute>
+        <attribute name="hidden-when">action-disabled</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Fullscreen</attribute>
+        <attribute name="action">win.fullscreen</attribute>
+      </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>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Find and Replace…</attribute>
+        <attribute name="action">win.replace</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Clear Highlight</attribute>
+        <attribute name="action">win.clear-highlight</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Go to Line…</attribute>
+        <attribute name="action">win.goto-line</attribute>
+      </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>
+    </section>
+    <section>
+      <attribute name="id">ext13</attribute>
+      <item>
+        <attribute name="label" translatable="yes">_Close All</attribute>
+        <attribute name="action">win.close-all</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Close</attribute>
+        <attribute name="action">win.close</attribute>
+      </item>
+    </section>
+  </menu>
+  <menu id="gear_menu_noappmenu">
+    <section>
+      <attribute name="id">ext1</attribute>
+    </section>
+    <section>
+      <attribute name="id">ext2</attribute>
+      <item>
+        <attribute name="label" translatable="yes">_Reload</attribute>
+        <attribute name="action">win.revert</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Save As…</attribute>
+        <attribute name="action">win.save-as</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">Save _All</attribute>
+        <attribute name="action">win.save-all</attribute>
+      </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>
+      </item>
+    </section>
+    <section>
+      <attribute name="id">ext5</attribute>
+    </section>
+    <section>
+      <attribute name="id">ext6</attribute>
+      <item>
+        <attribute name="label" translatable="yes">Side _Panel</attribute>
+        <attribute name="action">win.side-panel</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Bottom Panel</attribute>
+        <attribute name="action">win.bottom-panel</attribute>
+        <attribute name="hidden-when">action-disabled</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Fullscreen</attribute>
+        <attribute name="action">win.fullscreen</attribute>
+      </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>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Find and Replace…</attribute>
+        <attribute name="action">win.replace</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Clear Highlight</attribute>
+        <attribute name="action">win.clear-highlight</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Go to Line…</attribute>
+        <attribute name="action">win.goto-line</attribute>
+      </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>
+    </section>
+    <section>
+      <attribute name="id">appmenuext2</attribute>
+      <item>
+        <attribute name="label" translatable="yes">_Preferences</attribute>
+        <attribute name="action">app.preferences</attribute>
+      </item>
+    </section>
+    <section>
+      <attribute name="id">appmenuext3</attribute>
+      <item>
+        <attribute name="label" translatable="yes">_Help</attribute>
+        <attribute name="action">app.help</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_About</attribute>
+        <attribute name="action">app.about</attribute>
+      </item>
+    </section>
+    <section>
+      <attribute name="id">ext13</attribute>
+      <item>
+        <attribute name="label" translatable="yes">_Close All</attribute>
+        <attribute name="action">win.close-all</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Close</attribute>
+        <attribute name="action">win.close</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Quit</attribute>
+        <attribute name="action">app.quit</attribute>
+      </item>
+    </section>
+  </menu>
 </interface>
diff --git a/gedit/gedit-window-activatable.c b/gedit/gedit-window-activatable.c
index 4fb483d..0f2c7e3 100644
--- a/gedit/gedit-window-activatable.c
+++ b/gedit/gedit-window-activatable.c
@@ -124,61 +124,4 @@ gedit_window_activatable_update_state (GeditWindowActivatable *activatable)
        }
 }
 
-static GMenuModel *
-find_extension_point_section (GMenuModel  *model,
-                              const gchar *extension_point)
-{
-       gint i, n_items;
-       GMenuModel *section = NULL;
-
-       n_items = g_menu_model_get_n_items (model);
-
-       for (i = 0; i < n_items && !section; i++)
-       {
-               gchar *id = NULL;
-
-               if (g_menu_model_get_item_attribute (model, i, "id", "s", &id) &&
-                   strcmp (id, extension_point) == 0)
-               {
-                       section = g_menu_model_get_item_link (model, i, G_MENU_LINK_SECTION);
-               }
-
-               g_free (id);
-       }
-
-       return section;
-}
-
-GeditMenuExtension *
-gedit_window_activatable_extend_menu (GeditWindowActivatable *activatable,
-                                      const gchar            *extension_point)
-{
-       GeditWindow *window;
-       GMenuModel *model;
-       GMenuModel *section;
-
-       g_return_val_if_fail (GEDIT_IS_WINDOW_ACTIVATABLE (activatable), NULL);
-       g_return_val_if_fail (extension_point != NULL, NULL);
-
-       /* First look in the gear menu */
-       g_object_get (G_OBJECT (activatable), "window", &window, NULL);
-       model = _gedit_window_get_gear_menu (window);
-       g_object_unref (window);
-
-       section = find_extension_point_section (model, extension_point);
-
-       /* otherwise look in the app menu */
-       if (section == NULL)
-       {
-               model = gtk_application_get_app_menu (GTK_APPLICATION (g_application_get_default ()));
-
-               if (model != NULL)
-               {
-                       section = find_extension_point_section (model, extension_point);
-               }
-       }
-
-       return section != NULL ? _gedit_menu_extension_new (G_MENU (section)) : NULL;
-}
-
 /* ex:set ts=8 noet: */
diff --git a/gedit/gedit-window-activatable.h b/gedit/gedit-window-activatable.h
index 3e13b66..9b3c532 100644
--- a/gedit/gedit-window-activatable.h
+++ b/gedit/gedit-window-activatable.h
@@ -22,7 +22,6 @@
 #define __GEDIT_WINDOW_ACTIVATABLE_H__
 
 #include <glib-object.h>
-#include <gedit/gedit-menu-extension.h>
 
 G_BEGIN_DECLS
 
@@ -57,20 +56,6 @@ 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_menu:
- * @activatable: A #GeditWindowActivatable.
- * @extension_point: the extension point section of the menu to get.
- *
- * Gets the #GeditMenuExtension for the menu @extension_point. Note that
- * the extension point could be in different menus (gear menu, app menu, etc)
- * depending on the platform.
- *
- * Returns: (transfer full): a #GeditMenuExtension for the specific section or %NULL if not found.
- */
-GeditMenuExtension *gedit_window_activatable_extend_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 9e07e89..93df749 100644
--- a/gedit/gedit-window-private.h
+++ b/gedit/gedit-window-private.h
@@ -90,9 +90,6 @@ struct _GeditWindowPrivate
        GtkWidget      *open_button;
        GtkWidget      *open_menu;
        GtkMenuButton  *gear_button;
-       GMenuModel     *gear_menu;
-       GMenuModel     *gear_menu_win;
-       GMenuModel     *gear_menu_app;
 
        /* recent files */
 
diff --git a/gedit/gedit-window.c b/gedit/gedit-window.c
index c21f593..7507158 100644
--- a/gedit/gedit-window.c
+++ b/gedit/gedit-window.c
@@ -425,8 +425,6 @@ gedit_window_class_init (GeditWindowClass *klass)
        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_button);
-       gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, gear_menu_win);
-       gtk_widget_class_bind_template_child_private (widget_class, GeditWindow, gear_menu_app);
        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);
@@ -2953,6 +2951,7 @@ static void
 gedit_window_init (GeditWindow *window)
 {
        GtkTargetList *tl;
+       GMenuModel *gear_menu;
 
        gedit_debug (DEBUG_WINDOW);
 
@@ -2998,19 +2997,9 @@ gedit_window_init (GeditWindow *window)
 
        setup_headerbar_open_button (window);
 
-       if (_gedit_app_has_app_menu (GEDIT_APP (g_application_get_default ())))
-       {
-               window->priv->gear_menu = window->priv->gear_menu_win;
-       }
-       else
-       {
-               window->priv->gear_menu = window->priv->gear_menu_app;
-       }
-
-       gtk_menu_button_set_menu_model (window->priv->gear_button,
-                                       window->priv->gear_menu);
-       gtk_menu_button_set_menu_model (window->priv->fullscreen_gear_button,
-                                       window->priv->gear_menu);
+       gear_menu = _gedit_app_get_window_menu (GEDIT_APP (g_application_get_default ())),
+       gtk_menu_button_set_menu_model (window->priv->gear_button, gear_menu);
+       gtk_menu_button_set_menu_model (window->priv->fullscreen_gear_button, gear_menu);
 
        /* Setup status bar */
        setup_statusbar (window);
@@ -3840,20 +3829,4 @@ 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.ui b/gedit/gedit-window.ui
index 50bc38f..09ddc83 100644
--- a/gedit/gedit-window.ui
+++ b/gedit/gedit-window.ui
@@ -1,224 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.8 -->
-  <menu id="gear_menu_win">
-    <section>
-      <attribute name="id">ext1</attribute>
-    </section>
-    <section>
-      <attribute name="id">ext2</attribute>
-      <item>
-        <attribute name="label" translatable="yes">_Reload</attribute>
-        <attribute name="action">win.revert</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Save As…</attribute>
-        <attribute name="action">win.save-as</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">Save _All</attribute>
-        <attribute name="action">win.save-all</attribute>
-      </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>
-      </item>
-    </section>
-    <section>
-      <attribute name="id">ext5</attribute>
-    </section>
-    <section>
-      <attribute name="id">ext6</attribute>
-      <item>
-        <attribute name="label" translatable="yes">Side _Panel</attribute>
-        <attribute name="action">win.side-panel</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Bottom Panel</attribute>
-        <attribute name="action">win.bottom-panel</attribute>
-        <attribute name="hidden-when">action-disabled</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Fullscreen</attribute>
-        <attribute name="action">win.fullscreen</attribute>
-      </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>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Find and Replace…</attribute>
-        <attribute name="action">win.replace</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Clear Highlight</attribute>
-        <attribute name="action">win.clear-highlight</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Go to Line…</attribute>
-        <attribute name="action">win.goto-line</attribute>
-      </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>
-    </section>
-    <section>
-      <attribute name="id">ext13</attribute>
-      <item>
-        <attribute name="label" translatable="yes">_Close All</attribute>
-        <attribute name="action">win.close-all</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Close</attribute>
-        <attribute name="action">win.close</attribute>
-      </item>
-    </section>
-  </menu>
-  <menu id="gear_menu_app">
-    <section>
-      <attribute name="id">ext1</attribute>
-    </section>
-    <section>
-      <attribute name="id">ext2</attribute>
-      <item>
-        <attribute name="label" translatable="yes">_Reload</attribute>
-        <attribute name="action">win.revert</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Save As…</attribute>
-        <attribute name="action">win.save-as</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">Save _All</attribute>
-        <attribute name="action">win.save-all</attribute>
-      </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>
-      </item>
-    </section>
-    <section>
-      <attribute name="id">ext5</attribute>
-    </section>
-    <section>
-      <attribute name="id">ext6</attribute>
-      <item>
-        <attribute name="label" translatable="yes">Side _Panel</attribute>
-        <attribute name="action">win.side-panel</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Bottom Panel</attribute>
-        <attribute name="action">win.bottom-panel</attribute>
-        <attribute name="hidden-when">action-disabled</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Fullscreen</attribute>
-        <attribute name="action">win.fullscreen</attribute>
-      </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>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Find and Replace…</attribute>
-        <attribute name="action">win.replace</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Clear Highlight</attribute>
-        <attribute name="action">win.clear-highlight</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Go to Line…</attribute>
-        <attribute name="action">win.goto-line</attribute>
-      </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>
-    </section>
-    <section>
-      <attribute name="id">appmenuext2</attribute>
-      <item>
-        <attribute name="label" translatable="yes">_Preferences</attribute>
-        <attribute name="action">app.preferences</attribute>
-      </item>
-    </section>
-    <section>
-      <attribute name="id">appmenuext3</attribute>
-      <item>
-        <attribute name="label" translatable="yes">_Help</attribute>
-        <attribute name="action">app.help</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_About</attribute>
-        <attribute name="action">app.about</attribute>
-      </item>
-    </section>
-    <section>
-      <attribute name="id">ext13</attribute>
-      <item>
-        <attribute name="label" translatable="yes">_Close All</attribute>
-        <attribute name="action">win.close-all</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Close</attribute>
-        <attribute name="action">win.close</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Quit</attribute>
-        <attribute name="action">app.quit</attribute>
-      </item>
-    </section>
-  </menu>
   <template class="GeditWindow" parent="GtkWindow">
     <property name="can_focus">False</property>
     <property name="has_focus">False</property>
diff --git a/plugins/docinfo/gedit-docinfo-plugin.c b/plugins/docinfo/gedit-docinfo-plugin.c
index 97539bf..10ab10a 100644
--- a/plugins/docinfo/gedit-docinfo-plugin.c
+++ b/plugins/docinfo/gedit-docinfo-plugin.c
@@ -30,18 +30,19 @@
 #include <pango/pango-break.h>
 #include <gmodule.h>
 
+#include <gedit/gedit-app.h>
 #include <gedit/gedit-window.h>
-#include <gedit/gedit-window-activatable.h>
 #include <gedit/gedit-debug.h>
 #include <gedit/gedit-utils.h>
 #include <gedit/gedit-menu-extension.h>
+#include <gedit/gedit-app-activatable.h>
+#include <gedit/gedit-window-activatable.h>
 
 struct _GeditDocinfoPluginPrivate
 {
        GeditWindow *window;
 
        GSimpleAction *action;
-       GeditMenuExtension *menu;
 
        GtkWidget *dialog;
        GtkWidget *file_name_label;
@@ -62,20 +63,27 @@ struct _GeditDocinfoPluginPrivate
        GtkWidget *selected_chars_label;
        GtkWidget *selected_chars_ns_label;
        GtkWidget *selected_bytes_label;
+
+       GeditApp  *app;
+       GeditMenuExtension *menu_ext;
 };
 
 enum
 {
        PROP_0,
-       PROP_WINDOW
+       PROP_WINDOW,
+       PROP_APP
 };
 
+static void gedit_app_activatable_iface_init (GeditAppActivatableInterface *iface);
 static void gedit_window_activatable_iface_init (GeditWindowActivatableInterface *iface);
 
 G_DEFINE_DYNAMIC_TYPE_EXTENDED (GeditDocinfoPlugin,
                                gedit_docinfo_plugin,
                                PEAS_TYPE_EXTENSION_BASE,
                                0,
+                               G_IMPLEMENT_INTERFACE_DYNAMIC (GEDIT_TYPE_APP_ACTIVATABLE,
+                                                              gedit_app_activatable_iface_init)
                                G_IMPLEMENT_INTERFACE_DYNAMIC (GEDIT_TYPE_WINDOW_ACTIVATABLE,
                                                               gedit_window_activatable_iface_init))
 
@@ -437,8 +445,9 @@ gedit_docinfo_plugin_dispose (GObject *object)
        gedit_debug_message (DEBUG_PLUGINS, "GeditDocinfoPlugin dispose");
 
        g_clear_object (&plugin->priv->action);
-       g_clear_object (&plugin->priv->menu);
        g_clear_object (&plugin->priv->window);
+       g_clear_object (&plugin->priv->menu_ext);
+       g_clear_object (&plugin->priv->app);
 
        G_OBJECT_CLASS (gedit_docinfo_plugin_parent_class)->dispose (object);
 }
@@ -465,7 +474,9 @@ gedit_docinfo_plugin_set_property (GObject      *object,
                case PROP_WINDOW:
                        plugin->priv->window = GEDIT_WINDOW (g_value_dup_object (value));
                        break;
-
+               case PROP_APP:
+                       plugin->priv->app = GEDIT_APP (g_value_dup_object (value));
+                       break;
                default:
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                        break;
@@ -485,7 +496,9 @@ gedit_docinfo_plugin_get_property (GObject    *object,
                case PROP_WINDOW:
                        g_value_set_object (value, plugin->priv->window);
                        break;
-
+               case PROP_APP:
+                       g_value_set_object (value, plugin->priv->app);
+                       break;
                default:
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                        break;
@@ -515,7 +528,7 @@ update_ui (GeditDocinfoPlugin *plugin)
 }
 
 static void
-gedit_docinfo_plugin_activate (GeditWindowActivatable *activatable)
+gedit_docinfo_plugin_app_activate (GeditAppActivatable *activatable)
 {
        GeditDocinfoPluginPrivate *priv;
        GMenuItem *item;
@@ -524,23 +537,47 @@ gedit_docinfo_plugin_activate (GeditWindowActivatable *activatable)
 
        priv = GEDIT_DOCINFO_PLUGIN (activatable)->priv;
 
+       priv->menu_ext = gedit_app_activatable_extend_menu (activatable,
+                                                           "ext9");
+       item = g_menu_item_new (_("_Document Statistics"), "win.docinfo");
+       gedit_menu_extension_append_menu_item (priv->menu_ext, item);
+       g_object_unref (item);
+
+       update_ui (GEDIT_DOCINFO_PLUGIN (activatable));
+}
+
+static void
+gedit_docinfo_plugin_app_deactivate (GeditAppActivatable *activatable)
+{
+       GeditDocinfoPluginPrivate *priv;
+
+       gedit_debug (DEBUG_PLUGINS);
+
+       priv = GEDIT_DOCINFO_PLUGIN (activatable)->priv;
+
+       g_clear_object (&priv->menu_ext);
+}
+
+static void
+gedit_docinfo_plugin_window_activate (GeditWindowActivatable *activatable)
+{
+       GeditDocinfoPluginPrivate *priv;
+
+       gedit_debug (DEBUG_PLUGINS);
+
+       priv = GEDIT_DOCINFO_PLUGIN (activatable)->priv;
+
        priv->action = g_simple_action_new ("docinfo", NULL);
        g_signal_connect (priv->action, "activate",
                          G_CALLBACK (docinfo_cb), activatable);
        g_action_map_add_action (G_ACTION_MAP (priv->window),
                                 G_ACTION (priv->action));
 
-       priv->menu = gedit_window_activatable_extend_menu (activatable,
-                                                          "ext9");
-       item = g_menu_item_new (_("_Document Statistics"), "win.docinfo");
-       gedit_menu_extension_append_menu_item (priv->menu, item);
-       g_object_unref (item);
-
        update_ui (GEDIT_DOCINFO_PLUGIN (activatable));
 }
 
 static void
-gedit_docinfo_plugin_deactivate (GeditWindowActivatable *activatable)
+gedit_docinfo_plugin_window_deactivate (GeditWindowActivatable *activatable)
 {
        GeditDocinfoPluginPrivate *priv;
 
@@ -552,7 +589,7 @@ gedit_docinfo_plugin_deactivate (GeditWindowActivatable *activatable)
 }
 
 static void
-gedit_docinfo_plugin_update_state (GeditWindowActivatable *activatable)
+gedit_docinfo_plugin_window_update_state (GeditWindowActivatable *activatable)
 {
        gedit_debug (DEBUG_PLUGINS);
 
@@ -570,16 +607,24 @@ gedit_docinfo_plugin_class_init (GeditDocinfoPluginClass *klass)
        object_class->get_property = gedit_docinfo_plugin_get_property;
 
        g_object_class_override_property (object_class, PROP_WINDOW, "window");
+       g_object_class_override_property (object_class, PROP_APP, "app");
 
        g_type_class_add_private (klass, sizeof (GeditDocinfoPluginPrivate));
 }
 
 static void
+gedit_app_activatable_iface_init (GeditAppActivatableInterface *iface)
+{
+       iface->activate = gedit_docinfo_plugin_app_activate;
+       iface->deactivate = gedit_docinfo_plugin_app_deactivate;
+}
+
+static void
 gedit_window_activatable_iface_init (GeditWindowActivatableInterface *iface)
 {
-       iface->activate = gedit_docinfo_plugin_activate;
-       iface->deactivate = gedit_docinfo_plugin_deactivate;
-       iface->update_state = gedit_docinfo_plugin_update_state;
+       iface->activate = gedit_docinfo_plugin_window_activate;
+       iface->deactivate = gedit_docinfo_plugin_window_deactivate;
+       iface->update_state = gedit_docinfo_plugin_window_update_state;
 }
 
 static void
@@ -594,6 +639,9 @@ peas_register_types (PeasObjectModule *module)
        gedit_docinfo_plugin_register_type (G_TYPE_MODULE (module));
 
        peas_object_module_register_extension_type (module,
+                                                   GEDIT_TYPE_APP_ACTIVATABLE,
+                                                   GEDIT_TYPE_DOCINFO_PLUGIN);
+       peas_object_module_register_extension_type (module,
                                                    GEDIT_TYPE_WINDOW_ACTIVATABLE,
                                                    GEDIT_TYPE_DOCINFO_PLUGIN);
 }
diff --git a/plugins/quickopen/quickopen/__init__.py b/plugins/quickopen/quickopen/__init__.py
index e110156..8026028 100644
--- a/plugins/quickopen/quickopen/__init__.py
+++ b/plugins/quickopen/quickopen/__init__.py
@@ -30,6 +30,10 @@ class QuickOpenAppActivatable(GObject.Object, Gedit.AppActivatable):
     def do_activate(self):
         self.app.add_accelerator("<Primary><Alt>O", "win.quickopen", None)
 
+        self.menu_ext = self.extend_menu("ext2")
+        item = Gio.MenuItem.new(_("Quick Open..."), "win.quickopen")
+        self.menu_ext.prepend_menu_item(item)
+
     def do_deactivate(self):
         self.app.remove_accelerator("win.quickopen", None)
 
@@ -44,10 +48,13 @@ class QuickOpenPlugin(GObject.Object, Gedit.WindowActivatable):
     def do_activate(self):
         self._popup_size = (450, 300)
         self._popup = None
-        self._install_menu()
+
+        action = Gio.SimpleAction(name="quickopen")
+        action.connect('activate', self.on_quick_open_activate)
+        self.window.add_action(action)
 
     def do_deactivate(self):
-        self._uninstall_menu()
+        self.window.remove_action("quickopen")
 
     def get_popup_size(self):
         return self._popup_size
@@ -55,20 +62,6 @@ class QuickOpenPlugin(GObject.Object, Gedit.WindowActivatable):
     def set_popup_size(self, size):
         self._popup_size = size
 
-    def _uninstall_menu(self):
-        self.window.remove_action("quickopen")
-
-    def _install_menu(self):
-        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"))
-
-        self.menu = self.extend_menu("ext2")
-        self.menu.prepend_menu_item(item)
-
     def _create_popup(self):
         paths = []
 
diff --git a/plugins/snippets/snippets/appactivatable.py b/plugins/snippets/snippets/appactivatable.py
index 9c33426..bc7b8f6 100644
--- a/plugins/snippets/snippets/appactivatable.py
+++ b/plugins/snippets/snippets/appactivatable.py
@@ -44,6 +44,17 @@ class AppActivatable(GObject.Object, Gedit.AppActivatable):
 
                 library.set_dirs(snippetsdir, self.system_dirs())
 
+                action = Gio.SimpleAction(name="snippets")
+                action.connect('activate', self.on_action_snippets_activate)
+                self.app.add_action(action)
+
+                item = Gio.MenuItem.new(_("Manage _Snippets..."), "app.snippets")
+                self.menu = self.extend_menu("appmenuext2")
+                self.menu.append_menu_item(item)
+
+        def do_deactivate(self):
+                self.window.remove_action("snippets")
+
         def system_dirs(self):
                 if platform.system() != 'Windows':
                         if 'XDG_DATA_DIRS' in os.environ:
@@ -72,4 +83,10 @@ class AppActivatable(GObject.Object, Gedit.AppActivatable):
 
                 return ret
 
+        def create_configure_dialog(self):
+                SharedData().show_manager(self.app.get_active_window(), self.plugin_info.get_data_dir())
+
+        def on_action_snippets_activate(self, action, parameter):
+                self.create_configure_dialog()
+
 # vi:ex:ts=8:et
diff --git a/plugins/snippets/snippets/windowactivatable.py b/plugins/snippets/snippets/windowactivatable.py
index 54521c8..4ae9c5d 100644
--- a/plugins/snippets/snippets/windowactivatable.py
+++ b/plugins/snippets/snippets/windowactivatable.py
@@ -48,7 +48,6 @@ class WindowActivatable(GObject.Object, Gedit.WindowActivatable, Signals):
                 self.current_language_accel_group = None
 
         def do_activate(self):
-                self.insert_menu()
                 self.register_messages()
 
                 library = Library()
@@ -73,7 +72,6 @@ class WindowActivatable(GObject.Object, Gedit.WindowActivatable, Signals):
 
                 self.accel_group = None
 
-                self.remove_menu()
                 self.unregister_messages()
 
                 library = Library()
@@ -145,18 +143,6 @@ class WindowActivatable(GObject.Object, Gedit.WindowActivatable, Signals):
 
                 controller.parse_and_run_snippet(message.props.snippet, iter)
 
-        def insert_menu(self):
-                action = Gio.SimpleAction(name="snippets")
-                action.connect('activate', self.on_action_snippets_activate)
-                self.window.add_action(action)
-
-                item = Gio.MenuItem.new(_("Manage _Snippets..."), "win.snippets")
-                self.menu = self.extend_menu("appmenuext2")
-                self.menu.append_menu_item(item)
-
-        def remove_menu(self):
-                self.window.remove_action("snippets")
-
         def find_snippet(self, snippets, tag):
                 result = []
 
@@ -192,13 +178,6 @@ class WindowActivatable(GObject.Object, Gedit.WindowActivatable, Signals):
         def on_active_tab_changed(self, window, tab):
                 self.update_language(SharedData().get_controller(tab.get_view()))
 
-        # Callbacks
-        def create_configure_dialog(self):
-                SharedData().show_manager(self.window, self.plugin_info.get_data_dir())
-
-        def on_action_snippets_activate(self, action, parameter):
-                self.create_configure_dialog()
-
         def accelerator_activated(self, group, obj, keyval, mod):
                 if obj == self.window:
                         controller = SharedData().get_active_controller(self.window)
diff --git a/plugins/sort/gedit-sort-plugin.c b/plugins/sort/gedit-sort-plugin.c
index fb8bcc6..3a99b89 100644
--- a/plugins/sort/gedit-sort-plugin.c
+++ b/plugins/sort/gedit-sort-plugin.c
@@ -31,16 +31,20 @@
 #include <gedit/gedit-utils.h>
 #include <gedit/gedit-app.h>
 #include <gedit/gedit-window.h>
+#include <gedit/gedit-app-activatable.h>
 #include <gedit/gedit-window-activatable.h>
 
 #define GEDIT_SORT_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_SORT_PLUGIN, 
GeditSortPluginPrivate))
 
+static void gedit_app_activatable_iface_init (GeditAppActivatableInterface *iface);
 static void gedit_window_activatable_iface_init (GeditWindowActivatableInterface *iface);
 
 G_DEFINE_DYNAMIC_TYPE_EXTENDED (GeditSortPlugin,
                                gedit_sort_plugin,
                                PEAS_TYPE_EXTENSION_BASE,
                                0,
+                               G_IMPLEMENT_INTERFACE_DYNAMIC (GEDIT_TYPE_APP_ACTIVATABLE,
+                                                              gedit_app_activatable_iface_init)
                                G_IMPLEMENT_INTERFACE_DYNAMIC (GEDIT_TYPE_WINDOW_ACTIVATABLE,
                                                               gedit_window_activatable_iface_init))
 
@@ -49,14 +53,15 @@ struct _GeditSortPluginPrivate
        GeditWindow *window;
 
        GSimpleAction *action;
-       GeditMenuExtension *menu;
-
        GtkWidget *dialog;
        GtkWidget *col_num_spinbutton;
        GtkWidget *reverse_order_checkbutton;
        GtkWidget *ignore_case_checkbutton;
        GtkWidget *remove_dups_checkbutton;
 
+       GeditApp *app;
+       GeditMenuExtension *menu_ext;
+
        GtkTextIter start, end; /* selection */
 };
 
@@ -72,7 +77,8 @@ typedef struct
 enum
 {
        PROP_0,
-       PROP_WINDOW
+       PROP_WINDOW,
+       PROP_APP
 };
 
 static void sort_real (GeditSortPlugin *plugin);
@@ -413,7 +419,7 @@ update_ui (GeditSortPlugin *plugin)
 }
 
 static void
-gedit_sort_plugin_activate (GeditWindowActivatable *activatable)
+gedit_sort_plugin_app_activate (GeditAppActivatable *activatable)
 {
        GeditSortPluginPrivate *priv;
        GMenuItem *item;
@@ -422,23 +428,47 @@ gedit_sort_plugin_activate (GeditWindowActivatable *activatable)
 
        priv = GEDIT_SORT_PLUGIN (activatable)->priv;
 
+       priv->menu_ext = gedit_app_activatable_extend_menu (activatable,
+                                                           "ext9");
+       item = g_menu_item_new (_("S_ort..."), "win.sort");
+       gedit_menu_extension_append_menu_item (priv->menu_ext, item);
+       g_object_unref (item);
+
+       update_ui (GEDIT_SORT_PLUGIN (activatable));
+}
+
+static void
+gedit_sort_plugin_app_deactivate (GeditAppActivatable *activatable)
+{
+       GeditSortPluginPrivate *priv;
+
+       gedit_debug (DEBUG_PLUGINS);
+
+       priv = GEDIT_SORT_PLUGIN (activatable)->priv;
+
+       g_clear_object (&priv->menu_ext);
+}
+
+static void
+gedit_sort_plugin_window_activate (GeditWindowActivatable *activatable)
+{
+       GeditSortPluginPrivate *priv;
+
+       gedit_debug (DEBUG_PLUGINS);
+
+       priv = GEDIT_SORT_PLUGIN (activatable)->priv;
+
        priv->action = g_simple_action_new ("sort", NULL);
        g_signal_connect (priv->action, "activate",
                          G_CALLBACK (sort_cb), activatable);
        g_action_map_add_action (G_ACTION_MAP (priv->window),
                                 G_ACTION (priv->action));
 
-       priv->menu = gedit_window_activatable_extend_menu (activatable,
-                                                          "ext9");
-       item = g_menu_item_new (_("S_ort..."), "win.sort");
-       gedit_menu_extension_append_menu_item (priv->menu, item);
-       g_object_unref (item);
-
        update_ui (GEDIT_SORT_PLUGIN (activatable));
 }
 
 static void
-gedit_sort_plugin_deactivate (GeditWindowActivatable *activatable)
+gedit_sort_plugin_window_deactivate (GeditWindowActivatable *activatable)
 {
        GeditSortPluginPrivate *priv;
 
@@ -449,7 +479,7 @@ gedit_sort_plugin_deactivate (GeditWindowActivatable *activatable)
 }
 
 static void
-gedit_sort_plugin_update_state (GeditWindowActivatable *activatable)
+gedit_sort_plugin_window_update_state (GeditWindowActivatable *activatable)
 {
        gedit_debug (DEBUG_PLUGINS);
 
@@ -474,8 +504,9 @@ gedit_sort_plugin_dispose (GObject *object)
        gedit_debug_message (DEBUG_PLUGINS, "GeditSortPlugin disposing");
 
        g_clear_object (&plugin->priv->action);
-       g_clear_object (&plugin->priv->menu);
        g_clear_object (&plugin->priv->window);
+       g_clear_object (&plugin->priv->menu_ext);
+       g_clear_object (&plugin->priv->app);
 
        G_OBJECT_CLASS (gedit_sort_plugin_parent_class)->dispose (object);
 }
@@ -502,7 +533,9 @@ gedit_sort_plugin_set_property (GObject      *object,
                case PROP_WINDOW:
                        plugin->priv->window = GEDIT_WINDOW (g_value_dup_object (value));
                        break;
-
+               case PROP_APP:
+                       plugin->priv->app = GEDIT_APP (g_value_dup_object (value));
+                       break;
                default:
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                        break;
@@ -522,7 +555,9 @@ gedit_sort_plugin_get_property (GObject    *object,
                case PROP_WINDOW:
                        g_value_set_object (value, plugin->priv->window);
                        break;
-
+               case PROP_APP:
+                       g_value_set_object (value, plugin->priv->app);
+                       break;
                default:
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                        break;
@@ -540,6 +575,7 @@ gedit_sort_plugin_class_init (GeditSortPluginClass *klass)
        object_class->get_property = gedit_sort_plugin_get_property;
 
        g_object_class_override_property (object_class, PROP_WINDOW, "window");
+       g_object_class_override_property (object_class, PROP_APP, "app");
 
        g_type_class_add_private (klass, sizeof (GeditSortPluginPrivate));
 }
@@ -550,11 +586,18 @@ gedit_sort_plugin_class_finalize (GeditSortPluginClass *klass)
 }
 
 static void
+gedit_app_activatable_iface_init (GeditAppActivatableInterface *iface)
+{
+       iface->activate = gedit_sort_plugin_app_activate;
+       iface->deactivate = gedit_sort_plugin_app_deactivate;
+}
+
+static void
 gedit_window_activatable_iface_init (GeditWindowActivatableInterface *iface)
 {
-       iface->activate = gedit_sort_plugin_activate;
-       iface->deactivate = gedit_sort_plugin_deactivate;
-       iface->update_state = gedit_sort_plugin_update_state;
+       iface->activate = gedit_sort_plugin_window_activate;
+       iface->deactivate = gedit_sort_plugin_window_deactivate;
+       iface->update_state = gedit_sort_plugin_window_update_state;
 }
 
 G_MODULE_EXPORT void
@@ -563,6 +606,9 @@ peas_register_types (PeasObjectModule *module)
        gedit_sort_plugin_register_type (G_TYPE_MODULE (module));
 
        peas_object_module_register_extension_type (module,
+                                                   GEDIT_TYPE_APP_ACTIVATABLE,
+                                                   GEDIT_TYPE_SORT_PLUGIN);
+       peas_object_module_register_extension_type (module,
                                                    GEDIT_TYPE_WINDOW_ACTIVATABLE,
                                                    GEDIT_TYPE_SORT_PLUGIN);
 }
diff --git a/plugins/spell/gedit-spell-app-activatable.c b/plugins/spell/gedit-spell-app-activatable.c
index e926c7e..3b9bf2a 100644
--- a/plugins/spell/gedit-spell-app-activatable.c
+++ b/plugins/spell/gedit-spell-app-activatable.c
@@ -18,16 +18,16 @@
  * along with gedit. If not, see <http://www.gnu.org/licenses/>.
  */
 
-
-#include "gedit-spell-app-activatable.h"
+#include <glib/gi18n.h>
+#include <libpeas/peas-object-module.h>
 #include <gedit/gedit-app-activatable.h>
 #include <gedit/gedit-app.h>
-#include <libpeas/peas-object-module.h>
-
+#include "gedit-spell-app-activatable.h"
 
 typedef struct _GeditSpellAppActivatablePrivate
 {
        GeditApp *app;
+       GeditMenuExtension *menu_ext;
 } GeditSpellAppActivatablePrivate;
 
 enum
@@ -53,6 +53,7 @@ gedit_spell_app_activatable_dispose (GObject *object)
        GeditSpellAppActivatablePrivate *priv = gedit_spell_app_activatable_get_instance_private 
(activatable);
 
        g_clear_object (&priv->app);
+       g_clear_object (&priv->menu_ext);
 
        G_OBJECT_CLASS (gedit_spell_app_activatable_parent_class)->dispose (object);
 }
@@ -126,8 +127,23 @@ gedit_spell_app_activatable_activate (GeditAppActivatable *activatable)
 {
        GeditSpellAppActivatable *app_activatable = GEDIT_SPELL_APP_ACTIVATABLE (activatable);
        GeditSpellAppActivatablePrivate *priv = gedit_spell_app_activatable_get_instance_private 
(app_activatable);
+       GMenuItem *item;
 
        gtk_application_add_accelerator (GTK_APPLICATION (priv->app), "<Shift>F7", "win.check_spell", NULL);
+       priv->menu_ext = gedit_app_activatable_extend_menu (activatable,
+                                                           "ext5");
+
+       item = g_menu_item_new (_("_Check Spelling..."), "win.check_spell");
+       gedit_menu_extension_append_menu_item (priv->menu_ext, item);
+       g_object_unref (item);
+
+       item = g_menu_item_new (_("Set _Language..."), "win.config_spell");
+       gedit_menu_extension_append_menu_item (priv->menu_ext, item);
+       g_object_unref (item);
+
+       item = g_menu_item_new (_("_Highlight Misspelled Words"), "win.auto_spell");
+       gedit_menu_extension_append_menu_item (priv->menu_ext, item);
+       g_object_unref (item);
 }
 
 static void
@@ -137,6 +153,7 @@ gedit_spell_app_activatable_deactivate (GeditAppActivatable *activatable)
        GeditSpellAppActivatablePrivate *priv = gedit_spell_app_activatable_get_instance_private 
(app_activatable);
 
        gtk_application_remove_accelerator (GTK_APPLICATION (priv->app), "win.check_spell", NULL);
+       g_clear_object (&priv->menu_ext);
 }
 
 static void
diff --git a/plugins/spell/gedit-spell-plugin.c b/plugins/spell/gedit-spell-plugin.c
index 53ca966..c89ab67 100644
--- a/plugins/spell/gedit-spell-plugin.c
+++ b/plugins/spell/gedit-spell-plugin.c
@@ -31,6 +31,7 @@
 
 #include <gedit/gedit-debug.h>
 #include <gedit/gedit-statusbar.h>
+#include <gedit/gedit-app.h>
 #include <gedit/gedit-window.h>
 #include <gedit/gedit-window-activatable.h>
 #include <gtksourceview/gtksource.h>
@@ -68,7 +69,6 @@ struct _GeditSpellPluginPrivate
 {
        GeditWindow    *window;
 
-       GeditMenuExtension *menu;
        guint           message_cid;
        gulong          tab_added_id;
        gulong          tab_removed_id;
@@ -137,7 +137,6 @@ gedit_spell_plugin_dispose (GObject *object)
 
        gedit_debug_message (DEBUG_PLUGINS, "GeditSpellPlugin disposing");
 
-       g_clear_object (&plugin->priv->menu);
        g_clear_object (&plugin->priv->window);
 
        G_OBJECT_CLASS (gedit_spell_plugin_parent_class)->dispose (object);
@@ -1118,7 +1117,6 @@ gedit_spell_plugin_activate (GeditWindowActivatable *activatable)
 {
        GeditSpellPlugin *plugin;
        GeditSpellPluginPrivate *priv;
-       GMenuItem *item;
        GList *views, *l;
 
        gedit_debug (DEBUG_PLUGINS);
@@ -1131,21 +1129,6 @@ gedit_spell_plugin_activate (GeditWindowActivatable *activatable)
                                         G_N_ELEMENTS (action_entries),
                                         activatable);
 
-       priv->menu = gedit_window_activatable_extend_menu (activatable,
-                                                          "ext5");
-
-       item = g_menu_item_new (_("_Check Spelling..."), "win.check_spell");
-       gedit_menu_extension_append_menu_item (priv->menu, item);
-       g_object_unref (item);
-
-       item = g_menu_item_new (_("Set _Language..."), "win.config_spell");
-       gedit_menu_extension_append_menu_item (priv->menu, item);
-       g_object_unref (item);
-
-       item = g_menu_item_new (_("_Highlight Misspelled Words"), "win.auto_spell");
-       gedit_menu_extension_append_menu_item (priv->menu, item);
-       g_object_unref (item);
-
        priv->message_cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (gedit_window_get_statusbar 
(priv->window)),
                                                          "spell_plugin_message");
 
diff --git a/plugins/time/gedit-time-plugin.c b/plugins/time/gedit-time-plugin.c
index 8eeb837..66d85a5 100644
--- a/plugins/time/gedit-time-plugin.c
+++ b/plugins/time/gedit-time-plugin.c
@@ -33,6 +33,7 @@
 #include <gedit/gedit-debug.h>
 #include <gedit/gedit-utils.h>
 #include <gedit/gedit-window.h>
+#include <gedit/gedit-app-activatable.h>
 #include <gedit/gedit-window-activatable.h>
 #include <libpeas-gtk/peas-gtk-configurable.h>
 #include <gedit/gedit-app.h>
@@ -44,7 +45,7 @@
 
 /* gsettings keys */
 #define TIME_BASE_SETTINGS     "org.gnome.gedit.plugins.time"
-#define PROMPT_TYPE_KEY                "prompt-type"
+#define PROMPT_TYPE_KEY        "prompt-type"
 #define SELECTED_FORMAT_KEY    "selected-format"
 #define CUSTOM_FORMAT_KEY      "custom-format"
 
@@ -147,18 +148,21 @@ struct _GeditTimePluginPrivate
 {
        GSettings      *settings;
 
+       GSimpleAction  *action;
        GeditWindow    *window;
 
-       GSimpleAction *action;
-       GeditMenuExtension *menu;
+       GeditApp *app;
+       GeditMenuExtension *menu_ext;
 };
 
 enum
 {
        PROP_0,
-       PROP_WINDOW
+       PROP_WINDOW,
+       PROP_APP
 };
 
+static void gedit_app_activatable_iface_init (GeditAppActivatableInterface *iface);
 static void gedit_window_activatable_iface_init (GeditWindowActivatableInterface *iface);
 static void peas_gtk_configurable_iface_init (PeasGtkConfigurableInterface *iface);
 
@@ -166,6 +170,8 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED (GeditTimePlugin,
                                gedit_time_plugin,
                                PEAS_TYPE_EXTENSION_BASE,
                                0,
+                               G_IMPLEMENT_INTERFACE_DYNAMIC (GEDIT_TYPE_APP_ACTIVATABLE,
+                                                              gedit_app_activatable_iface_init)
                                G_IMPLEMENT_INTERFACE_DYNAMIC (GEDIT_TYPE_WINDOW_ACTIVATABLE,
                                                               gedit_window_activatable_iface_init)
                                G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_GTK_TYPE_CONFIGURABLE,
@@ -192,8 +198,9 @@ gedit_time_plugin_dispose (GObject *object)
 
        g_clear_object (&plugin->priv->settings);
        g_clear_object (&plugin->priv->action);
-       g_clear_object (&plugin->priv->menu);
        g_clear_object (&plugin->priv->window);
+       g_clear_object (&plugin->priv->menu_ext);
+       g_clear_object (&plugin->priv->app);
 
        G_OBJECT_CLASS (gedit_time_plugin_parent_class)->dispose (object);
 }
@@ -211,7 +218,9 @@ gedit_time_plugin_set_property (GObject      *object,
                case PROP_WINDOW:
                        plugin->priv->window = GEDIT_WINDOW (g_value_dup_object (value));
                        break;
-
+               case PROP_APP:
+                       plugin->priv->app = GEDIT_APP (g_value_dup_object (value));
+                       break;
                default:
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                        break;
@@ -231,7 +240,9 @@ gedit_time_plugin_get_property (GObject    *object,
                case PROP_WINDOW:
                        g_value_set_object (value, plugin->priv->window);
                        break;
-
+               case PROP_APP:
+                       g_value_set_object (value, plugin->priv->app);
+                       break;
                default:
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                        break;
@@ -255,7 +266,7 @@ update_ui (GeditTimePlugin *plugin)
 }
 
 static void
-gedit_time_plugin_activate (GeditWindowActivatable *activatable)
+gedit_time_plugin_app_activate (GeditAppActivatable *activatable)
 {
        GeditTimePluginPrivate *priv;
        GMenuItem *item;
@@ -264,23 +275,47 @@ gedit_time_plugin_activate (GeditWindowActivatable *activatable)
 
        priv = GEDIT_TIME_PLUGIN (activatable)->priv;
 
+       priv->menu_ext = gedit_app_activatable_extend_menu (activatable,
+                                                           "ext5");
+       item = g_menu_item_new (_("In_sert Date and Time..."), "win.time");
+       gedit_menu_extension_append_menu_item (priv->menu_ext, item);
+       g_object_unref (item);
+
+       update_ui (GEDIT_TIME_PLUGIN (activatable));
+}
+
+static void
+gedit_time_plugin_app_deactivate (GeditAppActivatable *activatable)
+{
+       GeditTimePluginPrivate *priv;
+
+       gedit_debug (DEBUG_PLUGINS);
+
+       priv = GEDIT_TIME_PLUGIN (activatable)->priv;
+
+       g_clear_object (&priv->menu_ext);
+}
+
+static void
+gedit_time_plugin_window_activate (GeditWindowActivatable *activatable)
+{
+       GeditTimePluginPrivate *priv;
+
+       gedit_debug (DEBUG_PLUGINS);
+
+       priv = GEDIT_TIME_PLUGIN (activatable)->priv;
+
        priv->action = g_simple_action_new ("time", NULL);
        g_signal_connect (priv->action, "activate",
                          G_CALLBACK (time_cb), activatable);
        g_action_map_add_action (G_ACTION_MAP (priv->window),
                                 G_ACTION (priv->action));
 
-       priv->menu = gedit_window_activatable_extend_menu (activatable,
-                                                          "ext5");
-       item = g_menu_item_new (_("In_sert Date and Time..."), "win.time");
-       gedit_menu_extension_append_menu_item (priv->menu, item);
-       g_object_unref (item);
-
        update_ui (GEDIT_TIME_PLUGIN (activatable));
 }
 
 static void
-gedit_time_plugin_deactivate (GeditWindowActivatable *activatable)
+gedit_time_plugin_window_deactivate (GeditWindowActivatable *activatable)
 {
        GeditTimePluginPrivate *priv;
 
@@ -292,7 +327,7 @@ gedit_time_plugin_deactivate (GeditWindowActivatable *activatable)
 }
 
 static void
-gedit_time_plugin_update_state (GeditWindowActivatable *activatable)
+gedit_time_plugin_window_update_state (GeditWindowActivatable *activatable)
 {
        gedit_debug (DEBUG_PLUGINS);
 
@@ -1014,6 +1049,7 @@ gedit_time_plugin_class_init (GeditTimePluginClass *klass)
        object_class->get_property = gedit_time_plugin_get_property;
 
        g_object_class_override_property (object_class, PROP_WINDOW, "window");
+       g_object_class_override_property (object_class, PROP_APP, "app");
 
        g_type_class_add_private (object_class, sizeof (GeditTimePluginPrivate));
 }
@@ -1030,11 +1066,18 @@ peas_gtk_configurable_iface_init (PeasGtkConfigurableInterface *iface)
 }
 
 static void
+gedit_app_activatable_iface_init (GeditAppActivatableInterface *iface)
+{
+       iface->activate = gedit_time_plugin_app_activate;
+       iface->deactivate = gedit_time_plugin_app_deactivate;
+}
+
+static void
 gedit_window_activatable_iface_init (GeditWindowActivatableInterface *iface)
 {
-       iface->activate = gedit_time_plugin_activate;
-       iface->deactivate = gedit_time_plugin_deactivate;
-       iface->update_state = gedit_time_plugin_update_state;
+       iface->activate = gedit_time_plugin_window_activate;
+       iface->deactivate = gedit_time_plugin_window_deactivate;
+       iface->update_state = gedit_time_plugin_window_update_state;
 }
 
 G_MODULE_EXPORT void
@@ -1043,6 +1086,9 @@ peas_register_types (PeasObjectModule *module)
        gedit_time_plugin_register_type (G_TYPE_MODULE (module));
 
        peas_object_module_register_extension_type (module,
+                                                   GEDIT_TYPE_APP_ACTIVATABLE,
+                                                   GEDIT_TYPE_TIME_PLUGIN);
+       peas_object_module_register_extension_type (module,
                                                    GEDIT_TYPE_WINDOW_ACTIVATABLE,
                                                    GEDIT_TYPE_TIME_PLUGIN);
        peas_object_module_register_extension_type (module,


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