[balsa/gtk4: 60/196] Various: Fill some menus with stateless GMenuItems




commit 2b2815b14020b707edfd8cf159d4c4da2ba5ab73
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Sat Jun 27 15:45:56 2020 -0400

    Various: Fill some menus with stateless GMenuItems
    
    Fill the move-to/copy-to menus with stateless GMenuItems, so that they
    are rendered without radio buttons.
    
    Instead, pass the URL as GObject data on a convenient object.
    
    * src/balsa-mblist.c (bmbl_add_action), (balsa_mblist_mru_menu),
      (balsa_mblist_mru_get_url), (balsa_mblist_mru_get_mailbox_from_url):
        rework balsa_mblist_mru_menu();
    * src/balsa-mblist.h: revised APIs;
    * src/balsa-index.c (move_to_activated), (bndx_add_actions),
      (bndx_popup_menu_create), (bndx_do_popup): use them;
    * src/balsa-message.c (copy_part_activated), (part_add_actions),
      (part_create_menu): ditto;
    * src/balsa-mime-widget-message.c (copy_activated),
      (bm_header_extend_popup): ditto;
    * src/message-window.c (move_to_activated), (message_window_new): ditto;
    * src/sendmsg-window.c (add_urlref_attachment): ditto.

 ChangeLog                       | 21 +++++++++
 src/balsa-index.c               | 28 ++++++------
 src/balsa-mblist.c              | 97 +++++++++++++++++++++++++++--------------
 src/balsa-mblist.h              | 18 +++++---
 src/balsa-message.c             | 26 +++++------
 src/balsa-mime-widget-message.c | 32 +++++++-------
 src/message-window.c            | 30 +++++++------
 src/sendmsg-window.c            |  4 +-
 8 files changed, 159 insertions(+), 97 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 2a8c75038..4ab975eea 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -134,6 +134,27 @@
 
        * src/sendmsg-window.c (attachments_add), (drag_data_quote):
 
+2020-06-27  Peter Bloomfield  <pbloomfield bellsouth net>
+
+       Various: Fill the move-to/copy-to menus with stateless GMenuItems,
+       so that they are rendered without radio buttons.
+
+       Instead, pass the URL as GObject data on a convenient
+       object.
+
+       * src/balsa-index.c (move_to_activated), (bndx_add_actions),
+       (bndx_popup_menu_create), (bndx_do_popup):
+       * src/balsa-mblist.c (bmbl_add_action), (balsa_mblist_mru_menu),
+       (balsa_mblist_mru_get_url),
+       (balsa_mblist_mru_get_mailbox_from_url):
+       * src/balsa-mblist.h:
+       * src/balsa-message.c (copy_part_activated), (part_add_actions),
+       (part_create_menu):
+       * src/balsa-mime-widget-message.c (copy_activated),
+       (bm_header_extend_popup):
+       * src/message-window.c (move_to_activated), (message_window_new):
+       * src/sendmsg-window.c (add_urlref_attachment):
+
 2020-06-26  Peter Bloomfield  <pbloomfield bellsouth net>
 
        Various: Fill the open-with menus with stateless GMenuItems, so
diff --git a/src/balsa-index.c b/src/balsa-index.c
index e716cb8e6..3abd16231 100644
--- a/src/balsa-index.c
+++ b/src/balsa-index.c
@@ -2032,15 +2032,18 @@ toggle_unread_activated(GSimpleAction *action,
 }
 
 static void
-move_to_change_state(GSimpleAction *action,
-                     GVariant      *parameter,
-                     gpointer       user_data)
+move_to_activated(GSimpleAction *action,
+                  GVariant      *parameter,
+                  gpointer       user_data)
 {
     BalsaIndex *bindex = user_data;
+    const gchar *action_name;
+    const gchar *url;
     LibBalsaMailbox *mailbox;
 
-    mailbox =
-        balsa_mblist_mru_get_mailbox_from_variant(parameter, GTK_WIDGET(bindex));
+    action_name = g_action_get_name(G_ACTION(action));
+    url = g_object_get_data(G_OBJECT(bindex), action_name);
+    mailbox = balsa_mblist_mru_get_mailbox_from_url(url, GTK_WIDGET(bindex));
 
     if (mailbox != NULL) {
         balsa_mblist_mru_add(&balsa_app.folder_mru, libbalsa_mailbox_get_url(mailbox));
@@ -2050,9 +2053,6 @@ move_to_change_state(GSimpleAction *action,
             balsa_index_selected_msgnos_free(bindex, selected);
         }
     }
-
-    if (GTK_IS_POPOVER(bindex->popup_widget))
-        gtk_popover_popdown((GtkPopover *) bindex->popup_widget);
 }
 
 /*
@@ -2076,8 +2076,7 @@ bndx_add_actions(BalsaIndex  *bindex,
         {"trash",            move_to_trash_activated},
         {"toggle-flagged",   toggle_flagged_activated},
         {"toggle-unread",    toggle_unread_activated},
-        {"view-source",      view_source_activated},
-        {"move-to",          libbalsa_radio_activated, "s", "''", move_to_change_state}
+        {"view-source",      view_source_activated}
     };
 
     simple = g_simple_action_group_new();
@@ -2122,7 +2121,7 @@ bndx_popup_menu_create(BalsaIndex * bindex)
     /* Toggle items */
     submenu = g_menu_new();
 
-    g_menu_append(submenu, _("_Flagged"), "toggle-flagged");
+    g_menu_append(submenu, _("_Flagged"), "toggle-lagged");
     g_menu_append(submenu, _("_Unread"),  "toggle-unread");
 
     g_menu_append_submenu(menu, _("T_oggle"), G_MENU_MODEL(submenu));
@@ -2211,13 +2210,16 @@ bndx_do_popup(BalsaIndex * index, const GdkEvent *event)
     bndx_action_set_enabled(index, "popup", "trash", any && !readonly && mailbox != balsa_app.trash);
     bndx_action_set_enabled(index, "popup", "toggle-flagged", any && !readonly);
     bndx_action_set_enabled(index, "popup", "toggle-unread", any && !readonly);
-    bndx_action_set_enabled(index, "popup", "move-to", any && !readonly);
 
     /* The move-to submenu */
     item = g_menu_item_new_from_model(G_MENU_MODEL(index->popup_menu),
                                       index->move_position);
 
-    mru_menu = balsa_mblist_mru_menu(&balsa_app.folder_mru, "move-to");
+    mru_menu = balsa_mblist_mru_menu(&balsa_app.folder_mru,
+                                     G_ACTION_MAP(gtk_widget_get_action_group(GTK_WIDGET(index),
+                                                                              "popup")),
+                                     any && !readonly, NULL,
+                                     G_CALLBACK(move_to_activated), index);
     g_menu_item_set_submenu(item, G_MENU_MODEL(mru_menu));
     g_object_unref(mru_menu);
 
diff --git a/src/balsa-mblist.c b/src/balsa-mblist.c
index 6dc22c568..f47bc87be 100644
--- a/src/balsa-mblist.c
+++ b/src/balsa-mblist.c
@@ -1689,17 +1689,63 @@ static void bmbl_mru_activated_cb(GtkTreeView * tree_view,
  * that resolves to a mailbox, labeled with the mailbox name, with a
  * last entry that pops up the whole mailbox tree.
  */
+
+static void
+bmbl_add_action(GMenu       *section,
+                const gchar *url,
+                GActionMap  *action_map,
+                gboolean     action_enabled,
+                const gchar *action_namespace,
+                const gchar *label,
+                GCallback    callback,
+                gpointer     user_data)
+{
+    gchar *action_name;
+    gchar *p;
+    GSimpleAction *action;
+
+    action_name = g_strstrip(g_strdup(url));
+
+    /* Make the action name valid. */
+    for (p = action_name; *p != '\0'; p++) {
+        if (!g_ascii_isalnum(*p))
+            *p = '-';
+    }
+
+    action = g_simple_action_new(action_name, NULL);
+    g_signal_connect(action, "activate", callback, user_data);
+    g_simple_action_set_enabled(action, action_enabled),
+    g_action_map_add_action(action_map, G_ACTION(action));
+    g_object_unref(action);
+
+    g_object_set_data_full(user_data, action_name, g_strdup(url), g_free);
+
+    if (action_namespace != NULL) {
+        gchar *prefixed_action_name;
+
+        prefixed_action_name = g_strdup_printf("%s.%s", action_namespace, action_name);
+        g_free(action_name);
+        action_name = prefixed_action_name;
+    }
+
+    g_menu_append(section, label, action_name);
+    g_free(action_name);
+}
+
 GMenu *
-balsa_mblist_mru_menu(GList ** url_list,
-                      const gchar *action)
+balsa_mblist_mru_menu(GList      **url_list,
+                      GActionMap  *action_map,
+                      gboolean     action_enabled,
+                      const gchar *action_namespace,
+                      GCallback    callback,
+                      gpointer     user_data)
 {
     GMenu *menu;
     GMenu *section;
     GList *list;
-    GMenuItem *item;
 
     g_return_val_if_fail(url_list != NULL, NULL);
-    g_return_val_if_fail(action != NULL, NULL);
+    g_return_val_if_fail(G_IS_ACTION_MAP(action_map), NULL);
 
     menu = g_menu_new();
 
@@ -1710,25 +1756,18 @@ balsa_mblist_mru_menu(GList ** url_list,
         LibBalsaMailbox *mailbox = balsa_find_mailbox_by_url(url);
 
         if (mailbox != NULL) {
-            const gchar *name = libbalsa_mailbox_get_name(mailbox);
-
-            item = g_menu_item_new(name, NULL);
-            g_menu_item_set_action_and_target(item, action, "s", url);
-            g_menu_append_item(section, item);
-            g_object_unref(item);
+            bmbl_add_action(section, url, action_map, action_enabled, action_namespace,
+                            libbalsa_mailbox_get_name(mailbox), callback, user_data);
         }
     }
 
     g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
     g_object_unref(section);
 
+    /* Other… section */
     section = g_menu_new();
-
-    item = g_menu_item_new(_("_Other…"), NULL);
-    g_menu_item_set_action_and_target(item, action, "s", "");
-    g_menu_append_item(section, item);
-    g_object_unref(item);
-
+    bmbl_add_action(section, "-", action_map, action_enabled, action_namespace,
+                    _("_Other…"), callback, user_data);
     g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
     g_object_unref(section);
 
@@ -2371,47 +2410,39 @@ bmbl_choose_mailbox(GtkWidget *widget)
 }
 
 /*
- * balsa_mblist_mru_get_url_from_variant,
- * balsa_mblist_mru_get_mailbox_from_variant:
+ * balsa_mblist_mru_get_url,
+ * balsa_mblist_mru_get_mailbox_from_url:
  *
  * Helpers for "_change_state" actions of mru_menus
  *
- * Get the url from the GVariant parameter. If it is an empty string,
+ * Get the url from the GVariant parameter. If it is "-",
  * the user selected "Other...", so we must pop up the mailbox list dialog
  * and let the user choose the mailbox. That dialog can be canceled,
  * returning a NULL mailbox, so we must be careful; the caller must be
- * prepared for the return of an empty url string or a NULL mailbox,
+ * prepared for the return of a NULL url or mailbox,
  * respectively.
  */
 
 const gchar *
-balsa_mblist_mru_get_url_from_variant(GVariant *parameter, GtkWidget *widget)
+balsa_mblist_mru_get_url(const gchar *url, GtkWidget *widget)
 {
-    const gchar *url;
-
-    url = g_variant_get_string(parameter, NULL);
-
-    if (url[0] == '\0') {
+    if (url[0] == '-' && url[1] == '\0') {
         LibBalsaMailbox *mailbox;
 
         mailbox = bmbl_choose_mailbox(widget);
 
-        if (mailbox != NULL)
-            url = libbalsa_mailbox_get_url(mailbox);
+        url = mailbox != NULL ? libbalsa_mailbox_get_url(mailbox) : NULL;
     }
 
     return url;
 }
 
 LibBalsaMailbox *
-balsa_mblist_mru_get_mailbox_from_variant(GVariant *parameter, GtkWidget *widget)
+balsa_mblist_mru_get_mailbox_from_url(const gchar *url, GtkWidget *widget)
 {
     LibBalsaMailbox *mailbox;
-    const gchar *url;
-
-    url = g_variant_get_string(parameter, NULL);
 
-    if (url[0] == '\0')
+    if (url[0] == '-' && url[1] == '\0')
         mailbox = bmbl_choose_mailbox(widget);
     else
         mailbox = balsa_find_mailbox_by_url(url);
diff --git a/src/balsa-mblist.h b/src/balsa-mblist.h
index c07318e3f..23b667582 100644
--- a/src/balsa-mblist.h
+++ b/src/balsa-mblist.h
@@ -50,19 +50,25 @@ BalsaMailboxNode *balsa_mblist_get_selected_node(BalsaMBList * mblist);
 BalsaMailboxNode *balsa_mblist_get_node_by_mailbox(BalsaMBList * mblist,
                                                    LibBalsaMailbox *
                                                    mailbox);
-GMenu *balsa_mblist_mru_menu(GList ** url_list,
-                             const gchar *action);
+
+GMenu * balsa_mblist_mru_menu(GList      **url_list,
+                              GActionMap  *action_map,
+                              gboolean     action_enabled,
+                              const gchar *action_namespace,
+                              GCallback    callback,
+                              gpointer     user_data);
 void balsa_mblist_mru_add(GList ** url_list, const gchar * url);
 void balsa_mblist_mru_drop(GList ** url_list, const gchar * url);
+const gchar     *balsa_mblist_mru_get_url             (const gchar *url,
+                                                       GtkWidget   *widget);
+LibBalsaMailbox *balsa_mblist_mru_get_mailbox_from_url(const gchar *url,
+                                                       GtkWidget   *widget);
+
 GtkWidget *balsa_mblist_mru_option_menu(GtkWindow * window, 
                                         GList ** url_list);
 void balsa_mblist_mru_option_menu_set(GtkWidget * option_menu,
                                       const gchar * url);
 const gchar *balsa_mblist_mru_option_menu_get(GtkWidget * option_menu);
-const gchar *balsa_mblist_mru_get_url_from_variant(GVariant  *parameter,
-                                                   GtkWidget *widget);
-LibBalsaMailbox *balsa_mblist_mru_get_mailbox_from_variant(GVariant  *parameter,
-                                                           GtkWidget *widget);
 
 /* BalsaMailboxNode methods */
 void balsa_mblist_mailbox_node_append(BalsaMailboxNode * root,
diff --git a/src/balsa-message.c b/src/balsa-message.c
index 2e1d79ffb..13a47f0bc 100644
--- a/src/balsa-message.c
+++ b/src/balsa-message.c
@@ -1820,23 +1820,22 @@ open_with_activated(GSimpleAction *action,
 }
 
 static void
-copy_part_change_state(GSimpleAction *action,
-                       GVariant      *parameter,
-                       gpointer       user_data)
+copy_part_activated(GSimpleAction *action,
+                    GVariant      *parameter,
+                    gpointer       user_data)
 {
     BalsaPartInfo *info = user_data;
+    const gchar *action_name;
     const gchar *url;
 
-    url = balsa_mblist_mru_get_url_from_variant(parameter, info->popup_widget);
+    action_name = g_action_get_name(G_ACTION(action));
+    url = g_object_get_data(G_OBJECT(info), action_name);
+    url = balsa_mblist_mru_get_url(url, info->popup_widget);
 
-    if (url[0] != '\0') {
+    if (url != NULL) {
         balsa_mblist_mru_add(&balsa_app.folder_mru, url);
         balsa_message_copy_part(url, info->body);
     }
-
-    g_simple_action_set_state(action, parameter);
-    if (GTK_IS_POPOVER(info->popup_widget))
-        gtk_popover_popdown((GtkPopover *) info->popup_widget);
 }
 
 static GSimpleActionGroup *
@@ -1845,8 +1844,7 @@ part_add_actions(BalsaMessage *balsa_message,
 {
     GSimpleActionGroup *simple;
     static const GActionEntry entries[] = {
-        {"save", save_activated},
-        {"copy-part", libbalsa_radio_activated, "s", "''", copy_part_change_state}
+        {"save", save_activated}
     };
 
     simple = g_simple_action_group_new();
@@ -1882,16 +1880,18 @@ part_create_menu(BalsaMessage *balsa_message, BalsaPartInfo *info)
 
     namespace = g_strdup_printf("menu-%d", ++menu_number);
     gtk_widget_insert_action_group(GTK_WIDGET(balsa_message), namespace, G_ACTION_GROUP(simple));
-    g_object_unref(simple);
 
     g_menu_append(menu, _("Save…"), "save");
 
     if (strcmp(content_type, "message/rfc822") == 0) {
         GMenu *submenu;
 
-        submenu = balsa_mblist_mru_menu(&balsa_app.folder_mru, "copy-part");
+        submenu = balsa_mblist_mru_menu(&balsa_app.folder_mru, G_ACTION_MAP(simple),
+                                        TRUE, NULL,
+                                        G_CALLBACK(copy_part_activated), info);
         g_menu_append_submenu(menu, _("_Copy to folder…"), G_MENU_MODEL(submenu));
     }
+    g_object_unref(simple);
     g_free(content_type);
 
     info->popup_widget =
diff --git a/src/balsa-mime-widget-message.c b/src/balsa-mime-widget-message.c
index 0b33c24d4..9de7f4bb9 100644
--- a/src/balsa-mime-widget-message.c
+++ b/src/balsa-mime-widget-message.c
@@ -438,15 +438,20 @@ bm_header_ctx_menu_reply(GtkWidget * menu_item,
 }
 
 static void
-copy_change_state(GSimpleAction *action,
-                  GVariant      *parameter,
-                  gpointer       user_data)
+copy_activated(GSimpleAction *action,
+               GVariant      *parameter,
+               gpointer       user_data)
 {
-    LibBalsaMessageBody *part = user_data;
-    const gchar *url =
-        balsa_mblist_mru_get_url_from_variant(parameter, part->user_data);
+    LibBalsaMessageBody *part = g_object_get_data(user_data, "part");
+    GtkWidget *widget = user_data;
+    const gchar *action_name;
+    const gchar *url;
 
-    if (url[0] != '\0') {
+    action_name = g_action_get_name(G_ACTION(action));
+    url = g_object_get_data(G_OBJECT(widget), action_name);
+    url = balsa_mblist_mru_get_url(url, widget);
+
+    if (url != NULL) {
         balsa_mblist_mru_add(&balsa_app.folder_mru, url);
         balsa_message_copy_part(url, part);
     }
@@ -457,9 +462,6 @@ bm_header_extend_popup(GtkWidget * widget, GtkMenu * menu, gpointer arg)
 {
     LibBalsaMessageBody *part = arg;
     GSimpleActionGroup *simple;
-    static const GActionEntry header_popup_entries[] = {
-        {"copy", libbalsa_radio_activated, "s", "''", copy_change_state},
-    };
     GMenu *mru_menu;
     GtkWidget *menu_item, *submenu;
     GtkWidget *separator = gtk_separator_menu_item_new();
@@ -476,17 +478,15 @@ bm_header_extend_popup(GtkWidget * widget, GtkMenu * menu, gpointer arg)
     gtk_widget_show(menu_item);
 
     simple = g_simple_action_group_new();
-    g_action_map_add_action_entries(G_ACTION_MAP(simple),
-                                    header_popup_entries,
-                                    G_N_ELEMENTS(header_popup_entries),
-                                    part);
+    g_object_set_data(G_OBJECT(part->user_data), "part", part);
+    mru_menu = balsa_mblist_mru_menu(&balsa_app.folder_mru, G_ACTION_MAP(simple),
+                                     TRUE, "header-popup",
+                                     G_CALLBACK(copy_activated), part->user_data);
     gtk_widget_insert_action_group(widget,
                                    "header-popup",
                                    G_ACTION_GROUP(simple));
     g_object_unref(simple);
 
-    mru_menu =
-        balsa_mblist_mru_menu(&balsa_app.folder_mru, "header-popup.copy");
     submenu = gtk_menu_new_from_model(G_MENU_MODEL(mru_menu));
     g_object_unref(mru_menu);
 
diff --git a/src/message-window.c b/src/message-window.c
index 39f9ca13b..bcd04bfd1 100644
--- a/src/message-window.c
+++ b/src/message-window.c
@@ -795,16 +795,22 @@ message_window_add_action_entries(GActionMap * action_map)
 }
 
 static void
-move_to_change_state(GSimpleAction *action,
-                     GVariant      *parameter,
-                     gpointer       user_data)
+move_to_activated(GSimpleAction *action,
+                  GVariant      *parameter,
+                  gpointer       user_data)
 {
-    MessageWindow *mw = user_data;
+    GtkWidget *window = user_data;
+    const gchar *action_name;
+    const gchar *url;
     LibBalsaMailbox *mailbox;
 
-    mailbox = balsa_mblist_mru_get_mailbox_from_variant(parameter, mw->window);
+    action_name = g_action_get_name(G_ACTION(action));
+    url = g_object_get_data(G_OBJECT(window), action_name);
+    mailbox = balsa_mblist_mru_get_mailbox_from_url(url, window);
 
     if (mailbox != NULL) {
+        MessageWindow *mw = g_object_get_data(G_OBJECT(window), "mw");
+
         balsa_mblist_mru_add(&balsa_app.folder_mru, libbalsa_mailbox_get_url(mailbox));
         message_window_move_message(mw, mailbox);
     }
@@ -826,9 +832,6 @@ message_window_new(LibBalsaMailbox * mailbox, guint msgno)
     const gchar resource_path[] = "/org/desktop/Balsa/message-window.ui";
     GAction *action;
     GSimpleActionGroup *simple;
-    static const GActionEntry message_window_entries[] = {
-        {"move-to", libbalsa_radio_activated, "s", "''", move_to_change_state},
-    };
     GMenu *mru_menu;
 
     if (!mailbox || !msgno)
@@ -896,17 +899,16 @@ message_window_new(LibBalsaMailbox * mailbox, guint msgno)
 
     /* Set up the "move-to" action */
     simple = g_simple_action_group_new();
-    g_action_map_add_action_entries(G_ACTION_MAP(simple),
-                                    message_window_entries,
-                                    G_N_ELEMENTS(message_window_entries),
-                                    mw);
+    g_object_set_data(G_OBJECT(mw->window), "mw", mw);
+    mru_menu = balsa_mblist_mru_menu(&balsa_app.folder_mru,
+                                     G_ACTION_MAP(simple), TRUE,
+                                     "message-window",
+                                     G_CALLBACK(move_to_activated), mw->window);
     gtk_widget_insert_action_group(GTK_WIDGET(mw->window),
                                    "message-window",
                                    G_ACTION_GROUP(simple));
     g_object_unref(simple);
 
-    mru_menu =
-        balsa_mblist_mru_menu(&balsa_app.folder_mru, "message-window.move-to");
     submenu = gtk_menu_new_from_model(G_MENU_MODEL(mru_menu));
     g_object_unref(mru_menu);
 
diff --git a/src/sendmsg-window.c b/src/sendmsg-window.c
index 0966ef6d8..77bcb4a00 100644
--- a/src/sendmsg-window.c
+++ b/src/sendmsg-window.c
@@ -1845,7 +1845,7 @@ add_urlref_attachment(BalsaSendmsg * bsmsg, const gchar *url)
     GSimpleActionGroup *simple;
     static GActionEntry attachment_entries[] = {
         {"remove", remove_attachment},
-        {"open", libbalsa_radio_activated, "s", "''", on_open_url_cb}
+        {"open", on_open_url_cb}
     };
     GMenu *menu;
     GMenu *section;
@@ -1900,7 +1900,7 @@ add_urlref_attachment(BalsaSendmsg * bsmsg, const gchar *url)
     g_object_unref(section);
 
     attach_data->popup_menu =
-        libbalsa_popup_widget_new(bsmsg->window, G_MENU_MODEL(menu), "urlref-attachment");
+        libbalsa_popup_widget_new(bsmsg->tree_view, G_MENU_MODEL(menu), "urlref-attachment");
     g_object_unref(menu);
 
     /* append to the list store */


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