[balsa/gtk4: 38/312] balsa-mime-widget-text: Port HTML popup




commit 53d19901e4293fefc7b832ed0a5bf1e3f641a765
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Thu May 14 17:31:37 2020 -0400

    balsa-mime-widget-text: Port HTML popup
    
    to GtkPopover

 src/balsa-message.c          |   1 -
 src/balsa-mime-widget-text.c | 264 ++++++++++++++++++++++++++++---------------
 2 files changed, 173 insertions(+), 92 deletions(-)
---
diff --git a/src/balsa-message.c b/src/balsa-message.c
index d6a61ae96..20e517b09 100644
--- a/src/balsa-message.c
+++ b/src/balsa-message.c
@@ -2781,7 +2781,6 @@ balsa_message_zoom(BalsaMessage * balsa_message, gint in_out)
                      GINT_TO_POINTER(zoom));
 
      libbalsa_html_zoom(GTK_WIDGET(balsa_message->current_part->mime_widget), in_out);
-
 }
 #endif /* HAVE_HTML_WIDGET */
 
diff --git a/src/balsa-mime-widget-text.c b/src/balsa-mime-widget-text.c
index 0bfd77312..83f601926 100644
--- a/src/balsa-mime-widget-text.c
+++ b/src/balsa-mime-widget-text.c
@@ -625,6 +625,10 @@ text_view_populate_popup(GtkWidget *widget, GtkMenu *menu,
     GMenu *open_menu;
     GtkWidget *submenu;
 
+    /* GtkTextView's populate-popup signal handler is supposed to check: */
+    if (!GTK_IS_MENU(menu))
+        return;
+
     gtk_widget_hide(GTK_WIDGET(menu));
     gtk_container_foreach(GTK_CONTAINER(menu),
                          (GtkCallback) gtk_widget_hide, NULL);
@@ -1115,155 +1119,228 @@ bm_widget_on_url(const gchar *url)
 }
 
 #ifdef HAVE_HTML_WIDGET
+
+/*
+ * Context menu
+ */
+
 static void
-bmwt_html_zoom_in(BalsaMessage * bm)
+zoom_in_activated(GSimpleAction *action,
+                  GVariant      *parameter,
+                  gpointer       user_data)
 {
+    GtkWidget *html = user_data;
+    BalsaMessage *bm = g_object_get_data(G_OBJECT(html), "bm");
+
     balsa_message_zoom(bm, 1);
 }
 
 static void
-bmwt_html_zoom_out(BalsaMessage * bm)
+zoom_out_activated(GSimpleAction *action,
+                   GVariant      *parameter,
+                   gpointer       user_data)
 {
+    GtkWidget *html = user_data;
+    BalsaMessage *bm = g_object_get_data(G_OBJECT(html), "bm");
+
     balsa_message_zoom(bm, -1);
 }
 
 static void
-bmwt_html_zoom_reset(BalsaMessage * bm)
+zoom_reset_activated(GSimpleAction *action,
+                     GVariant      *parameter,
+                     gpointer       user_data)
 {
+    GtkWidget *html = user_data;
+    BalsaMessage *bm = g_object_get_data(G_OBJECT(html), "bm");
+
     balsa_message_zoom(bm, 0);
 }
 
 static void
-bmwt_html_select_all_cb(GtkWidget * html)
+select_all_activated(GSimpleAction *action,
+                     GVariant      *parameter,
+                     gpointer       user_data)
 {
+    GtkWidget *html = user_data;
+
     libbalsa_html_select_all(html);
 }
 
 static void
-bmwt_html_prefer_html_changed(GtkCheckMenuItem *checkmenuitem,
-                              gpointer          user_data)
+html_open_with_change_state(GSimpleAction *action,
+                            GVariant      *parameter,
+                            gpointer       user_data)
 {
-       libbalsa_html_prefer_set_prefer_html(INTERNET_ADDRESS_LIST(user_data),
-               gtk_check_menu_item_get_active(checkmenuitem));
+    GtkWidget *html = user_data;
+    gpointer mime_body = g_object_get_data(G_OBJECT(html), "mime-body");
+    GtkPopover *popover = g_object_get_data(G_OBJECT(html), "popover");
+
+    open_with_change_state(action, parameter, mime_body);
+
+    gtk_popover_popdown(popover);
 }
 
 static void
-bmwt_html_load_images_changed(GtkCheckMenuItem *checkmenuitem,
-                              gpointer          user_data)
+prefer_html_change_state(GSimpleAction *action,
+                         GVariant      *state,
+                         gpointer       user_data)
 {
-       libbalsa_html_prefer_set_load_images(INTERNET_ADDRESS_LIST(user_data),
-               gtk_check_menu_item_get_active(checkmenuitem));
+    GtkWidget *html = user_data;
+    BalsaMessage *bm = g_object_get_data(G_OBJECT(html), "bm");
+    InternetAddressList *from;
+
+    from = libbalsa_message_get_headers(balsa_message_get_message(bm))->from;
+    libbalsa_html_prefer_set_prefer_html(from, g_variant_get_boolean(state);
+
+    g_simple_action_set_state(G_SIMPLE_ACTION(action), state);
 }
 
 static void
-bmwt_html_populate_popup_menu(BalsaMessage * bm,
-                              GtkWidget    * html,
-                              GtkMenu      * menu)
+load_images_change_state(GSimpleAction *action,
+                         GVariant      *state,
+                         gpointer       user_data)
 {
-    GtkWidget *menuitem;
+    GtkWidget *html = user_data;
+    BalsaMessage *bm = g_object_get_data(G_OBJECT(html), "bm");
     InternetAddressList *from;
-    gpointer mime_body = g_object_get_data(G_OBJECT(html), "mime-body");
-    GSimpleActionGroup *simple;
-    static const GActionEntry text_view_popup_entries[] = {
-        {"open-with", libbalsa_radio_activated, "s", "''", open_with_change_state},
-    };
-    GMenu *open_menu;
-    GtkWidget *submenu;
 
-    menuitem = gtk_menu_item_new_with_label(_("Zoom In"));
-    g_signal_connect_swapped(menuitem, "activate",
-                             G_CALLBACK(bmwt_html_zoom_in), bm);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+    from = libbalsa_message_get_headers(balsa_message_get_message(bm))->from;
+    libbalsa_html_prefer_set_load_images(from, g_variant_get_boolean(state);
 
-    menuitem = gtk_menu_item_new_with_label(_("Zoom Out"));
-    g_signal_connect_swapped(menuitem, "activate",
-                             G_CALLBACK(bmwt_html_zoom_out), bm);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+    g_simple_action_set_state(G_SIMPLE_ACTION(action), state);
+}
 
-    menuitem = gtk_menu_item_new_with_label(_("Zoom 100%"));
-    g_signal_connect_swapped(menuitem, "activate",
-                             G_CALLBACK(bmwt_html_zoom_reset), bm);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+static void
+save_activated(GSimpleAction *action,
+               GVariant      *parameter,
+               gpointer       user_data)
+{
+    GtkWidget *html = user_data;
+    gpointer mime_body = g_object_get_data(G_OBJECT(html), "mime-body");
 
-    menuitem = gtk_separator_menu_item_new();
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+    balsa_mime_widget_ctx_menu_save(html, mime_body);
+}
 
-    if (libbalsa_html_can_select(html)) {
-        menuitem = gtk_menu_item_new_with_mnemonic(_("Select _All"));
-        g_signal_connect_swapped(menuitem, "activate",
-                                 G_CALLBACK(bmwt_html_select_all_cb), html);
-        gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+static void
+print_activated(GSimpleAction *action,
+                GVariant      *parameter,
+                gpointer       user_data)
+{
+    GtkWidget *html = user_data;
 
-        menuitem = gtk_separator_menu_item_new();
-        gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-    }
+    libbalsa_html_print(html);
+}
 
-    /* Set up the "open-with" action: */
+static void
+bmwt_populate_popup_menu(BalsaMessage * bm,
+                         GtkWidget    * html,
+                         GMenu        * menu)
+{
+    GSimpleActionGroup *simple;
+    static const GActionEntry text_view_popup_entries[] = {
+        {"zoom-in", zoom_in_activated},
+        {"zoom-out", zoom_out_activated},
+        {"zoom-reset", zoom_reset_activated},
+        {"select-all", select_all_activated},
+        {"open-with", libbalsa_radio_activated, "s", "''", html_open_with_change_state},
+        {"save", save_activated},
+        {"print", print_activated},
+        {"prefer-html", NULL, NULL, "false", prefer_html_change_state},
+        {"load-images", NULL, NULL, "false", load_images_change_state}
+    };
+    GAction *print_action;
+    GMenu *open_menu;
+    GMenu *section;
+    InternetAddressList *from;
+
+    /* Set up the actions: */
     simple = g_simple_action_group_new();
     g_action_map_add_action_entries(G_ACTION_MAP(simple),
                                     text_view_popup_entries,
                                     G_N_ELEMENTS(text_view_popup_entries),
-                                    mime_body);
-    gtk_widget_insert_action_group(GTK_WIDGET(menu),
+                                    html);
+    gtk_widget_insert_action_group(GTK_WIDGET(html),
                                    "text-view-popup",
                                    G_ACTION_GROUP(simple));
+
+    print_action = g_action_map_lookup_action(G_ACTION_MAP(simple), "print");
     g_object_unref(simple);
 
+    section = g_menu_new();
+
+    g_menu_append(section, _("Zoom In"), "text-view-popup.zoom-in");
+    g_menu_append(section, _("Zoom Out"), "text-view-popup.zoom-out");
+    g_menu_append(section, _("Zoom 100%"), "text-view-popup.zoom-reset");
+
+    g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
+    g_object_unref(section);
+
+    if (libbalsa_html_can_select(html)) {
+        section = g_menu_new();
+        g_menu_append(section, _("Select _All"), "text-view-popup.select-all");
+        g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
+        g_object_unref(section);
+    }
+
+    section = g_menu_new();
+
     open_menu = g_menu_new();
     libbalsa_vfs_fill_menu_by_content_type(open_menu, "text/html",
                                            "text-view-popup.open-with");
-    submenu = gtk_menu_new_from_model(G_MENU_MODEL(open_menu));
+
+    g_menu_append_submenu(section, _("Open…"), G_MENU_MODEL(open_menu));
     g_object_unref(open_menu);
 
-    menuitem = gtk_menu_item_new_with_label(_("Open…"));
-    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+    g_menu_append(section, _("Save…"), "text-view-popup.save");
 
-    menuitem = gtk_menu_item_new_with_label(_("Save…"));
-    g_signal_connect(menuitem, "activate",
-                     G_CALLBACK(balsa_mime_widget_ctx_menu_save),
-                     mime_body);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+    g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
+    g_object_unref(section);
 
-    menuitem = gtk_separator_menu_item_new();
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+    section = g_menu_new();
 
-    menuitem = gtk_menu_item_new_with_label(_("Print…"));
-    g_signal_connect_swapped(menuitem, "activate",
-                             G_CALLBACK(libbalsa_html_print), html);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-    gtk_widget_set_sensitive(menuitem, libbalsa_html_can_print(html));
+    g_menu_append(section, _("Print…"), "text-view-popup.print");
+    g_simple_action_set_enabled(G_SIMPLE_ACTION(print_action),
+                                libbalsa_html_can_print(html));
 
-    menuitem = gtk_separator_menu_item_new();
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+    g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
+    g_object_unref(section);
 
     from = libbalsa_message_get_headers(balsa_message_get_message(bm))->from;
-    menuitem = gtk_check_menu_item_new_with_label(_("Prefer HTML for this sender"));
-    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem),
-        libbalsa_html_get_prefer_html(from));
-    gtk_widget_set_sensitive(menuitem, from != NULL);
-    g_signal_connect(menuitem, "toggled", G_CALLBACK(bmwt_html_prefer_html_changed), from);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
-    menuitem = gtk_check_menu_item_new_with_label(_("Load images for this sender"));
-    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem),
-        libbalsa_html_get_load_images(from));
-    gtk_widget_set_sensitive(menuitem, from != NULL);
-    g_signal_connect(menuitem, "toggled", G_CALLBACK(bmwt_html_load_images_changed), from);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+    section = g_menu_new();
 
-    gtk_widget_show_all(GTK_WIDGET(menu));
+    g_menu_append(section, _("Prefer HTML for this sender"), "text-view-popup.prefer-html");
+    g_simple_action_set_enabled(G_SIMPLE_ACTION(prefer_html_action),
+                                libbalsa_html_get_prefer_html(from));
+    g_simple_action_set_enabled(G_SIMPLE_ACTION(prefer_html_action), from != NULL);
+
+    g_menu_append(section, _("Load images for this sender") "text-view-popup.prefer-html");
+    g_simple_action_set_enabled(G_SIMPLE_ACTION(load_images_action),
+                                libbalsa_html_get_load_images(from));
+    g_simple_action_set_enabled(G_SIMPLE_ACTION(load_images_action), from != NULL);
+
+    g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
+    g_object_unref(section);
+
+    g_object_set_data(G_OBJECT(html), "bm", bm);
 }
 
 static gboolean
 bmwt_html_popup_context_menu(GtkWidget * html, BalsaMessage * bm)
 {
-    GtkWidget *menu;
+    GtkWidget *popover;
     const GdkEvent *event;
     GdkEvent *current_event = NULL;
 
-    menu = gtk_menu_new();
-    bmwt_html_populate_popup_menu(bm, html, GTK_MENU(menu));
+    popover = g_object_get_data(G_OBJECT(html), "popover");
+    if (popover == NULL) {
+        GMenu *menu;
+
+        menu = g_menu_new();
+        bmwt_populate_popup_menu(bm, html, menu);
+        popover = gtk_popover_new_from_model(html, G_MENU_MODEL(menu));
+        g_object_set_data(G_OBJECT(html), "popover", popover);
+    }
 
     /* In WebKit2, the context menu signal is asynchronous, so the
      * GdkEvent is no longer current; instead it is preserved and passed
@@ -1271,14 +1348,19 @@ bmwt_html_popup_context_menu(GtkWidget * html, BalsaMessage * bm)
     event = g_object_get_data(G_OBJECT(html), LIBBALSA_HTML_POPUP_EVENT);
     if (event == NULL)
         event = current_event = gtk_get_current_event();
-    if (event != NULL)
-        gtk_menu_popup_at_pointer(GTK_MENU(menu),
-                                 (GdkEvent *) event);
-    else
-        gtk_menu_popup_at_widget(GTK_MENU(menu),
-                                 GTK_WIDGET(bm),
-                                 GDK_GRAVITY_CENTER, GDK_GRAVITY_CENTER,
-                                 NULL);
+
+    if (event != NULL && gdk_event_triggers_context_menu(event)) {
+        GdkRectangle rectangle;
+
+        /* Pop up above the pointer */
+        rectangle.x = event->button.x;
+        rectangle.width = 0;
+        rectangle.y = event->button.y;
+        rectangle.height = 0;
+        gtk_popover_set_pointing_to(GTK_POPOVER(popover), &rectangle);
+    }
+    gtk_popover_popup(GTK_POPOVER(popover));
+
     if (current_event != NULL)
         gdk_event_free(current_event);
 


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