[file-roller/wip/jtojnar/gtk4: 2/16] Port GtkMenu to GtkPopoverMenu




commit c3d6dc2a3dbb266371178980c52942272089c7f3
Author: Jan Tojnar <jtojnar gmail com>
Date:   Sun Dec 12 23:21:36 2021 +0100

    Port GtkMenu to GtkPopoverMenu
    
    GtkMenu will not be present in GTK 4:
    https://docs.gtk.org/gtk4/migrating-3to4.html#gtkmenu-gtkmenubar-and-gtkmenuitem-are-gone

 src/dlg-add.c                 | 67 +++++++++++++++++++-----------------
 src/fr-file-selector-dialog.c | 79 +++++++++++++++++++++++++++++++------------
 src/fr-file-selector-dialog.h |  1 +
 src/fr-window.c               | 53 ++++++++---------------------
 src/gtk-utils.c               | 63 ++++++++++++++++++++++++++++++++++
 src/gtk-utils.h               |  2 ++
 src/ui/add-dialog-options.ui  | 16 +++++++++
 src/ui/file-selector.ui       | 51 ++++++++++------------------
 8 files changed, 207 insertions(+), 125 deletions(-)
---
diff --git a/src/dlg-add.c b/src/dlg-add.c
index 465a5f9d..d8a76e96 100644
--- a/src/dlg-add.c
+++ b/src/dlg-add.c
@@ -144,20 +144,31 @@ file_selector_response_cb (GtkWidget    *widget,
 }
 
 
-static void load_options_activate_cb (GtkMenuItem *menu_item, DialogData *data);
-static void save_options_activate_cb (GtkMenuItem *menu_item, DialogData *data);
-static void clear_options_activate_cb (GtkMenuItem *menu_item, DialogData *data);
+static void load_options_activate_cb (GSimpleAction *action,
+       GVariant *parameter,
+       gpointer user_data);
+static void save_options_activate_cb (GSimpleAction *action,
+       GVariant *parameter,
+       gpointer user_data);
+static void clear_options_activate_cb (GSimpleAction *action,
+       GVariant *parameter,
+       gpointer user_data);
 static void dlg_add_folder_load_last_options (DialogData *data);
 
 
+static GActionEntry dlg_entries[] = {
+  { "load-options", load_options_activate_cb, NULL, NULL, NULL },
+  { "save-options", save_options_activate_cb, NULL, NULL, NULL },
+  { "clear-options", clear_options_activate_cb, NULL, NULL, NULL }
+};
+
+
 /* create the "add" dialog. */
 void
 dlg_add (FrWindow *window)
 {
        DialogData *data;
        GtkWidget  *options_button;
-       GtkWidget  *options_menu;
-       GtkWidget  *menu_item;
        gboolean    use_header;
        GtkWidget  *button;
 
@@ -182,30 +193,18 @@ dlg_add (FrWindow *window)
        gtk_menu_button_set_use_popover (GTK_MENU_BUTTON (options_button), TRUE);
        gtk_widget_show (options_button);
 
-       options_menu = gtk_menu_new ();
-
        /* load options */
 
-       menu_item = gtk_menu_item_new_with_label (C_("Action", "Load Options"));
-       gtk_widget_show (menu_item);
-       g_signal_connect (menu_item, "activate", G_CALLBACK (load_options_activate_cb), data);
-       gtk_menu_shell_append (GTK_MENU_SHELL (options_menu), menu_item);
-
-       /* save options */
+       g_action_map_add_action_entries (G_ACTION_MAP (fr_file_selector_dialog_get_action_map 
(FR_FILE_SELECTOR_DIALOG (data->dialog))),
+                       dlg_entries, G_N_ELEMENTS (dlg_entries),
+                       data);
 
-       menu_item = gtk_menu_item_new_with_label (C_("Action", "Save Options"));
-       gtk_widget_show (menu_item);
-       g_signal_connect (menu_item, "activate", G_CALLBACK (save_options_activate_cb), data);
-       gtk_menu_shell_append (GTK_MENU_SHELL (options_menu), menu_item);
+       {
+               GMenuModel *menu;
 
-       /* clear options */
-
-       menu_item = gtk_menu_item_new_with_label (_("Reset Options"));
-       gtk_widget_show (menu_item);
-       g_signal_connect (menu_item, "activate", G_CALLBACK (clear_options_activate_cb), data);
-       gtk_menu_shell_append (GTK_MENU_SHELL (options_menu), menu_item);
-
-       gtk_menu_button_set_popup (GTK_MENU_BUTTON (options_button), options_menu);
+               menu = G_MENU_MODEL (gtk_builder_get_object (data->builder, "options-menu"));
+               gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (options_button), menu);
+       }
 
        /* add the buttons */
 
@@ -299,10 +298,12 @@ sync_widgets_with_options (DialogData *data,
 
 
 static void
-clear_options_activate_cb (GtkMenuItem *menu_item,
-                          DialogData  *data)
+clear_options_activate_cb (GSimpleAction *action,
+                          GVariant *parameter,
+                          gpointer user_data)
 {
        GFile *folder;
+       DialogData *data = user_data;
 
        folder = fr_file_selector_dialog_get_current_folder (FR_FILE_SELECTOR_DIALOG (data->dialog));
        sync_widgets_with_options (data,
@@ -720,8 +721,9 @@ aod_remove_cb (GtkWidget             *widget,
 
 
 static void
-load_options_activate_cb (GtkMenuItem *menu_item,
-                         DialogData  *data)
+load_options_activate_cb (GSimpleAction *action,
+                         GVariant *parameter,
+                         gpointer user_data)
 {
        LoadOptionsDialogData *aod_data;
        GtkWidget             *ok_button;
@@ -729,6 +731,7 @@ load_options_activate_cb (GtkMenuItem *menu_item,
        GtkWidget             *remove_button;
        GtkCellRenderer       *renderer;
        GtkTreeViewColumn     *column;
+       DialogData *data = user_data;
 
        aod_data = g_new0 (LoadOptionsDialogData, 1);
 
@@ -822,12 +825,14 @@ load_options_activate_cb (GtkMenuItem *menu_item,
 
 
 static void
-save_options_activate_cb (GtkMenuItem *menu_item,
-                         DialogData  *data)
+save_options_activate_cb (GSimpleAction *action,
+                         GVariant *parameter,
+                         gpointer user_data)
 {
        GFile *options_dir;
        GFile *options_file;
        char  *opt_filename;
+       DialogData *data = user_data;
 
        options_dir = _g_file_new_user_config_subdir (ADD_FOLDER_OPTIONS_DIR, TRUE);
        _g_file_make_directory_tree (options_dir, 0700, NULL);
diff --git a/src/fr-file-selector-dialog.c b/src/fr-file-selector-dialog.c
index 1ae2cc48..e5907c37 100644
--- a/src/fr-file-selector-dialog.c
+++ b/src/fr-file-selector-dialog.c
@@ -105,6 +105,9 @@ struct _FrFileSelectorDialog {
        GthIconCache  *icon_cache;
        GSettings     *settings;
        gboolean       show_hidden;
+       GSimpleActionGroup *action_map;
+       GtkPopover *file_context_menu;
+
 };
 
 
@@ -123,6 +126,8 @@ fr_file_selector_dialog_finalize (GObject *object)
        g_object_unref (self->builder);
        _g_object_unref (self->current_folder);
        g_object_unref (self->settings);
+       g_clear_object (&self->action_map);
+
 
        G_OBJECT_CLASS (fr_file_selector_dialog_parent_class)->finalize (object);
 }
@@ -574,7 +579,10 @@ files_treeview_button_press_event_cb (GtkWidget      *widget,
        FrFileSelectorDialog *self = user_data;
 
        if (event->button == 3) {
-               gtk_menu_popup_at_pointer (GTK_MENU (GET_WIDGET ("file_list_context_menu")),  (GdkEvent *) 
event);
+               int wx;
+               int wy;
+               gtk_tree_view_convert_bin_window_to_widget_coords (GTK_TREE_VIEW (widget), event->x, 
event->y, &wx, &wy);
+               _gtk_popover_popup_at_position (self->file_context_menu, wx, wy);
 
                return TRUE;
        }
@@ -606,16 +614,18 @@ select_all_files (FrFileSelectorDialog *self,
 
 
 static void
-select_all_menuitem_activate_cb (GtkMenuItem *menu_item,
-                                gpointer     user_data)
+select_all_activate_cb (GSimpleAction *action,
+                         GVariant *state,
+                         gpointer user_data)
 {
        select_all_files (FR_FILE_SELECTOR_DIALOG (user_data), TRUE);
 }
 
 
 static void
-unselect_all_menuitem_activate_cb (GtkMenuItem *menu_item,
-                                  gpointer     user_data)
+unselect_all_activate_cb (GSimpleAction *action,
+                                  GVariant *state,
+                                   gpointer user_data)
 {
        select_all_files (FR_FILE_SELECTOR_DIALOG (user_data), FALSE);
 }
@@ -628,23 +638,46 @@ _set_current_folder (FrFileSelectorDialog *self,
 
 
 static void
-show_hidden_files_menuitem_toggled_cb (GtkCheckMenuItem *checkmenuitem,
-                                      gpointer          user_data)
+show_hidden_files_toggled_cb (GSimpleAction *action,
+                                      GVariant *state,
+                                       gpointer user_data)
 {
        FrFileSelectorDialog *self = user_data;
        GFile                *folder;
        GList                *selected_files;
 
-       self->show_hidden = gtk_check_menu_item_get_active (checkmenuitem);
+       self->show_hidden = g_variant_get_boolean (state);
        folder = fr_file_selector_dialog_get_current_folder (self);
        selected_files = fr_file_selector_dialog_get_selected_files (self);
        _set_current_folder (self, folder, selected_files);
 
+       g_simple_action_set_state (action, state);
+
        _g_object_list_unref (selected_files);
        _g_object_unref (folder);
 }
 
 
+static void
+activate_toggle (GSimpleAction *action,
+                 GVariant      *parameter,
+                 gpointer       user_data)
+{
+       GVariant *state;
+
+       state = g_action_get_state (G_ACTION (action));
+       g_action_change_state (G_ACTION (action), g_variant_new_boolean (!g_variant_get_boolean (state)));
+       g_variant_unref (state);
+}
+
+
+static GActionEntry dlg_entries[] = {
+  { "select-all", select_all_activate_cb, NULL, NULL, NULL },
+  { "deselect-all", unselect_all_activate_cb, NULL, NULL, NULL },
+  { "show-hidden", activate_toggle, NULL, "false", show_hidden_files_toggled_cb }
+};
+
+
 static void
 fr_file_selector_dialog_init (FrFileSelectorDialog *self)
 {
@@ -653,6 +686,8 @@ fr_file_selector_dialog_init (FrFileSelectorDialog *self)
        self->icon_cache = NULL;
        self->settings = g_settings_new ("org.gnome.FileRoller.FileSelector");
        self->show_hidden = g_settings_get_boolean (self->settings, PREF_FILE_SELECTOR_SHOW_HIDDEN);
+       self->action_map = g_simple_action_group_new ();
+       self->file_context_menu = GTK_POPOVER (gtk_popover_new_from_model (GET_WIDGET ("files_treeview"), 
G_MENU_MODEL (gtk_builder_get_object (self->builder, "file_list_context_menu_model"))));
 
        gtk_container_set_border_width (GTK_CONTAINER (self), 5);
        gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), GET_WIDGET 
("content"), TRUE, TRUE, 0);
@@ -662,8 +697,6 @@ fr_file_selector_dialog_init (FrFileSelectorDialog *self)
        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), 
FILE_LIST_COLUMN_MODIFIED, files_modified_column_sort_func, self, NULL);
        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GET_WIDGET ("files_liststore")), 
FILE_LIST_COLUMN_NAME, GTK_SORT_ASCENDING);
 
-       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (GET_WIDGET ("show_hidden_files_menuitem")), 
self->show_hidden);
-
        g_signal_connect (GET_WIDGET ("is_selected_cellrenderertoggle"),
                          "toggled",
                          G_CALLBACK (is_selected_cellrenderertoggle_toggled_cb),
@@ -684,18 +717,13 @@ fr_file_selector_dialog_init (FrFileSelectorDialog *self)
                          "button-press-event",
                          G_CALLBACK (files_treeview_button_press_event_cb),
                          self);
-       g_signal_connect (GET_WIDGET ("select_all_menuitem"),
-                         "activate",
-                         G_CALLBACK (select_all_menuitem_activate_cb),
-                         self);
-       g_signal_connect (GET_WIDGET ("unselect_all_menuitem"),
-                         "activate",
-                         G_CALLBACK (unselect_all_menuitem_activate_cb),
-                         self);
-       g_signal_connect (GET_WIDGET ("show_hidden_files_menuitem"),
-                         "toggled",
-                         G_CALLBACK (show_hidden_files_menuitem_toggled_cb),
-                         self);
+
+       g_action_map_add_action_entries (G_ACTION_MAP (self->action_map),
+                       dlg_entries, G_N_ELEMENTS (dlg_entries),
+                       self);
+       gtk_widget_insert_action_group (GTK_WIDGET (self), "file-selector-dialog", G_ACTION_GROUP 
(self->action_map));
+
+       g_simple_action_set_state (G_SIMPLE_ACTION (g_action_map_lookup_action (G_ACTION_MAP 
(self->action_map), "show-hidden")), g_variant_new_boolean (self->show_hidden));
 
        _fr_file_selector_dialog_update_size (self);
        gtk_widget_grab_focus (GET_WIDGET ("files_treeview"));
@@ -733,6 +761,13 @@ fr_file_selector_dialog_get_extra_widget (FrFileSelectorDialog *self)
 }
 
 
+GSimpleActionGroup *
+fr_file_selector_dialog_get_action_map (FrFileSelectorDialog *self)
+{
+       return self->action_map;
+}
+
+
 static gboolean
 _g_date_time_same_day (GDateTime *dt1,
                       GDateTime *dt2)
diff --git a/src/fr-file-selector-dialog.h b/src/fr-file-selector-dialog.h
index 14eaf0bd..b6472cc8 100644
--- a/src/fr-file-selector-dialog.h
+++ b/src/fr-file-selector-dialog.h
@@ -37,5 +37,6 @@ GFile *         fr_file_selector_dialog_get_current_folder  (FrFileSelectorDialo
 void            fr_file_selector_dialog_set_selected_files  (FrFileSelectorDialog   *dialog,
                                                             GList                  *files /* GFile list */);
 GList *         fr_file_selector_dialog_get_selected_files  (FrFileSelectorDialog   *dialog);
+GSimpleActionGroup *fr_file_selector_dialog_get_action_map (FrFileSelectorDialog   *dialog);
 
 #endif /* FR_FILE_SELECTOR_DIALOG_H */
diff --git a/src/fr-window.c b/src/fr-window.c
index c61070fc..c5fd7101 100644
--- a/src/fr-window.c
+++ b/src/fr-window.c
@@ -3603,6 +3603,8 @@ dir_tree_button_press_cb (GtkWidget      *widget,
                if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (window->priv->tree_view),
                                                   event->x, event->y,
                                                   &path, NULL, NULL, NULL)) {
+                       int wx;
+                       int wy;
 
                        if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (window->priv->tree_store), &iter, 
path)) {
                                gtk_tree_path_free (path);
@@ -3615,7 +3617,8 @@ dir_tree_button_press_cb (GtkWidget      *widget,
                                gtk_tree_selection_select_iter (selection, &iter);
                        }
 
-                       gtk_menu_popup_at_pointer (GTK_MENU (window->priv->sidebar_folder_popup_menu), 
(GdkEvent *) event);
+                       gtk_tree_view_convert_bin_window_to_widget_coords (GTK_TREE_VIEW (widget), event->x, 
event->y, &wx, &wy);
+                       _gtk_popover_popup_at_position (GTK_POPOVER 
(window->priv->sidebar_folder_popup_menu), wx, wy);
                }
                else
                        gtk_tree_selection_unselect_all (selection);
@@ -3782,6 +3785,8 @@ file_button_press_cb (GtkWidget      *widget,
                GtkTreePath *path;
                GtkTreeIter  iter;
                int          n_selected;
+               int wx;
+               int wy;
 
                if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (window->priv->list_view),
                                                   event->x, event->y,
@@ -3801,11 +3806,12 @@ file_button_press_cb (GtkWidget      *widget,
                else
                        gtk_tree_selection_unselect_all (selection);
 
+               gtk_tree_view_convert_bin_window_to_widget_coords (GTK_TREE_VIEW (window->priv->list_view), 
event->x, event->y, &wx, &wy);
                n_selected = fr_window_get_n_selected_files (window);
                if ((n_selected == 1) && selection_has_a_dir (window))
-                       gtk_menu_popup_at_pointer (GTK_MENU (window->priv->folder_popup_menu),  (GdkEvent *) 
event);
+                       _gtk_popover_popup_at_position (GTK_POPOVER (window->priv->folder_popup_menu), wx, 
wy);
                else
-                       gtk_menu_popup_at_pointer (GTK_MENU (window->priv->file_popup_menu), (GdkEvent *) 
event);
+                       _gtk_popover_popup_at_position (GTK_POPOVER (window->priv->file_popup_menu), wx, wy);
                return TRUE;
        }
        else if ((event->type == GDK_BUTTON_PRESS) && (event->button == 1)) {
@@ -4825,38 +4831,12 @@ key_press_cb (GtkWidget   *widget,
                    ((event->keyval == GDK_KEY_F10) &&
                     (event->state & modifiers) == GDK_SHIFT_MASK)) {
                        GtkTreeSelection *selection;
-                       GList *selected_rows;
-                       GtkTreePath *first_selected_row_path;
-                       GtkTreeView *tree_view;
-                       GdkRectangle rect;
-                       GdkWindow   *win;
 
-                       tree_view = GTK_TREE_VIEW (window->priv->list_view);
-                       win = gtk_tree_view_get_bin_window (tree_view);
-
-                       selection = gtk_tree_view_get_selection (tree_view);
-                       selected_rows = gtk_tree_selection_get_selected_rows (selection, NULL);
+                       selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->list_view));
                        if (selection == NULL)
                                return GDK_EVENT_PROPAGATE;
 
-                       if (selected_rows == NULL)
-                               return GDK_EVENT_PROPAGATE;
-
-                       first_selected_row_path = (GtkTreePath *) selected_rows->data;
-
-                       gtk_tree_view_get_cell_area (tree_view,
-                                                    first_selected_row_path,
-                                                    NULL,
-                                                    &rect);
-
-                       g_list_free_full (selected_rows, (GDestroyNotify) gtk_tree_path_free);
-
-                       gtk_menu_popup_at_rect (GTK_MENU (window->priv->file_popup_menu),
-                                               win,
-                                               &rect,
-                                               GDK_GRAVITY_SOUTH_WEST,
-                                               GDK_GRAVITY_NORTH_WEST,
-                                               (const GdkEvent *) event);
+                       _gtk_popover_popup_at_selected (GTK_POPOVER (window->priv->file_popup_menu), 
GTK_TREE_VIEW (window->priv->list_view));
                        retval = GDK_EVENT_STOP;
                }
                break;
@@ -5930,14 +5910,9 @@ fr_window_construct (FrWindow *window)
 
                builder = _gtk_builder_new_from_resource ("menus.ui");
 
-               window->priv->file_popup_menu = gtk_menu_new_from_model (G_MENU_MODEL (gtk_builder_get_object 
(builder, "file-popup")));
-               gtk_menu_attach_to_widget (GTK_MENU (window->priv->file_popup_menu), GTK_WIDGET (window), 
NULL);
-
-               window->priv->folder_popup_menu = gtk_menu_new_from_model (G_MENU_MODEL 
(gtk_builder_get_object (builder, "folder-popup")));
-               gtk_menu_attach_to_widget (GTK_MENU (window->priv->folder_popup_menu), GTK_WIDGET (window), 
NULL);
-
-               window->priv->sidebar_folder_popup_menu = gtk_menu_new_from_model (G_MENU_MODEL 
(gtk_builder_get_object (builder, "sidebar-popup")));
-               gtk_menu_attach_to_widget (GTK_MENU (window->priv->sidebar_folder_popup_menu), GTK_WIDGET 
(window), NULL);
+               window->priv->file_popup_menu = gtk_popover_new_from_model (window->priv->list_view, 
G_MENU_MODEL (gtk_builder_get_object (builder, "file-popup")));
+               window->priv->folder_popup_menu = gtk_popover_new_from_model (window->priv->list_view, 
G_MENU_MODEL (gtk_builder_get_object (builder, "folder-popup")));
+               window->priv->sidebar_folder_popup_menu = gtk_popover_new_from_model 
(window->priv->tree_view, G_MENU_MODEL (gtk_builder_get_object (builder, "sidebar-popup")));
 
                g_object_unref (builder);
        }
diff --git a/src/gtk-utils.c b/src/gtk-utils.c
index 5805bbb8..0bbd4492 100644
--- a/src/gtk-utils.c
+++ b/src/gtk-utils.c
@@ -911,3 +911,66 @@ _gtk_application_add_accelerators (GtkApplication *app,
                                                             acc->accelerator);
        }
 }
+
+void
+_gtk_popover_popup_at_selected (GtkPopover *popover, GtkTreeView *tree_view)
+{
+       int width = gtk_widget_get_allocated_width (GTK_WIDGET (tree_view));
+       int height = gtk_widget_get_allocated_height (GTK_WIDGET (tree_view));
+       gdouble center_x = 0.5 * width;
+       gdouble center_y = 0.5 * height;
+
+       GdkRectangle rect;
+       GtkTreeSelection *selection;
+       GList *list;
+
+       selection = gtk_tree_view_get_selection (tree_view);
+       list = gtk_tree_selection_get_selected_rows (selection, NULL);
+       if (list) {
+               int min_y = height;
+               int max_y = 0;
+               int max_height = 0;
+
+               for (GList *item = list; item; item = item->next) {
+                       GtkTreePath *path = list->data;
+
+                       gtk_tree_view_get_cell_area (tree_view, path, NULL, &rect);
+                       gtk_tree_view_convert_bin_window_to_widget_coords (tree_view, rect.x, rect.y, 
&rect.x, &rect.y);
+
+                       min_y = MIN (min_y, rect.y);
+                       if (rect.y > max_y) {
+                               max_y = rect.y;
+                               max_height = rect.height;
+                       }
+               }
+
+               rect.x = CLAMP (center_x - 20, 0, width - 40);
+               rect.y = min_y;
+               rect.width = 40;
+               rect.height = max_y + max_height - min_y;
+
+               g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+       } else {
+               rect.x = center_x;
+               rect.y = center_y;
+               rect.width = 1;
+               rect.height = 1;
+       }
+
+       gtk_popover_set_pointing_to (GTK_POPOVER (popover), &rect);
+       gtk_popover_popup (GTK_POPOVER (popover));
+}
+
+void
+_gtk_popover_popup_at_position (GtkPopover *popover, gdouble x, gdouble y)
+{
+       GdkRectangle rect;
+
+       rect.x = x;
+       rect.y = y;
+       rect.width = 1;
+       rect.height = 1;
+
+       gtk_popover_set_pointing_to (GTK_POPOVER (popover), &rect);
+       gtk_popover_popup (GTK_POPOVER (popover));
+}
diff --git a/src/gtk-utils.h b/src/gtk-utils.h
index d7dbc54d..8dfa4cca 100644
--- a/src/gtk-utils.h
+++ b/src/gtk-utils.h
@@ -122,5 +122,7 @@ void          _gtk_application_add_accelerator_for_action
 void         _gtk_application_add_accelerators    (GtkApplication   *app,
                                                    const FrAccelerator *accelerators,
                                                    int               n_accelerators);
+void         _gtk_popover_popup_at_selected (GtkPopover *popover, GtkTreeView *view);
+void         _gtk_popover_popup_at_position (GtkPopover *popover, gdouble x, gdouble y);
 
 #endif
diff --git a/src/ui/add-dialog-options.ui b/src/ui/add-dialog-options.ui
index fd8590e9..979868de 100644
--- a/src/ui/add-dialog-options.ui
+++ b/src/ui/add-dialog-options.ui
@@ -1,6 +1,22 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.10 -->
+  <menu id="options-menu">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">Load Options</attribute>
+        <attribute name="action">file-selector-dialog.load-options</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">Save Options</attribute>
+        <attribute name="action">file-selector-dialog.save-options</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">Reset Options</attribute>
+        <attribute name="action">file-selector-dialog.clear-options</attribute>
+      </item>
+    </section>
+  </menu>
   <object class="GtkBox" id="extra_widget">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
diff --git a/src/ui/file-selector.ui b/src/ui/file-selector.ui
index 5bd32864..7f10d57e 100644
--- a/src/ui/file-selector.ui
+++ b/src/ui/file-selector.ui
@@ -1,39 +1,24 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.10 -->
-  <object class="GtkMenu" id="file_list_context_menu">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <child>
-      <object class="GtkMenuItem" id="select_all_menuitem">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="label" translatable="yes">_Select All</property>
-        <property name="use_underline">True</property>
-      </object>
-    </child>
-    <child>
-      <object class="GtkMenuItem" id="unselect_all_menuitem">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="label" translatable="yes">Dese_lect All</property>
-        <property name="use_underline">True</property>
-      </object>
-    </child>
-    <child>
-      <object class="GtkSeparatorMenuItem" id="menuitem3">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-      </object>
-    </child>
-    <child>
-      <object class="GtkCheckMenuItem" id="show_hidden_files_menuitem">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="label" translatable="yes">Show Hidden Files</property>
-      </object>
-    </child>
-  </object>
+  <menu id="file_list_context_menu_model">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Select All</attribute>
+        <attribute name="action">file-selector-dialog.select-all</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">Dese_lect All</attribute>
+        <attribute name="action">file-selector-dialog.deselect-all</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">Show Hidden Files</attribute>
+        <attribute name="action">file-selector-dialog.show-hidden</attribute>
+      </item>
+    </section>
+  </menu>
   <object class="GtkListStore" id="files_liststore">
     <columns>
       <!-- column-name icon -->


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