[nautilus/wip/antoniof/preserve_popover_menu_model] ui-utilities: Simplify GMenu handling



commit 887c61f74484ef7b51c169938801eaf2fc85c505
Author: António Fernandes <antoniof gnome org>
Date:   Sat Jun 22 18:54:02 2019 +0100

    ui-utilities: Simplify GMenu handling
    
    We have been iterating on menu items to match a custom attribute, "id",
    in order to programatically add items to submenus and sections.
    
    But GtkBuilder can get us the submenus and sections by actual id.
    
    So take advantage of that and use the GMenu/GMenuModel API in a more
    direct fashion.

 src/nautilus-files-view.c                          |  90 ++++++------
 src/nautilus-pathbar.c                             |  16 ++-
 src/nautilus-ui-utilities.c                        | 151 ++++-----------------
 src/nautilus-ui-utilities.h                        |  10 +-
 .../ui/nautilus-files-view-context-menus.ui        |  23 ++--
 src/resources/ui/nautilus-pathbar-context-menu.ui  |   6 +-
 6 files changed, 90 insertions(+), 206 deletions(-)
---
diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c
index 666fcf365..710e43a2c 100644
--- a/src/nautilus-files-view.c
+++ b/src/nautilus-files-view.c
@@ -5008,24 +5008,24 @@ build_menu_for_extension_menu_items (NautilusFilesView *view,
 }
 
 static void
-update_extensions_menus (NautilusFilesView *view)
+update_extensions_menus (NautilusFilesView *view,
+                         GtkBuilder        *builder)
 {
-    NautilusFilesViewPrivate *priv;
     GList *selection_items, *background_items;
+    GObject *object;
     g_autoptr (GMenu) background_menu = NULL;
     g_autoptr (GMenu) selection_menu = NULL;
 
-    priv = nautilus_files_view_get_instance_private (view);
     selection_items = get_extension_selection_menu_items (view);
     if (selection_items != NULL)
     {
         selection_menu = build_menu_for_extension_menu_items (view, "extensions",
                                                               selection_items);
 
-        nautilus_gmenu_merge (priv->selection_menu_model,
-                              selection_menu,
-                              "extensions",
-                              FALSE);
+        object = gtk_builder_get_object (builder, "selection-extensions-section");
+        nautilus_gmenu_set_from_model (G_MENU (object),
+                                       G_MENU_MODEL (selection_menu));
+
         nautilus_menu_item_list_free (selection_items);
     }
 
@@ -5035,10 +5035,10 @@ update_extensions_menus (NautilusFilesView *view)
         background_menu = build_menu_for_extension_menu_items (view, "extensions",
                                                                background_items);
 
-        nautilus_gmenu_merge (priv->background_menu_model,
-                              background_menu,
-                              "extensions",
-                              FALSE);
+        object = gtk_builder_get_object (builder, "background-extensions-section");
+        nautilus_gmenu_set_from_model (G_MENU (object),
+                                       G_MENU_MODEL (background_menu));
+
         nautilus_menu_item_list_free (background_items);
     }
 
@@ -5500,7 +5500,8 @@ update_directory_in_scripts_menu (NautilusFilesView *view,
 
 
 static void
-update_scripts_menu (NautilusFilesView *view)
+update_scripts_menu (NautilusFilesView *view,
+                     GtkBuilder        *builder)
 {
     NautilusFilesViewPrivate *priv;
     GList *sorted_copy, *node;
@@ -5530,10 +5531,12 @@ update_scripts_menu (NautilusFilesView *view)
     submenu = update_directory_in_scripts_menu (view, directory);
     if (submenu != NULL)
     {
-        nautilus_gmenu_merge (priv->selection_menu_model,
-                              submenu,
-                              "scripts-submenu",
-                              TRUE);
+        GObject *object;
+
+        object = gtk_builder_get_object (builder, "scripts-submenu");
+        nautilus_gmenu_set_from_model (G_MENU (object),
+                                       G_MENU_MODEL (submenu));
+
         g_object_unref (submenu);
     }
 
@@ -5749,7 +5752,8 @@ update_directory_in_templates_menu (NautilusFilesView *view,
 
 
 static void
-update_templates_menu (NautilusFilesView *view)
+update_templates_menu (NautilusFilesView *view,
+                       GtkBuilder        *builder)
 {
     NautilusFilesViewPrivate *priv;
     GList *sorted_copy, *node;
@@ -5791,10 +5795,10 @@ update_templates_menu (NautilusFilesView *view)
     submenu = update_directory_in_templates_menu (view, directory);
     if (submenu != NULL)
     {
-        nautilus_gmenu_merge (priv->background_menu_model,
-                              submenu,
-                              "templates-submenu",
-                              FALSE);
+        GObject *object;
+        object = gtk_builder_get_object (builder, "templates-submenu");
+        nautilus_gmenu_set_from_model (G_MENU (object),
+                                       G_MENU_MODEL (submenu));
     }
 
     nautilus_view_set_templates_menu (NAUTILUS_VIEW (view), submenu);
@@ -7738,9 +7742,9 @@ nautilus_files_view_update_actions_state (NautilusFilesView *view)
 }
 
 static void
-update_selection_menu (NautilusFilesView *view)
+update_selection_menu (NautilusFilesView *view,
+                       GtkBuilder        *builder)
 {
-    NautilusFilesViewPrivate *priv;
     g_autolist (NautilusFile) selection = NULL;
     GList *l;
     gint selection_count;
@@ -7752,6 +7756,7 @@ update_selection_menu (NautilusFilesView *view)
     GAppInfo *app;
     GIcon *app_icon;
     GMenuItem *menu_item;
+    GObject *object;
     gboolean show_mount;
     gboolean show_unmount;
     gboolean show_eject;
@@ -7760,8 +7765,6 @@ update_selection_menu (NautilusFilesView *view)
     gboolean show_detect_media;
     GDriveStartStopType start_stop_type;
 
-    priv = nautilus_files_view_get_instance_private (view);
-
     selection = nautilus_view_get_selection (NAUTILUS_VIEW (view));
     selection_count = g_list_length (selection);
 
@@ -7778,10 +7781,8 @@ update_selection_menu (NautilusFilesView *view)
                                   selection_count);
     menu_item = g_menu_item_new (item_label, "view.new-folder-with-selection");
     g_menu_item_set_attribute (menu_item, "hidden-when", "s", "action-disabled");
-    nautilus_gmenu_add_item_in_submodel (priv->selection_menu_model,
-                                         menu_item,
-                                         "new-folder-with-selection-section",
-                                         FALSE);
+    object = gtk_builder_get_object (builder, "new-folder-with-selection-section");
+    g_menu_append_item (G_MENU (object), menu_item);
     g_object_unref (menu_item);
     g_free (item_label);
 
@@ -7863,10 +7864,8 @@ update_selection_menu (NautilusFilesView *view)
         g_menu_item_set_icon (menu_item, app_icon);
     }
 
-    nautilus_gmenu_add_item_in_submodel (priv->selection_menu_model,
-                                         menu_item,
-                                         "open-with-default-application-section",
-                                         FALSE);
+    object = gtk_builder_get_object (builder, "open-with-default-application-section");
+    g_menu_append_item (G_MENU (object), menu_item);
 
     g_free (item_label);
     g_object_unref (menu_item);
@@ -7936,10 +7935,8 @@ update_selection_menu (NautilusFilesView *view)
         }
 
         menu_item = g_menu_item_new (item_label, "view.start-volume");
-        nautilus_gmenu_add_item_in_submodel (priv->selection_menu_model,
-                                             menu_item,
-                                             "drive-section",
-                                             FALSE);
+        object = gtk_builder_get_object (builder, "drive-section");
+        g_menu_append_item (G_MENU (object), menu_item);
         g_object_unref (menu_item);
     }
 
@@ -7980,24 +7977,23 @@ update_selection_menu (NautilusFilesView *view)
         }
 
         menu_item = g_menu_item_new (item_label, "view.stop-volume");
-        nautilus_gmenu_add_item_in_submodel (priv->selection_menu_model,
-                                             menu_item,
-                                             "drive-section",
-                                             FALSE);
+        object = gtk_builder_get_object (builder, "drive-section");
+        g_menu_append_item (G_MENU (object), menu_item);
         g_object_unref (menu_item);
     }
 
-    update_scripts_menu (view);
+    update_scripts_menu (view, builder);
 }
 
 static void
-update_background_menu (NautilusFilesView *view)
+update_background_menu (NautilusFilesView *view,
+                        GtkBuilder        *builder)
 {
     if (nautilus_files_view_supports_creating_files (view) &&
         !showing_recent_directory (view) &&
         !showing_starred_directory (view))
     {
-        update_templates_menu (view);
+        update_templates_menu (view, builder);
     }
 }
 
@@ -8020,9 +8016,9 @@ real_update_context_menus (NautilusFilesView *view)
     object = gtk_builder_get_object (builder, "selection-menu");
     priv->selection_menu_model = g_object_ref (G_MENU (object));
 
-    update_selection_menu (view);
-    update_background_menu (view);
-    update_extensions_menus (view);
+    update_selection_menu (view, builder);
+    update_background_menu (view, builder);
+    update_extensions_menus (view, builder);
 
     nautilus_files_view_update_actions_state (view);
 }
diff --git a/src/nautilus-pathbar.c b/src/nautilus-pathbar.c
index 3abf165b4..a5bace76f 100644
--- a/src/nautilus-pathbar.c
+++ b/src/nautilus-pathbar.c
@@ -101,6 +101,8 @@ struct _NautilusPathBar
     GtkPopover *current_view_menu_popover;
     GtkPopover *button_menu_popover;
     GMenu *current_view_menu;
+    GMenu *extensions_section;
+    GMenu *templates_submenu;
     GMenu *button_menu;
     GMenu *extensions_background_menu;
     GMenu *templates_menu;
@@ -213,6 +215,8 @@ nautilus_path_bar_init (NautilusPathBar *self)
     /* Context menu */
     builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/ui/nautilus-pathbar-context-menu.ui");
     self->current_view_menu = g_object_ref_sink (G_MENU (gtk_builder_get_object (builder, 
"current-view-menu")));
+    self->extensions_section = g_object_ref (G_MENU (gtk_builder_get_object (builder, 
"extensions-section")));
+    self->templates_submenu = g_object_ref (G_MENU (gtk_builder_get_object (builder, "templates-submenu")));
     self->button_menu = g_object_ref_sink (G_MENU (gtk_builder_get_object (builder, "button-menu")));
     self->current_view_menu_popover = g_object_ref_sink (GTK_POPOVER (gtk_popover_new_from_model (NULL,
                                                                                                   
G_MENU_MODEL (self->current_view_menu))));
@@ -248,6 +252,8 @@ nautilus_path_bar_finalize (GObject *object)
 
     g_list_free (self->button_list);
     g_clear_object (&self->current_view_menu);
+    g_clear_object (&self->extensions_section);
+    g_clear_object (&self->templates_submenu);
     g_clear_object (&self->button_menu);
     g_clear_object (&self->button_menu_popover);
     g_clear_object (&self->current_view_menu_popover);
@@ -917,16 +923,14 @@ update_current_view_menu (NautilusPathBar *self)
 {
     if (self->extensions_background_menu != NULL)
     {
-        nautilus_gmenu_merge (self->current_view_menu,
-                              self->extensions_background_menu,
-                              "extensions",
-                              TRUE);
+        nautilus_gmenu_set_from_model (self->extensions_section,
+                                       G_MENU_MODEL (self->extensions_background_menu));
     }
 
     if (self->templates_menu != NULL)
     {
-        nautilus_gmenu_merge (self->current_view_menu, self->templates_menu,
-                              "templates-submenu", TRUE);
+        nautilus_gmenu_set_from_model (self->templates_submenu,
+                                       G_MENU_MODEL (self->templates_menu));
     }
 }
 
diff --git a/src/nautilus-ui-utilities.c b/src/nautilus-ui-utilities.c
index 1c84ee113..ab0db3e77 100644
--- a/src/nautilus-ui-utilities.c
+++ b/src/nautilus-ui-utilities.c
@@ -32,141 +32,40 @@
 #include <string.h>
 #include <glib/gi18n.h>
 
-static GMenuModel *
-find_gmenu_model (GMenuModel  *model,
-                  const gchar *model_id)
-{
-    gint i, n_items;
-    GMenuModel *insertion_model = NULL;
-
-    n_items = g_menu_model_get_n_items (model);
-
-    for (i = 0; i < n_items && !insertion_model; i++)
-    {
-        gchar *id = NULL;
-        if (g_menu_model_get_item_attribute (model, i, "id", "s", &id) &&
-            g_strcmp0 (id, model_id) == 0)
-        {
-            insertion_model = g_menu_model_get_item_link (model, i, G_MENU_LINK_SECTION);
-            if (!insertion_model)
-            {
-                insertion_model = g_menu_model_get_item_link (model, i, G_MENU_LINK_SUBMENU);
-            }
-        }
-        else
-        {
-            GMenuModel *submodel;
-            GMenuModel *submenu;
-            gint j, j_items;
-
-            submodel = g_menu_model_get_item_link (model, i, G_MENU_LINK_SECTION);
-
-            if (!submodel)
-            {
-                submodel = g_menu_model_get_item_link (model, i, G_MENU_LINK_SUBMENU);
-            }
-
-            if (!submodel)
-            {
-                continue;
-            }
-
-            j_items = g_menu_model_get_n_items (submodel);
-            for (j = 0; j < j_items; j++)
-            {
-                submenu = g_menu_model_get_item_link (submodel, j, G_MENU_LINK_SUBMENU);
-                if (submenu)
-                {
-                    insertion_model = find_gmenu_model (submenu, model_id);
-                    g_object_unref (submenu);
-                }
-
-                if (insertion_model)
-                {
-                    break;
-                }
-            }
-
-            g_object_unref (submodel);
-        }
-
-        g_free (id);
-    }
-
-    return insertion_model;
-}
-
-/*
- * The original GMenu is modified adding to the section @submodel_name
- * the items in @gmenu_to_merge.
- * @gmenu_to_merge should be a list of menu items.
+/**
+ * nautilus_gmenu_set_from_model:
+ * @target_menu: the #GMenu to be filled
+ * @source_model: (nullable): a #GMenuModel to copy items from
+ *
+ * This will replace the content of @target_menu with a copy of all items from
+ * @source_model.
+ *
+ * If the @source_model is empty (i.e., its item count is 0), or if it is %NULL,
+ * then the @target_menu is left empty.
  */
 void
-nautilus_gmenu_merge (GMenu       *original,
-                      GMenu       *gmenu_to_merge,
-                      const gchar *submodel_name,
-                      gboolean     prepend)
+nautilus_gmenu_set_from_model (GMenu      *target_menu,
+                               GMenuModel *source_model)
 {
-    gint i, n_items;
-    GMenuModel *submodel;
-    GMenuItem *item;
-
-    g_return_if_fail (G_IS_MENU (original));
-    g_return_if_fail (G_IS_MENU (gmenu_to_merge));
-
-    submodel = find_gmenu_model (G_MENU_MODEL (original), submodel_name);
-
-    g_return_if_fail (submodel != NULL);
+    g_return_if_fail (G_IS_MENU (target_menu));
+    g_return_if_fail (source_model == NULL || G_IS_MENU_MODEL (source_model));
 
-    n_items = g_menu_model_get_n_items (G_MENU_MODEL (gmenu_to_merge));
+    /* First, empty the menu... */
+    g_menu_remove_all (target_menu);
 
-    for (i = 0; i < n_items; i++)
+    /* ...then, repopulate it (maybe). */
+    if (source_model != NULL)
     {
-        if (prepend)
-        {
-            item = g_menu_item_new_from_model (G_MENU_MODEL (gmenu_to_merge),
-                                               n_items - i - 1);
-            g_menu_prepend_item (G_MENU (submodel), item);
-        }
-        else
+        gint n_items;
+
+        n_items = g_menu_model_get_n_items (source_model);
+        for (gint i = 0; i < n_items; i++)
         {
-            item = g_menu_item_new_from_model (G_MENU_MODEL (gmenu_to_merge), i);
-            g_menu_append_item (G_MENU (submodel), item);
+            g_autoptr (GMenuItem) item = NULL;
+            item = g_menu_item_new_from_model (source_model, i);
+            g_menu_append_item (target_menu, item);
         }
-        g_object_unref (item);
     }
-
-    g_object_unref (submodel);
-}
-
-/*
- * The GMenu @menu is modified adding to the section @submodel_name
- * the item @item.
- */
-void
-nautilus_gmenu_add_item_in_submodel (GMenu       *menu,
-                                     GMenuItem   *item,
-                                     const gchar *submodel_name,
-                                     gboolean     prepend)
-{
-    GMenuModel *submodel;
-
-    g_return_if_fail (G_IS_MENU (menu));
-    g_return_if_fail (G_IS_MENU_ITEM (item));
-
-    submodel = find_gmenu_model (G_MENU_MODEL (menu), submodel_name);
-
-    g_return_if_fail (submodel != NULL);
-    if (prepend)
-    {
-        g_menu_prepend_item (G_MENU (submodel), item);
-    }
-    else
-    {
-        g_menu_append_item (G_MENU (submodel), item);
-    }
-
-    g_object_unref (submodel);
 }
 
 #define NAUTILUS_THUMBNAIL_FRAME_LEFT 3
diff --git a/src/nautilus-ui-utilities.h b/src/nautilus-ui-utilities.h
index 6419f0d2f..1136e1de6 100644
--- a/src/nautilus-ui-utilities.h
+++ b/src/nautilus-ui-utilities.h
@@ -25,14 +25,8 @@
 #include <gtk/gtk.h>
 
 
-void        nautilus_gmenu_add_item_in_submodel     (GMenu             *menu,
-                                                     GMenuItem         *item,
-                                                     const gchar       *section_name,
-                                                     gboolean           prepend);
-void        nautilus_gmenu_merge                    (GMenu             *original,
-                                                     GMenu             *gmenu_to_merge,
-                                                     const gchar       *submodel_name,
-                                                     gboolean           prepend);
+void        nautilus_gmenu_set_from_model           (GMenu             *target_menu,
+                                                     GMenuModel        *source_model);
 
 void        nautilus_ui_frame_image                 (GdkPixbuf        **pixbuf);
 void        nautilus_ui_frame_video                 (GdkPixbuf        **pixbuf);
diff --git a/src/resources/ui/nautilus-files-view-context-menus.ui 
b/src/resources/ui/nautilus-files-view-context-menus.ui
index 9f0d23860..949abe5a4 100644
--- a/src/resources/ui/nautilus-files-view-context-menus.ui
+++ b/src/resources/ui/nautilus-files-view-context-menus.ui
@@ -5,8 +5,7 @@
       <attribute name="label" translatable="yes">New _Folder</attribute>
       <attribute name="action">view.new-folder</attribute>
     </item>
-    <submenu>
-      <attribute name="id">templates-submenu</attribute>
+    <submenu id="templates-submenu">
       <attribute name="label" translatable="yes">New _Document</attribute>
       <attribute name="action">view.new-document</attribute>
       <attribute name="hidden-when">action-disabled</attribute>
@@ -37,19 +36,15 @@
         <attribute name="hidden-when">action-disabled</attribute>
       </item>
     </section>
-    <section>
-      <attribute name="id">extensions</attribute>
+    <section id="background-extensions-section">
     </section>
   </menu>
   <menu id="selection-menu">
-    <section>
-      <attribute name="id">new-folder-with-selection-section</attribute>
+    <section id="new-folder-with-selection-section">
     </section>
-    <section>
-      <attribute name="id">open-with-default-application-section</attribute>
+    <section id="open-with-default-application-section">
     </section>
-    <submenu>
-      <attribute name="id">scripts-submenu</attribute>
+    <submenu id="scripts-submenu">
       <attribute name="label" translatable="yes">_Scripts</attribute>
       <attribute name="action">view.scripts</attribute>
       <attribute name="hidden-when">action-disabled</attribute>
@@ -85,8 +80,7 @@
         <attribute name="hidden-when">action-disabled</attribute>
       </item>
     </section>
-    <section>
-      <attribute name="id">drive-section</attribute>
+    <section id="drive-section">
       <item>
         <attribute name="label" translatable="yes">_Mount</attribute>
         <attribute name="action">view.mount-volume</attribute>
@@ -197,8 +191,7 @@
         <attribute name="hidden-when">action-disabled</attribute>
       </item>
     </section>
-    <section>
-      <attribute name="id">extensions</attribute>
+    <section id="selection-extensions-section">
       <item>
         <attribute name="label" translatable="yes">_Extract Here</attribute>
         <attribute name="action">view.extract-here</attribute>
@@ -239,4 +232,4 @@
       </item>
     </section>
   </menu>
-</interface>
\ No newline at end of file
+</interface>
diff --git a/src/resources/ui/nautilus-pathbar-context-menu.ui 
b/src/resources/ui/nautilus-pathbar-context-menu.ui
index 26e8b309e..2a253ba06 100644
--- a/src/resources/ui/nautilus-pathbar-context-menu.ui
+++ b/src/resources/ui/nautilus-pathbar-context-menu.ui
@@ -6,8 +6,7 @@
       <attribute name="label" translatable="yes">New _Folder…</attribute>
       <attribute name="action">view.new-folder</attribute>
     </item>
-    <submenu>
-      <attribute name="id">templates-submenu</attribute>
+    <submenu id="templates-submenu">
       <attribute name="label" translatable="yes">New _Document</attribute>
       <attribute name="action">view.new-document</attribute>
       <attribute name="hidden-when">action-disabled</attribute>
@@ -31,8 +30,7 @@
         <attribute name="hidden-when">action-disabled</attribute>
       </item>
     </section>
-    <section>
-      <attribute name="id">extensions</attribute>
+    <section id="extensions-section">
     </section>
   </menu>
   <menu id="button-menu">


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