[planner: 25/61] usage-tree: Port from GtkItemFactory to GtkUIManager




commit 15bf812403c75bdc5907ff9a1ee6bb42ddb3cfe5
Author: Mart Raudsepp <leio gentoo org>
Date:   Sat Dec 26 01:19:55 2020 +0200

    usage-tree: Port from GtkItemFactory to GtkUIManager
    
    GtkItemFactory doesn't exist in GTK3, while GtkUIManager exists in both
    GTK2 and GTK3, so port to the latter for now as an iterative step, despite
    GtkUIManager itself being deprecated in early GTK3.
    
    The resulting behaviour in the resource usage tabs context menu should
    match exactly to what was before with GtkItemFactory, except during the
    port I took the liberty of solving accelerator key clashes in the menu
    items.

 src/planner-usage-tree.c | 223 +++++++++++++++++++++--------------------------
 1 file changed, 98 insertions(+), 125 deletions(-)
---
diff --git a/src/planner-usage-tree.c b/src/planner-usage-tree.c
index 2e0736d8..12545bc3 100644
--- a/src/planner-usage-tree.c
+++ b/src/planner-usage-tree.c
@@ -35,6 +35,7 @@
 #include "planner-resource-dialog.h"
 #include "planner-usage-tree.h"
 #include "planner-usage-model.h"
+#include "planner-util.h"
 
 enum {
         SELECTION_CHANGED,
@@ -49,26 +50,12 @@ struct _PlannerUsageTreePriv {
         GHashTable     *task_dialogs;
         GHashTable     *resource_dialogs;
 
-        GtkItemFactory *popup_factory;
+        GtkUIManager   *popup_ui_manager;
 };
 
 static void     usage_tree_class_init                   (PlannerUsageTreeClass *klass);
 static void     usage_tree_init                         (PlannerUsageTree      *tree);
 static void     usage_tree_finalize                     (GObject                *object);
-static void     usage_tree_popup_edit_resource_cb       (gpointer                callback_data,
-                                                         guint                   action,
-                                                         GtkWidget              *widget);
-static void     usage_tree_popup_edit_task_cb           (gpointer                callback_data,
-                                                         guint                   action,
-                                                         GtkWidget              *widget);
-static void     usage_tree_popup_expand_all_cb          (gpointer                callback_data,
-                                                         guint                   action,
-                                                         GtkWidget              *widget);
-static void     usage_tree_popup_collapse_all_cb        (gpointer                callback_data,
-                                                         guint                   action,
-                                                         GtkWidget              *widget);
-static char *   usage_tree_item_factory_trans           (const char             *path,
-                                                         gpointer                data);
 static void     usage_tree_tree_view_popup_menu         (GtkWidget              *widget,
                                                          PlannerUsageTree      *tree);
 static gboolean usage_tree_tree_view_button_press_event (GtkTreeView            *tree_view,
@@ -83,35 +70,48 @@ static gboolean usage_tree_drag_drop_cb                 (GtkWidget
                                                          gint                    x,
                                                          gint                    y,
                                                          guint                   time);
+static void     usage_tree_popup_edit_resource_cb       (GtkAction *action,
+                                                         gpointer   callback_data);
+static void     usage_tree_popup_edit_task_cb           (GtkAction *action,
+                                                         gpointer   callback_data);
+static void     usage_tree_popup_expand_all_cb          (GtkAction *action,
+                                                         gpointer   callback_data);
+static void     usage_tree_popup_collapse_all_cb        (GtkAction *action,
+                                                         gpointer   callback_data);
 
 
 static GtkTreeViewClass *parent_class = NULL;
 static guint signals[LAST_SIGNAL];
 
-#define GIF_CB(x) ((GtkItemFactoryCallback)(x))
-
-enum {
-        POPUP_NONE,
-        POPUP_REDIT,
-        POPUP_TEDIT,
-        POPUP_EXPAND,
-        POPUP_COLLAPSE
+static GtkActionEntry popup_menu_entries[] = {
+        { "EditResource", NULL,
+          N_("Edit _resource..."), NULL, NULL,
+          G_CALLBACK (usage_tree_popup_edit_resource_cb)
+        },
+        { "EditTask", NULL,
+          N_("_Edit task..."), NULL, NULL,
+          G_CALLBACK (usage_tree_popup_edit_task_cb)
+        },
+        { "ExpandResources", NULL,
+          N_("E_xpand all resources"), NULL, NULL,
+          G_CALLBACK (usage_tree_popup_expand_all_cb)
+        },
+        { "CollapseResources", NULL,
+          N_("_Collapse all resources"), NULL, NULL,
+          G_CALLBACK (usage_tree_popup_collapse_all_cb)
+        },
 };
 
-static GtkItemFactoryEntry popup_menu_items[] = {
-        {N_("/_Edit resource..."), NULL,
-         GIF_CB (usage_tree_popup_edit_resource_cb), POPUP_REDIT, "<Item>",
-         NULL},
-        {N_("/_Edit task..."), NULL, GIF_CB (usage_tree_popup_edit_task_cb),
-         POPUP_TEDIT, "<Item>", NULL},
-        {"/sep1", NULL, 0, POPUP_NONE, "<Separator>"},
-        {N_("/_Expand all resources"), NULL,
-         GIF_CB (usage_tree_popup_expand_all_cb), POPUP_EXPAND, "<Item>",
-         NULL},
-        {N_("/_Collapse all resources"), NULL,
-         GIF_CB (usage_tree_popup_collapse_all_cb), POPUP_COLLAPSE, "<Item>",
-         NULL},
-};
+static const char *popup_menu =
+"<ui>"
+        "<popup name='UsageTreePopup'>"
+                "<menuitem action='EditResource'/>"
+                "<menuitem action='EditTask'/>"
+                "<separator/>"
+                "<menuitem action='ExpandResources'/>"
+                "<menuitem action='CollapseResources'/>"
+        "</popup>"
+"</ui>";
 
 GType
 planner_usage_tree_get_type (void)
@@ -176,25 +176,35 @@ static void
 usage_tree_init (PlannerUsageTree *tree)
 {
         PlannerUsageTreePriv *priv;
+        GtkActionGroup       *action_group;
+        GError               *error;
 
         priv = g_new0 (PlannerUsageTreePriv, 1);
         tree->priv = priv;
 
-       gtk_tree_view_set_enable_search (GTK_TREE_VIEW (tree), FALSE);
-
-        priv->popup_factory = gtk_item_factory_new (GTK_TYPE_MENU,
-                                                    "<main>", NULL);
-        gtk_item_factory_set_translate_func (priv->popup_factory,
-                                             usage_tree_item_factory_trans,
-                                             NULL, NULL);
-        gtk_item_factory_create_items (priv->popup_factory,
-                                       G_N_ELEMENTS (popup_menu_items),
-                                       popup_menu_items, tree);
-
-       g_signal_connect (tree,
-                         "drag_drop",
-                         G_CALLBACK (usage_tree_drag_drop_cb),
-                         NULL);
+        gtk_tree_view_set_enable_search (GTK_TREE_VIEW (tree), FALSE);
+
+        action_group = gtk_action_group_new ("UsageTreePopupActions");
+        gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
+        gtk_action_group_add_actions (action_group,
+                                      popup_menu_entries,
+                                      G_N_ELEMENTS (popup_menu_entries),
+                                      tree);
+
+        priv->popup_ui_manager = gtk_ui_manager_new ();
+        gtk_ui_manager_insert_action_group (priv->popup_ui_manager, action_group, 0);
+
+        error = NULL;
+        if (!gtk_ui_manager_add_ui_from_string (priv->popup_ui_manager, popup_menu, -1, &error)) {
+                g_critical ("Building task popup menu failed: %s", error->message);
+                g_error_free (error);
+                g_abort ();
+        }
+
+        g_signal_connect (tree,
+                          "drag_drop",
+                          G_CALLBACK (usage_tree_drag_drop_cb),
+                          NULL);
 }
 
 static void
@@ -205,7 +215,8 @@ usage_tree_finalize (GObject *object)
 
         tree = PLANNER_USAGE_TREE (object);
 
-       priv = tree->priv;
+        priv = tree->priv;
+        g_clear_object (&priv->popup_ui_manager);
         g_free (priv);
 
        if (G_OBJECT_CLASS (parent_class)->finalize) {
@@ -385,22 +396,22 @@ planner_usage_tree_new (PlannerWindow      *main_window,
 
 /*For the popup menu, and associated actions */
 static void
-usage_tree_popup_edit_resource_cb (gpointer callback_data,
-                                    guint action, GtkWidget *widget)
+usage_tree_popup_edit_resource_cb (GtkAction *action,
+                                   gpointer   callback_data)
 {
         planner_usage_tree_edit_resource (callback_data);
 }
 
 static void
-usage_tree_popup_edit_task_cb (gpointer callback_data,
-                                guint action, GtkWidget *widget)
+usage_tree_popup_edit_task_cb (GtkAction *action,
+                               gpointer   callback_data)
 {
         planner_usage_tree_edit_task (callback_data);
 }
 
 static void
-usage_tree_popup_expand_all_cb (gpointer callback_data,
-                                 guint action, GtkWidget *widget)
+usage_tree_popup_expand_all_cb (GtkAction *action,
+                                gpointer   callback_data)
 {
         g_signal_emit (callback_data, signals[EXPAND_ALL], 0);
 }
@@ -422,9 +433,8 @@ planner_usage_tree_collapse_all (PlannerUsageTree *tree)
 }
 
 static void
-usage_tree_popup_collapse_all_cb (gpointer   callback_data,
-                                   guint      action,
-                                  GtkWidget *widget)
+usage_tree_popup_collapse_all_cb (GtkAction *action,
+                                  gpointer   callback_data)
 {
         g_signal_emit (callback_data, signals[COLLAPSE_ALL], 0);
 }
@@ -543,41 +553,10 @@ static void
 usage_tree_tree_view_popup_menu (GtkWidget         *widget,
                                   PlannerUsageTree *tree)
 {
-       GtkTreeView       *tv;
-       GtkTreePath       *path;
-       GtkTreeViewColumn *column;
-       GdkRectangle       rect;
-       gint               x, y;
-
-       tv = GTK_TREE_VIEW (tree);
-
-       gtk_tree_view_get_cursor (tv, &path, &column);
-       gtk_tree_view_get_cell_area (tv,
-                                    path,
-                                    column,
-                                    &rect);
-
-       x = rect.x;
-       y = rect.y;
-
-       /* Note: this is not perfect, but good enough for now. */
-       gdk_window_get_root_origin (GTK_WIDGET (tree)->window, &x, &y);
-       rect.x += x;
-       rect.y += y;
-
-       gtk_widget_translate_coordinates (GTK_WIDGET (tree),
-                                         gtk_widget_get_toplevel (GTK_WIDGET (tree)),
-                                         rect.x, rect.y,
-                                         &x, &y);
-
-       /* Offset so it's not overlapping the cell. */
-       rect.x = x + 20;
-       rect.y = y + 20;
-
-       gtk_item_factory_popup (tree->priv->popup_factory,
-                               rect.x, rect.y,
-                               0,
-                               gtk_get_current_event_time ());
+        gtk_menu_popup (GTK_MENU (gtk_ui_manager_get_widget (tree->priv->popup_ui_manager, 
"/UsageTreePopup")),
+                        NULL, NULL,
+                        planner_util_menu_position_on_current_cell, GTK_TREE_VIEW (tree),
+                        0, gtk_get_current_event_time ());
 }
 
 static gboolean
@@ -589,22 +568,22 @@ usage_tree_tree_view_button_press_event (GtkTreeView       *tree_view,
         GtkTreeView           *tv;
         PlannerUsageTreePriv *priv;
         PlannerUsageModel    *model;
-        GtkItemFactory        *factory;
+        GtkUIManager         *popup_ui_manager;
 
         tv = GTK_TREE_VIEW (tree);
         priv = tree->priv;
 
-        factory = priv->popup_factory;
+        popup_ui_manager = priv->popup_ui_manager;
         model = PLANNER_USAGE_MODEL (gtk_tree_view_get_model (tv));
 
         if (event->button == 3) {
                 gtk_widget_grab_focus (GTK_WIDGET (tree));
-                gtk_widget_set_sensitive
-                        (gtk_item_factory_get_widget_by_action
-                         (factory, POPUP_EXPAND), TRUE);
-                gtk_widget_set_sensitive
-                        (gtk_item_factory_get_widget_by_action
-                         (factory, POPUP_COLLAPSE), TRUE);
+                gtk_action_set_sensitive
+                        (gtk_ui_manager_get_action
+                         (popup_ui_manager, "/UsageTreePopup/ExpandResources"), TRUE);
+                gtk_action_set_sensitive
+                        (gtk_ui_manager_get_action
+                         (popup_ui_manager, "/UsageTreePopup/CollapseResources"), TRUE);
 
                 if (gtk_tree_view_get_path_at_pos
                     (tv, event->x, event->y, &path, NULL, NULL, NULL)) {
@@ -614,35 +593,29 @@ usage_tree_tree_view_button_press_event (GtkTreeView       *tree_view,
                                 (gtk_tree_view_get_selection (tv), path);
                         if (planner_usage_model_path_is_assignment
                             (model, path)) {
-                                gtk_widget_set_sensitive
-                                        (gtk_item_factory_get_widget_by_action
-                                         (factory, POPUP_REDIT), TRUE);
-                                gtk_widget_set_sensitive
-                                        (gtk_item_factory_get_widget_by_action
-                                         (factory, POPUP_TEDIT), TRUE);
+                                gtk_action_set_sensitive
+                                        (gtk_ui_manager_get_action
+                                         (popup_ui_manager, "/UsageTreePopup/EditResource"), TRUE);
+                                gtk_action_set_sensitive
+                                        (gtk_ui_manager_get_action
+                                         (popup_ui_manager, "/UsageTreePopup/EditTask"), TRUE);
                         } else {
-                                gtk_widget_set_sensitive
-                                        (gtk_item_factory_get_widget_by_action
-                                         (factory, POPUP_REDIT), TRUE);
-                                gtk_widget_set_sensitive
-                                        (gtk_item_factory_get_widget_by_action
-                                         (factory, POPUP_TEDIT), FALSE);
+                                gtk_action_set_sensitive
+                                        (gtk_ui_manager_get_action
+                                         (popup_ui_manager, "/UsageTreePopup/EditResource"), TRUE);
+                                gtk_action_set_sensitive
+                                        (gtk_ui_manager_get_action
+                                         (popup_ui_manager, "/UsageTreePopup/EditTask"), FALSE);
                         }
                         gtk_tree_path_free (path);
                 }
-                gtk_item_factory_popup (factory, event->x_root, event->y_root,
-                                        event->button, event->time);
+                gtk_menu_popup (GTK_MENU (gtk_ui_manager_get_widget (popup_ui_manager, "/UsageTreePopup")),
+                                NULL, NULL, NULL, NULL, event->button, event->time);
                 return TRUE;
         }
         return FALSE;
 }
 
-static char *
-usage_tree_item_factory_trans (const char *path, gpointer data)
-{
-        return _((gchar *) path);
-}
-
 static void
 usage_tree_row_inserted (GtkTreeModel *model,
                           GtkTreePath  *path,


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