aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2013-06-11 03:21:10 +0800
committerMatthew Barnes <mbarnes@redhat.com>2013-06-11 03:47:13 +0800
commit4f7b4d81e757bfed1b42b888207a0fdf6fae8533 (patch)
tree5c159ca51db5488c7e8c8cf1ab55fd48953ecf3d
parente51e1d6e4bbd6d33a841a87b15680c824adf8988 (diff)
downloadgsoc2013-evolution-4f7b4d81e757bfed1b42b888207a0fdf6fae8533.tar
gsoc2013-evolution-4f7b4d81e757bfed1b42b888207a0fdf6fae8533.tar.gz
gsoc2013-evolution-4f7b4d81e757bfed1b42b888207a0fdf6fae8533.tar.bz2
gsoc2013-evolution-4f7b4d81e757bfed1b42b888207a0fdf6fae8533.tar.lz
gsoc2013-evolution-4f7b4d81e757bfed1b42b888207a0fdf6fae8533.tar.xz
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.txt2
-rw-r--r--modules/calendar/e-cal-shell-backend.c19
-rw-r--r--shell/e-shell-backend.c6
-rw-r--r--shell/e-shell-window.c146
-rw-r--r--shell/e-shell-window.h5
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. */