diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2013-06-11 03:21:10 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2013-06-11 03:47:13 +0800 |
commit | 4f7b4d81e757bfed1b42b888207a0fdf6fae8533 (patch) | |
tree | 5c159ca51db5488c7e8c8cf1ab55fd48953ecf3d | |
parent | e51e1d6e4bbd6d33a841a87b15680c824adf8988 (diff) | |
download | gsoc2013-evolution-4f7b4d81e757bfed1b42b888207a0fdf6fae8533.tar.gz gsoc2013-evolution-4f7b4d81e757bfed1b42b888207a0fdf6fae8533.tar.zst gsoc2013-evolution-4f7b4d81e757bfed1b42b888207a0fdf6fae8533.zip |
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
-rw-r--r-- | doc/reference/evolution-shell/evolution-shell-sections.txt | 2 | ||||
-rw-r--r-- | modules/calendar/e-cal-shell-backend.c | 19 | ||||
-rw-r--r-- | shell/e-shell-backend.c | 6 | ||||
-rw-r--r-- | shell/e-shell-window.c | 146 | ||||
-rw-r--r-- | shell/e-shell-window.h | 5 |
5 files changed, 52 insertions, 126 deletions
diff --git a/doc/reference/evolution-shell/evolution-shell-sections.txt b/doc/reference/evolution-shell/evolution-shell-sections.txt index 4c80e1e889..4e3585ee03 100644 --- a/doc/reference/evolution-shell/evolution-shell-sections.txt +++ b/doc/reference/evolution-shell/evolution-shell-sections.txt @@ -296,8 +296,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 ab8ecd550f..6a9bc1aac8 100644 --- a/modules/calendar/e-cal-shell-backend.c +++ b/modules/calendar/e-cal-shell-backend.c @@ -215,6 +215,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; @@ -222,6 +223,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)); @@ -229,11 +240,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"), @@ -250,7 +257,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 0261d8a3e2..d30e698981 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 57c94df573..0bc5a51514 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 @@ -473,12 +445,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); @@ -1520,62 +1506,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 abd940feb0..b96d2f6df5 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. */ |