[evolution/gnome-3-8] Reimplement the main toolbar's "prefer-item" feature.



commit b7331351e8de694cf3c55aaa6061d03ea2cd0f6b
Author: Matthew Barnes <mbarnes redhat com>
Date:   Mon Jun 10 15:21:10 2013 -0400

    Reimplement the main toolbar's "prefer-item" feature.
    
    This fixes a bug in the old implementation where the application could
    crash after a second shell window was created and destroyed, because a
    signal handler with the destroyed shell window as the closure was left
    connected.
    
    But moreover this simplifies the implementation by using a property
    binding plus transform function instead of juggling signal handlers,
    and also adds code comments where things get a little tricky.
    
    Removed (now unused) functions:
    
      e_shell_window_get_toolbar_new_prefer_item
      e_shell_window_set_toolbar_new_prefer_item
    
    (cherry picked from commit 4f7b4d81e757bfed1b42b888207a0fdf6fae8533)

 doc/reference/libeshell/libeshell-sections.txt |    2 -
 modules/calendar/e-cal-shell-backend.c         |   19 ++-
 shell/e-shell-backend.c                        |    6 +-
 shell/e-shell-window.c                         |  146 ++++++-----------------
 shell/e-shell-window.h                         |    5 -
 5 files changed, 52 insertions(+), 126 deletions(-)
---
diff --git a/doc/reference/libeshell/libeshell-sections.txt b/doc/reference/libeshell/libeshell-sections.txt
index 5734ef3..dc49190 100644
--- a/doc/reference/libeshell/libeshell-sections.txt
+++ b/doc/reference/libeshell/libeshell-sections.txt
@@ -344,8 +344,6 @@ e_shell_window_get_taskbar_visible
 e_shell_window_set_taskbar_visible
 e_shell_window_get_toolbar_visible
 e_shell_window_set_toolbar_visible
-e_shell_window_get_toolbar_new_prefer_item
-e_shell_window_set_toolbar_new_prefer_item
 e_shell_window_register_new_item_actions
 e_shell_window_register_new_source_actions
 e_shell_window_get_menu_bar_box
diff --git a/modules/calendar/e-cal-shell-backend.c b/modules/calendar/e-cal-shell-backend.c
index a631c75..192a79b 100644
--- a/modules/calendar/e-cal-shell-backend.c
+++ b/modules/calendar/e-cal-shell-backend.c
@@ -217,6 +217,7 @@ action_event_new_cb (GtkAction *action,
         * the view. */
        shell_view = e_shell_window_peek_shell_view (shell_window, "calendar");
        if (shell_view != NULL) {
+               EShellWindow *shell_window;
                EShellContent *shell_content;
                GnomeCalendar *gcal;
                GnomeCalendarViewType view_type;
@@ -224,6 +225,16 @@ action_event_new_cb (GtkAction *action,
 
                shell_backend = e_shell_view_get_shell_backend (shell_view);
                shell_content = e_shell_view_get_shell_content (shell_view);
+               shell_window = e_shell_view_get_shell_window (shell_view);
+
+               e_shell_backend_set_prefer_new_item (
+                       shell_backend, action_name);
+
+               /* This forces the shell window to update the "New" toolbar
+                * button menu, and the toolbar button will then update its
+                * button image to reflect the "preferred new item" we just
+                * set on the shell backend. */
+               g_object_notify (G_OBJECT (shell_window), "active-view");
 
                gcal = e_cal_shell_content_get_calendar (
                        E_CAL_SHELL_CONTENT (shell_content));
@@ -231,11 +242,7 @@ action_event_new_cb (GtkAction *action,
                view_type = gnome_calendar_get_view (gcal);
                view = gnome_calendar_get_calendar_view (gcal, view_type);
 
-               if (view) {
-                       g_object_set (
-                               G_OBJECT (shell_backend),
-                               "prefer-new-item", action_name, NULL);
-
+               if (view != NULL) {
                        e_calendar_view_new_appointment_full (
                                view,
                                g_str_equal (action_name, "event-all-day-new"),
@@ -252,7 +259,7 @@ action_event_new_cb (GtkAction *action,
        source = e_source_registry_ref_default_calendar (registry);
 
        shell_backend = e_shell_get_backend_by_name (shell, "calendar");
-       g_object_set (G_OBJECT (shell_backend), "prefer-new-item", action_name, NULL);
+       e_shell_backend_set_prefer_new_item (shell_backend, action_name);
 
        /* Use a callback function appropriate for the action. */
        if (strcmp (action_name, "event-all-day-new") == 0)
diff --git a/shell/e-shell-backend.c b/shell/e-shell-backend.c
index 0261d8a..d30e698 100644
--- a/shell/e-shell-backend.c
+++ b/shell/e-shell-backend.c
@@ -252,11 +252,6 @@ shell_backend_dispose (GObject *object)
                priv->shell_view_class = NULL;
        }
 
-       if (priv->prefer_new_item) {
-               g_free (priv->prefer_new_item);
-               priv->prefer_new_item = NULL;
-       }
-
        if (priv->notify_busy_handler_id > 0) {
                g_signal_handler_disconnect (
                        object, priv->notify_busy_handler_id);
@@ -279,6 +274,7 @@ shell_backend_finalize (GObject *object)
 
        g_free (priv->config_dir);
        g_free (priv->data_dir);
+       g_free (priv->prefer_new_item);
 
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (e_shell_backend_parent_class)->finalize (object);
diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c
index e3f383e..3ed79b4 100644
--- a/shell/e-shell-window.c
+++ b/shell/e-shell-window.c
@@ -81,68 +81,40 @@ shell_window_menubar_update_new_menu (EShellWindow *shell_window)
        gtk_widget_show (widget);
 }
 
-static void    shell_window_backend_prefer_item_changed_cb
-                                               (EShellBackend *backend,
-                                                GParamSpec *pspec,
-                                                EShellWindow *shell_window);
-
 static void
-shell_window_toolbar_update_new_menu (EShellWindow *shell_window,
+shell_window_toolbar_update_new_menu (GtkMenuToolButton *menu_tool_button,
                                       GParamSpec *pspec,
-                                      GtkMenuToolButton *menu_tool_button)
+                                      EShellWindow *shell_window)
 {
        GtkWidget *menu;
 
        /* Update the "New" menu tool button submenu. */
        menu = e_shell_window_create_new_menu (shell_window);
        gtk_menu_tool_button_set_menu (menu_tool_button, menu);
-
-       if (pspec && g_strcmp0 (pspec->name, "active-view") == 0) {
-               EShellView *shell_view;
-               EShellBackend *shell_backend;
-
-               shell_view = e_shell_window_peek_shell_view (
-                       shell_window,
-                       e_shell_window_get_active_view (shell_window));
-               g_return_if_fail (shell_view != NULL);
-
-               shell_backend = e_shell_view_get_shell_backend (shell_view);
-
-               g_signal_handlers_disconnect_by_func (
-                       shell_backend,
-                       shell_window_backend_prefer_item_changed_cb,
-                       shell_window);
-
-               g_signal_connect (
-                       shell_backend, "notify::prefer-new-item",
-                       G_CALLBACK (shell_window_backend_prefer_item_changed_cb),
-                       shell_window);
-
-               shell_window_backend_prefer_item_changed_cb (
-                       shell_backend, NULL, shell_window);
-       }
 }
 
-static void
-shell_window_backend_prefer_item_changed_cb (EShellBackend *backend,
-                                             GParamSpec *pspec,
-                                             EShellWindow *shell_window)
+static gboolean
+shell_window_active_view_to_prefer_item (GBinding *binding,
+                                         const GValue *source_value,
+                                         GValue *target_value,
+                                         gpointer user_data)
 {
-       EShellView *shell_view;
+       GObject *source_object;
+       EShell *shell;
        EShellBackend *shell_backend;
+       const gchar *active_view;
+       const gchar *prefer_item;
 
-       shell_view = e_shell_window_peek_shell_view (
-               shell_window,
-               e_shell_window_get_active_view (shell_window));
-       g_return_if_fail (shell_view != NULL);
+       active_view = g_value_get_string (source_value);
 
-       shell_backend = e_shell_view_get_shell_backend (shell_view);
-       if (shell_backend != backend)
-               return;
+       source_object = g_binding_get_source (binding);
+       shell = e_shell_window_get_shell (E_SHELL_WINDOW (source_object));
+       shell_backend = e_shell_get_backend_by_name (shell, active_view);
+       prefer_item = e_shell_backend_get_prefer_new_item (shell_backend);
 
-       e_shell_window_set_toolbar_new_prefer_item (
-               shell_window,
-               e_shell_backend_get_prefer_new_item (shell_backend));
+       g_value_set_string (target_value, prefer_item);
+
+       return TRUE;
 }
 
 static void
@@ -503,12 +475,26 @@ shell_window_construct_toolbar (EShellWindow *shell_window)
        gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, 0);
        gtk_widget_show (GTK_WIDGET (item));
 
-       g_signal_connect (
-               shell_window, "notify::active-view",
-               G_CALLBACK (shell_window_toolbar_update_new_menu),
-               GTK_MENU_TOOL_BUTTON (item));
+       /* XXX The ECalShellBackend has a hack where it forces the
+        *     EMenuToolButton to update its button image by forcing
+        *     a "notify::active-view" signal emission on the window.
+        *     This will trigger the property binding, which will set
+        *     EMenuToolButton's "prefer-item" property, which will
+        *     invoke shell_window_toolbar_update_new_menu(), which
+        *     will cause EMenuToolButton to update its button image.
+        *
+        *     It's a bit of a Rube Goldberg machine and should be
+        *     reworked, but it's just serving one (now documented)
+        *     corner case and works for now. */
+       g_object_bind_property_full (
+               shell_window, "active-view",
+               item, "prefer-item",
+               G_BINDING_SYNC_CREATE,
+               shell_window_active_view_to_prefer_item,
+               (GBindingTransformFunc) NULL,
+               NULL, (GDestroyNotify) NULL);
 
-       g_signal_connect_swapped (
+       g_signal_connect (
                item, "notify::prefer-item",
                G_CALLBACK (shell_window_toolbar_update_new_menu),
                shell_window);
@@ -1576,62 +1562,6 @@ e_shell_window_set_toolbar_visible (EShellWindow *shell_window,
 }
 
 /**
- * e_shell_window_get_toolbar_new_prefer_item:
- * @shell_window: an #EShellWindow
- *
- * Returns: name of preferred item on the New button for current view.
- *
- * Since: 3.4
- **/
-const gchar *
-e_shell_window_get_toolbar_new_prefer_item (EShellWindow *shell_window)
-{
-       GtkWidget *toolbar;
-       GtkToolItem *item;
-
-       g_return_val_if_fail (shell_window != NULL, NULL);
-       g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
-
-       toolbar = e_shell_window_get_managed_widget (shell_window, "/main-toolbar");
-       g_return_val_if_fail (toolbar != NULL, NULL);
-
-       item = gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), 0);
-       g_return_val_if_fail (item != NULL, NULL);
-       g_return_val_if_fail (E_IS_MENU_TOOL_BUTTON (item), NULL);
-
-       return e_menu_tool_button_get_prefer_item (E_MENU_TOOL_BUTTON (item));
-}
-
-/**
- * e_shell_window_set_toolbar_new_prefer_item:
- * @shell_window: an #EShellWindow
- * @prefer_item: prefer-item name to be set
- *
- * Sets prefer item on the New button for current view.
- *
- * Since: 3.4
- **/
-void
-e_shell_window_set_toolbar_new_prefer_item (EShellWindow *shell_window,
-                                            const gchar *prefer_item)
-{
-       GtkWidget *toolbar;
-       GtkToolItem *item;
-
-       g_return_if_fail (shell_window != NULL);
-       g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
-
-       toolbar = e_shell_window_get_managed_widget (shell_window, "/main-toolbar");
-       g_return_if_fail (toolbar != NULL);
-
-       item = gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), 0);
-       g_return_if_fail (item != NULL);
-       g_return_if_fail (E_IS_MENU_TOOL_BUTTON (item));
-
-       e_menu_tool_button_set_prefer_item (E_MENU_TOOL_BUTTON (item), prefer_item);
-}
-
-/**
  * e_shell_window_register_new_item_actions:
  * @shell_window: an #EShellWindow
  * @backend_name: name of an #EShellBackend
diff --git a/shell/e-shell-window.h b/shell/e-shell-window.h
index abd940f..b96d2f6 100644
--- a/shell/e-shell-window.h
+++ b/shell/e-shell-window.h
@@ -134,11 +134,6 @@ gboolean   e_shell_window_get_toolbar_visible
 void           e_shell_window_set_toolbar_visible
                                                (EShellWindow *shell_window,
                                                 gboolean toolbar_visible);
-const gchar *  e_shell_window_get_toolbar_new_prefer_item
-                                               (EShellWindow *shell_window);
-void           e_shell_window_set_toolbar_new_prefer_item
-                                               (EShellWindow *shell_window,
-                                                const gchar *prefer_item);
 
 /* These should be called from the shell backend's window_created() handler. */
 


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