[evolution] Calendar views inline text edit with Ctrl+C/V/X does not work



commit 4a101290fdb546296f7bc0a9a34ba342e741895a
Author: Milan Crha <mcrha redhat com>
Date:   Fri Jun 21 15:56:34 2013 +0200

    Calendar views inline text edit with Ctrl+C/V/X does not work
    
    The shortcuts Ctrl+C/V/X are used for whole calendar items
    copy/paste/cut, not for text when editing event details inline, either
    in a day/week view or in a list view. By tracking the is-editing property
    of respective cell editor and using it when enabling/disabling clipboard
    actions makes the respective text operations work as expected.

 calendar/gui/e-cal-list-view.c          |   51 ++++++++++++++++++++++++++
 calendar/gui/e-cal-list-view.h          |    2 +
 calendar/gui/e-calendar-view.c          |   52 ++++++++++++++++++++++++---
 calendar/gui/e-calendar-view.h          |    2 +
 calendar/gui/e-day-view.c               |   28 ++++++++++++++-
 calendar/gui/e-day-view.h               |    2 +
 calendar/gui/e-memo-table.c             |   10 +++--
 calendar/gui/e-task-table.c             |   10 +++--
 calendar/gui/e-week-view.c              |   40 +++++++++++++++++++--
 calendar/gui/e-week-view.h              |    2 +
 e-util/e-table-click-to-add.c           |   46 +++++++++++++++++++++++-
 e-util/e-table-click-to-add.h           |    1 +
 e-util/e-table-group-container.c        |   29 ++++++++++++++-
 e-util/e-table-group-container.h        |    2 +
 e-util/e-table-group-leaf.c             |   35 ++++++++++++++++++-
 e-util/e-table-group-leaf.h             |    2 +
 e-util/e-table-group.c                  |   59 +++++++++++++++++++++++++++++++
 e-util/e-table-group.h                  |    2 +
 e-util/e-table-item.c                   |   32 +++++++++++++++++
 e-util/e-table-item.h                   |    2 +
 e-util/e-table.c                        |   57 +++++++++++++++++++++++++++++-
 e-util/e-table.h                        |    1 +
 e-util/e-tree.c                         |   36 +++++++++++++++++++
 e-util/e-tree.h                         |    2 +
 modules/calendar/e-cal-shell-content.c  |   19 ++++++++++
 modules/calendar/e-cal-shell-view.c     |   31 ++++++++++++++++
 modules/calendar/e-memo-shell-content.c |   13 +++++++
 modules/calendar/e-task-shell-content.c |   13 +++++++
 28 files changed, 559 insertions(+), 22 deletions(-)
---
diff --git a/calendar/gui/e-cal-list-view.c b/calendar/gui/e-cal-list-view.c
index 94722c0..275cc0c 100644
--- a/calendar/gui/e-cal-list-view.c
+++ b/calendar/gui/e-cal-list-view.c
@@ -48,6 +48,11 @@
 #include "calendar-config.h"
 #include "misc.h"
 
+enum {
+       PROP_0,
+       PROP_IS_EDITING
+};
+
 static void      e_cal_list_view_dispose                (GObject *object);
 
 static GList    *e_cal_list_view_get_selected_events    (ECalendarView *cal_view);
@@ -68,6 +73,24 @@ static void e_cal_list_view_cursor_change_cb (ETable *etable, gint row, gpointer
 G_DEFINE_TYPE (ECalListView, e_cal_list_view, E_TYPE_CALENDAR_VIEW)
 
 static void
+e_cal_list_view_get_property (GObject *object,
+                             guint property_id,
+                             GValue *value,
+                             GParamSpec *pspec)
+{
+       ECalListView *eclv = E_CAL_LIST_VIEW (object);
+
+       switch (property_id) {
+       case PROP_IS_EDITING:
+               g_value_set_boolean (value, e_cal_list_view_is_editing (eclv));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+               break;
+       }
+}
+
+static void
 e_cal_list_view_class_init (ECalListViewClass *class)
 {
        GObjectClass *object_class;
@@ -80,12 +103,18 @@ e_cal_list_view_class_init (ECalListViewClass *class)
 
        /* Method override */
        object_class->dispose           = e_cal_list_view_dispose;
+       object_class->get_property      = e_cal_list_view_get_property;
 
        widget_class->popup_menu = e_cal_list_view_popup_menu;
 
        view_class->get_selected_events = e_cal_list_view_get_selected_events;
        view_class->get_selected_time_range = e_cal_list_view_get_selected_time_range;
        view_class->get_visible_time_range = e_cal_list_view_get_visible_time_range;
+
+       g_object_class_override_property (
+               object_class,
+               PROP_IS_EDITING,
+               "is-editing");
 }
 
 static void
@@ -147,6 +176,16 @@ e_cal_list_view_save_state (ECalListView *cal_list_view,
 }
 
 static void
+e_cal_list_view_table_editing_changed_cb (ETable *table,
+                                         GParamSpec *param,
+                                         ECalListView *eclv)
+{
+       g_return_if_fail (E_IS_CAL_LIST_VIEW (eclv));
+
+       g_object_notify (G_OBJECT (eclv), "is-editing");
+}
+
+static void
 setup_e_table (ECalListView *cal_list_view)
 {
        ECalModel *model;
@@ -300,6 +339,10 @@ setup_e_table (ECalListView *cal_list_view)
                cal_list_view->table, "cursor_change",
                G_CALLBACK (e_cal_list_view_cursor_change_cb),
                cal_list_view);
+       g_signal_connect_after (
+               cal_list_view->table, "notify::is-editing",
+               G_CALLBACK (e_cal_list_view_table_editing_changed_cb),
+               cal_list_view);
 }
 
 /**
@@ -563,3 +606,11 @@ e_cal_list_view_get_range_shown (ECalListView *cal_list_view,
        *days_shown = g_date_days_between (start_date, &end_date);
        return TRUE;
 }
+
+gboolean
+e_cal_list_view_is_editing (ECalListView *eclv)
+{
+       g_return_val_if_fail (E_IS_CAL_LIST_VIEW (eclv), FALSE);
+
+       return eclv->table && e_table_is_editing (eclv->table);
+}
diff --git a/calendar/gui/e-cal-list-view.h b/calendar/gui/e-cal-list-view.h
index e5eff47..e434033 100644
--- a/calendar/gui/e-cal-list-view.h
+++ b/calendar/gui/e-cal-list-view.h
@@ -91,6 +91,8 @@ void e_cal_list_view_save_state (ECalListView *cal_list_view, gchar *filename);
 gboolean   e_cal_list_view_get_range_shown      (ECalListView *cal_list_view, GDate *start_date,
                                                 gint *days_shown);
 
+gboolean       e_cal_list_view_is_editing      (ECalListView *eclv);
+
 G_END_DECLS
 
 #endif /* _E_CAL_LIST_VIEW_H_ */
diff --git a/calendar/gui/e-calendar-view.c b/calendar/gui/e-calendar-view.c
index 8228e68..54df73a 100644
--- a/calendar/gui/e-calendar-view.c
+++ b/calendar/gui/e-calendar-view.c
@@ -79,7 +79,8 @@ enum {
        PROP_COPY_TARGET_LIST,
        PROP_MODEL,
        PROP_PASTE_TARGET_LIST,
-       PROP_TIME_DIVISIONS
+       PROP_TIME_DIVISIONS,
+       PROP_IS_EDITING
 };
 
 /* FIXME Why are we emitting these event signals here? Can't the model just be listened to? */
@@ -313,6 +314,10 @@ calendar_view_get_property (GObject *object,
                                value, e_calendar_view_get_time_divisions (
                                E_CALENDAR_VIEW (object)));
                        return;
+
+               case PROP_IS_EDITING:
+                       g_value_set_boolean (value, e_calendar_view_is_editing (E_CALENDAR_VIEW (object)));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -398,12 +403,14 @@ calendar_view_update_actions (ESelectable *selectable,
        gboolean can_paste = FALSE;
        gboolean sources_are_editable = TRUE;
        gboolean recurring = FALSE;
+       gboolean is_editing;
        gboolean sensitive;
        const gchar *tooltip;
        gint n_selected;
        gint ii;
 
        view = E_CALENDAR_VIEW (selectable);
+       is_editing = e_calendar_view_is_editing (view);
 
        list = e_calendar_view_get_selected_events (view);
        n_selected = g_list_length (list);
@@ -434,25 +441,25 @@ calendar_view_update_actions (ESelectable *selectable,
                        target_list, clipboard_targets[ii], NULL);
 
        action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
-       sensitive = (n_selected > 0) && sources_are_editable;
+       sensitive = (n_selected > 0) && sources_are_editable && !is_editing;
        tooltip = _("Cut selected events to the clipboard");
        gtk_action_set_sensitive (action, sensitive);
        gtk_action_set_tooltip (action, tooltip);
 
        action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
-       sensitive = (n_selected > 0);
+       sensitive = (n_selected > 0) && !is_editing;
        tooltip = _("Copy selected events to the clipboard");
        gtk_action_set_sensitive (action, sensitive);
        gtk_action_set_tooltip (action, tooltip);
 
        action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
-       sensitive = sources_are_editable && can_paste;
+       sensitive = sources_are_editable && can_paste && !is_editing;
        tooltip = _("Paste events from the clipboard");
        gtk_action_set_sensitive (action, sensitive);
        gtk_action_set_tooltip (action, tooltip);
 
        action = e_focus_tracker_get_delete_selection_action (focus_tracker);
-       sensitive = (n_selected > 0) && sources_are_editable && !recurring;
+       sensitive = (n_selected > 0) && sources_are_editable && !recurring && !is_editing;
        tooltip = _("Delete selected events");
        gtk_action_set_sensitive (action, sensitive);
        gtk_action_set_tooltip (action, tooltip);
@@ -884,6 +891,16 @@ e_calendar_view_class_init (ECalendarViewClass *class)
                        30,
                        G_PARAM_READWRITE));
 
+       g_object_class_install_property (
+               object_class,
+               PROP_IS_EDITING,
+               g_param_spec_boolean (
+                       "is-editing",
+                       "Whether is in an editing mode",
+                       "Whether is in an editing mode",
+                       FALSE,
+                       G_PARAM_READABLE));
+
        signals[POPUP_EVENT] = g_signal_new (
                "popup-event",
                G_TYPE_FROM_CLASS (class),
@@ -2348,3 +2365,28 @@ is_array_index_in_bounds_func (GArray *array,
 
        return TRUE;
 }
+
+gboolean
+e_calendar_view_is_editing (ECalendarView *cal_view)
+{
+       static gboolean in = FALSE;
+       gboolean is_editing = FALSE;
+
+       g_return_val_if_fail (E_IS_CALENDAR_VIEW (cal_view), FALSE);
+
+       /* this should be called from the main thread only,
+          and each descendant overrides the property,
+          thus might cause no call recursion */
+       if (in) {
+               g_warn_if_reached ();
+               return FALSE;
+       }
+
+       in = TRUE;
+
+       g_object_get (G_OBJECT (cal_view), "is-editing", &is_editing, NULL);
+
+       in = FALSE;
+
+       return is_editing;
+}
diff --git a/calendar/gui/e-calendar-view.h b/calendar/gui/e-calendar-view.h
index 9ed1173..8e55587 100644
--- a/calendar/gui/e-calendar-view.h
+++ b/calendar/gui/e-calendar-view.h
@@ -274,6 +274,8 @@ void                draw_curved_rectangle           (cairo_t *cr,
 
 GdkColor       get_today_background            (GdkColor event_background);
 
+gboolean       e_calendar_view_is_editing      (ECalendarView *cal_view);
+
 G_END_DECLS
 
 #endif /* E_CALENDAR_VIEW_H */
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c
index 541b62a..6dae27f 100644
--- a/calendar/gui/e-day-view.c
+++ b/calendar/gui/e-day-view.c
@@ -434,7 +434,8 @@ enum {
        PROP_0,
        PROP_MARCUS_BAINS_SHOW_LINE,
        PROP_MARCUS_BAINS_DAY_VIEW_COLOR,
-       PROP_MARCUS_BAINS_TIME_BAR_COLOR
+       PROP_MARCUS_BAINS_TIME_BAR_COLOR,
+       PROP_IS_EDITING
 };
 
 G_DEFINE_TYPE (EDayView, e_day_view, E_TYPE_CALENDAR_VIEW)
@@ -755,6 +756,10 @@ day_view_get_property (GObject *object,
                                e_day_view_marcus_bains_get_time_bar_color (
                                E_DAY_VIEW (object)));
                        return;
+
+               case PROP_IS_EDITING:
+                       g_value_set_boolean (value, e_day_view_is_editing (E_DAY_VIEW (object)));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -1595,6 +1600,11 @@ e_day_view_class_init (EDayViewClass *class)
                        G_PARAM_READWRITE |
                        G_PARAM_STATIC_STRINGS));
 
+       g_object_class_override_property (
+               object_class,
+               PROP_IS_EDITING,
+               "is-editing");
+
        /* init the accessibility support for e_day_view */
        e_day_view_a11y_init ();
 }
@@ -2570,6 +2580,7 @@ e_day_view_remove_event_cb (EDayView *day_view,
        if (day_view->editing_event_num == event_num && day_view->editing_event_day == day) {
                day_view->editing_event_num = -1;
                day_view->editing_event_day = -1;
+               g_object_notify (G_OBJECT (day_view), "is-editing");
        }
 
        if (day_view->popup_event_num == event_num && day_view->popup_event_day == day) {
@@ -4920,6 +4931,7 @@ static void
 e_day_view_free_events (EDayView *day_view)
 {
        gint day;
+       gboolean did_editing = day_view->editing_event_day != -1;
 
        /* Reset all our indices. */
        day_view->editing_event_day = -1;
@@ -4935,6 +4947,9 @@ e_day_view_free_events (EDayView *day_view)
 
        for (day = 0; day < E_DAY_VIEW_MAX_DAYS; day++)
                e_day_view_free_event_array (day_view, day_view->events[day]);
+
+       if (did_editing)
+               g_object_notify (G_OBJECT (day_view), "is-editing");
 }
 
 static void
@@ -7066,6 +7081,8 @@ e_day_view_on_editing_started (EDayView *day_view,
        }
 
        g_signal_emit_by_name (day_view, "selection_changed");
+
+       g_object_notify (G_OBJECT (day_view), "is-editing");
 }
 
 static void
@@ -7259,6 +7276,8 @@ e_day_view_on_editing_stopped (EDayView *day_view,
        g_free (text);
 
        g_signal_emit_by_name (day_view, "selection_changed");
+
+       g_object_notify (G_OBJECT (day_view), "is-editing");
 }
 
 /* FIXME: It is possible that we may produce an invalid time due to daylight
@@ -8894,3 +8913,10 @@ e_day_view_get_num_events_selected (EDayView *day_view)
        return (day_view->editing_event_day != -1) ? 1 : 0;
 }
 
+gboolean
+e_day_view_is_editing (EDayView *day_view)
+{
+       g_return_val_if_fail (E_IS_DAY_VIEW (day_view), FALSE);
+
+       return day_view->editing_event_day != -1;
+}
diff --git a/calendar/gui/e-day-view.h b/calendar/gui/e-day-view.h
index b22253d..19d735d 100644
--- a/calendar/gui/e-day-view.h
+++ b/calendar/gui/e-day-view.h
@@ -564,6 +564,8 @@ void                e_day_view_ensure_rows_visible  (EDayView *day_view,
                                                 gint start_row,
                                                 gint end_row);
 
+gboolean       e_day_view_is_editing           (EDayView *day_view);
+
 G_END_DECLS
 
 #endif /* E_DAY_VIEW_H */
diff --git a/calendar/gui/e-memo-table.c b/calendar/gui/e-memo-table.c
index f229bcf..580f378 100644
--- a/calendar/gui/e-memo-table.c
+++ b/calendar/gui/e-memo-table.c
@@ -700,6 +700,7 @@ memo_table_update_actions (ESelectable *selectable,
        GSList *list, *iter;
        gboolean can_paste = FALSE;
        gboolean sources_are_editable = TRUE;
+       gboolean is_editing;
        gboolean sensitive;
        const gchar *tooltip;
        gint n_selected;
@@ -707,6 +708,7 @@ memo_table_update_actions (ESelectable *selectable,
 
        memo_table = E_MEMO_TABLE (selectable);
        n_selected = e_table_selected_count (E_TABLE (memo_table));
+       is_editing = e_table_is_editing (E_TABLE (memo_table));
 
        list = e_memo_table_get_selected (memo_table);
        for (iter = list; iter != NULL && sources_are_editable; iter = iter->next) {
@@ -723,25 +725,25 @@ memo_table_update_actions (ESelectable *selectable,
                        target_list, clipboard_targets[ii], NULL);
 
        action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
-       sensitive = (n_selected > 0) && sources_are_editable;
+       sensitive = (n_selected > 0) && sources_are_editable && !is_editing;
        tooltip = _("Cut selected memos to the clipboard");
        gtk_action_set_sensitive (action, sensitive);
        gtk_action_set_tooltip (action, tooltip);
 
        action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
-       sensitive = (n_selected > 0);
+       sensitive = (n_selected > 0) && !is_editing;
        tooltip = _("Copy selected memos to the clipboard");
        gtk_action_set_sensitive (action, sensitive);
        gtk_action_set_tooltip (action, tooltip);
 
        action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
-       sensitive = sources_are_editable && can_paste;
+       sensitive = sources_are_editable && can_paste && !is_editing;
        tooltip = _("Paste memos from the clipboard");
        gtk_action_set_sensitive (action, sensitive);
        gtk_action_set_tooltip (action, tooltip);
 
        action = e_focus_tracker_get_delete_selection_action (focus_tracker);
-       sensitive = (n_selected > 0) && sources_are_editable;
+       sensitive = (n_selected > 0) && sources_are_editable && !is_editing;
        tooltip = _("Delete selected memos");
        gtk_action_set_sensitive (action, sensitive);
        gtk_action_set_tooltip (action, tooltip);
diff --git a/calendar/gui/e-task-table.c b/calendar/gui/e-task-table.c
index 0ec834f..d16719c 100644
--- a/calendar/gui/e-task-table.c
+++ b/calendar/gui/e-task-table.c
@@ -998,6 +998,7 @@ task_table_update_actions (ESelectable *selectable,
        GSList *list, *iter;
        gboolean can_paste = FALSE;
        gboolean sources_are_editable = TRUE;
+       gboolean is_editing;
        gboolean sensitive;
        const gchar *tooltip;
        gint n_selected;
@@ -1005,6 +1006,7 @@ task_table_update_actions (ESelectable *selectable,
 
        task_table = E_TASK_TABLE (selectable);
        n_selected = e_table_selected_count (E_TABLE (task_table));
+       is_editing = e_table_is_editing (E_TABLE (task_table));
 
        list = e_task_table_get_selected (task_table);
        for (iter = list; iter != NULL && sources_are_editable; iter = iter->next) {
@@ -1021,25 +1023,25 @@ task_table_update_actions (ESelectable *selectable,
                        target_list, clipboard_targets[ii], NULL);
 
        action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
-       sensitive = (n_selected > 0) && sources_are_editable;
+       sensitive = (n_selected > 0) && sources_are_editable && !is_editing;
        tooltip = _("Cut selected tasks to the clipboard");
        gtk_action_set_sensitive (action, sensitive);
        gtk_action_set_tooltip (action, tooltip);
 
        action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
-       sensitive = (n_selected > 0);
+       sensitive = (n_selected > 0) && !is_editing;
        tooltip = _("Copy selected tasks to the clipboard");
        gtk_action_set_sensitive (action, sensitive);
        gtk_action_set_tooltip (action, tooltip);
 
        action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
-       sensitive = sources_are_editable && can_paste;
+       sensitive = sources_are_editable && can_paste && !is_editing;
        tooltip = _("Paste tasks from the clipboard");
        gtk_action_set_sensitive (action, sensitive);
        gtk_action_set_tooltip (action, tooltip);
 
        action = e_focus_tracker_get_delete_selection_action (focus_tracker);
-       sensitive = (n_selected > 0) && sources_are_editable;
+       sensitive = (n_selected > 0) && sources_are_editable && !is_editing;
        tooltip = _("Delete selected tasks");
        gtk_action_set_sensitive (action, sensitive);
        gtk_action_set_tooltip (action, tooltip);
diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c
index 8d1e881..b2bc509 100644
--- a/calendar/gui/e-week-view.c
+++ b/calendar/gui/e-week-view.c
@@ -199,7 +199,8 @@ G_DEFINE_TYPE (EWeekView, e_week_view, E_TYPE_CALENDAR_VIEW)
 enum {
        PROP_0,
        PROP_COMPRESS_WEEKEND,
-       PROP_SHOW_EVENT_END_TIMES
+       PROP_SHOW_EVENT_END_TIMES,
+       PROP_IS_EDITING
 };
 
 static gint map_left[] = {0, 1, 2, 0, 1, 2, 2};
@@ -704,6 +705,10 @@ week_view_get_property (GObject *object,
                                e_week_view_get_show_event_end_times (
                                E_WEEK_VIEW (object)));
                        return;
+
+               case PROP_IS_EDITING:
+                       g_value_set_boolean (value, e_week_view_is_editing (E_WEEK_VIEW (object)));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -1192,8 +1197,11 @@ week_view_get_selected_events (ECalendarView *cal_view)
        g_return_val_if_fail (E_IS_WEEK_VIEW (week_view), NULL);
 
        if (week_view->editing_event_num != -1) {
-               if (!is_array_index_in_bounds (week_view->events, week_view->editing_event_num))
+               if (!is_array_index_in_bounds (week_view->events, week_view->editing_event_num)) {
+                       week_view->editing_event_num = -1;
+                       g_object_notify (G_OBJECT (week_view), "is-editing");
                        return NULL;
+               }
 
                event = &g_array_index (week_view->events, EWeekViewEvent,
                                        week_view->editing_event_num);
@@ -1471,6 +1479,11 @@ e_week_view_class_init (EWeekViewClass *class)
                        G_PARAM_READWRITE |
                        G_PARAM_STATIC_STRINGS));
 
+       g_object_class_override_property (
+               object_class,
+               PROP_IS_EDITING,
+               "is-editing");
+
        /* init the accessibility support for e_week_view */
        e_week_view_a11y_init ();
 }
@@ -2445,8 +2458,10 @@ e_week_view_remove_event_cb (EWeekView *week_view,
 
        /* If we were editing this event, set editing_event_num to -1 so
         * on_editing_stopped doesn't try to update the event. */
-       if (week_view->editing_event_num == event_num)
+       if (week_view->editing_event_num == event_num) {
                week_view->editing_event_num = -1;
+               g_object_notify (G_OBJECT (week_view), "is-editing");
+       }
 
        if (week_view->popup_event_num == event_num)
                week_view->popup_event_num = -1;
@@ -2940,6 +2955,7 @@ e_week_view_free_events (EWeekView *week_view)
        EWeekViewEvent *event;
        EWeekViewEventSpan *span;
        gint event_num, span_num, num_days, day;
+       gboolean did_editing = week_view->editing_event_num != -1;
 
        /* Reset all our indices. */
        week_view->pressed_event_num = -1;
@@ -2983,6 +2999,9 @@ e_week_view_free_events (EWeekView *week_view)
        for (day = 0; day < E_WEEK_VIEW_MAX_WEEKS * 7; day++) {
                gnome_canvas_item_hide (week_view->jump_buttons[day]);
        }
+
+       if (did_editing)
+               g_object_notify (G_OBJECT (week_view), "is-editing");
 }
 
 /* This adds one event to the view, adding it to the appropriate array. */
@@ -4233,6 +4252,8 @@ e_week_view_on_editing_started (EWeekView *week_view,
        }
 
        g_signal_emit_by_name (week_view, "selection_changed");
+
+       g_object_notify (G_OBJECT (week_view), "is-editing");
 }
 
 static void
@@ -4278,8 +4299,10 @@ e_week_view_on_editing_stopped (EWeekView *week_view,
 
        /* Check that the event is still valid. */
        uid = icalcomponent_get_uid (event->comp_data->icalcomp);
-       if (!uid)
+       if (!uid) {
+               g_object_notify (G_OBJECT (week_view), "is-editing");
                return;
+       }
 
        text = NULL;
        g_object_set (span->text_item, "handle_popup", FALSE, NULL);
@@ -4431,6 +4454,8 @@ e_week_view_on_editing_stopped (EWeekView *week_view,
        g_object_unref (comp);
 
        g_signal_emit_by_name (week_view, "selection_changed");
+
+       g_object_notify (G_OBJECT (week_view), "is-editing");
 }
 
 gboolean
@@ -4925,3 +4950,10 @@ e_week_view_is_jump_button_visible (EWeekView *week_view,
        return FALSE;
 }
 
+gboolean
+e_week_view_is_editing (EWeekView *week_view)
+{
+       g_return_val_if_fail (E_IS_WEEK_VIEW (week_view), FALSE);
+
+       return week_view->editing_event_num != -1;
+}
diff --git a/calendar/gui/e-week-view.h b/calendar/gui/e-week-view.h
index 00181d1..f10967a 100644
--- a/calendar/gui/e-week-view.h
+++ b/calendar/gui/e-week-view.h
@@ -441,6 +441,8 @@ void                e_week_view_jump_to_button_item (EWeekView *week_view,
 void           e_week_view_scroll_a_step       (EWeekView *week_view,
                                                 ECalViewMoveDirection direction);
 
+gboolean       e_week_view_is_editing          (EWeekView *week_view);
+
 G_END_DECLS
 
 #endif /* E_WEEK_VIEW_H */
diff --git a/e-util/e-table-click-to-add.c b/e-util/e-table-click-to-add.c
index 8d80e19..2f36b18 100644
--- a/e-util/e-table-click-to-add.c
+++ b/e-util/e-table-click-to-add.c
@@ -60,7 +60,8 @@ enum {
        PROP_MODEL,
        PROP_MESSAGE,
        PROP_WIDTH,
-       PROP_HEIGHT
+       PROP_HEIGHT,
+       PROP_IS_EDITING
 };
 
 static void
@@ -311,6 +312,9 @@ etcta_get_property (GObject *object,
        case PROP_HEIGHT:
                g_value_set_double (value, etcta->height);
                break;
+       case PROP_IS_EDITING:
+               g_value_set_boolean (value, e_table_click_to_add_is_editing (etcta));
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
                break;
@@ -368,6 +372,16 @@ set_initial_selection (ETableClickToAdd *etcta)
 }
 
 static void
+table_click_to_add_row_is_editing_changed_cb (ETableItem *item,
+                                             GParamSpec *param,
+                                             ETableClickToAdd *etcta)
+{
+       g_return_if_fail (E_IS_TABLE_CLICK_TO_ADD (etcta));
+
+       g_object_notify (G_OBJECT (etcta), "is-editing");
+}
+
+static void
 finish_editing (ETableClickToAdd *etcta)
 {
        if (etcta->row) {
@@ -401,7 +415,13 @@ finish_editing (ETableClickToAdd *etcta)
                        etcta->row, "key_press",
                        G_CALLBACK (item_key_press), etcta);
 
+               g_signal_connect (
+                       etcta->row, "notify::is-editing",
+                       G_CALLBACK (table_click_to_add_row_is_editing_changed_cb), etcta);
+
                set_initial_selection (etcta);
+
+               g_object_notify (G_OBJECT (etcta), "is-editing");
        }
 }
 
@@ -452,9 +472,15 @@ etcta_event (GnomeCanvasItem *item,
                                etcta->row, "key_press",
                                G_CALLBACK (item_key_press), etcta);
 
+                       g_signal_connect (
+                               etcta->row, "notify::is-editing",
+                               G_CALLBACK (table_click_to_add_row_is_editing_changed_cb), etcta);
+
                        e_canvas_item_grab_focus (GNOME_CANVAS_ITEM (etcta->row), TRUE);
 
                        set_initial_selection (etcta);
+
+                       g_object_notify (G_OBJECT (etcta), "is-editing");
                }
                break;
 
@@ -588,6 +614,16 @@ e_table_click_to_add_class_init (ETableClickToAddClass *class)
                        G_PARAM_READABLE |
                        G_PARAM_LAX_VALIDATION));
 
+       g_object_class_install_property (
+               object_class,
+               PROP_IS_EDITING,
+               g_param_spec_boolean (
+                       "is-editing",
+                       "Whether is in an editing mode",
+                       "Whether is in an editing mode",
+                       FALSE,
+                       G_PARAM_READABLE));
+
        etcta_signals[CURSOR_CHANGE] = g_signal_new (
                "cursor_change",
                G_OBJECT_CLASS_TYPE (object_class),
@@ -665,3 +701,11 @@ e_table_click_to_add_commit (ETableClickToAdd *etcta)
        create_rect_and_text (etcta);
        e_canvas_item_move_absolute (etcta->text, 3, 3);
 }
+
+gboolean
+e_table_click_to_add_is_editing (ETableClickToAdd *etcta)
+{
+       g_return_val_if_fail (E_IS_TABLE_CLICK_TO_ADD (etcta), FALSE);
+
+       return etcta->row && e_table_item_is_editing (E_TABLE_ITEM (etcta->row));
+}
diff --git a/e-util/e-table-click-to-add.h b/e-util/e-table-click-to-add.h
index cd1519b..7c0c400 100644
--- a/e-util/e-table-click-to-add.h
+++ b/e-util/e-table-click-to-add.h
@@ -93,6 +93,7 @@ struct _ETableClickToAddClass {
 
 GType          e_table_click_to_add_get_type   (void) G_GNUC_CONST;
 void           e_table_click_to_add_commit     (ETableClickToAdd *etcta);
+gboolean       e_table_click_to_add_is_editing (ETableClickToAdd *etcta);
 
 G_END_DECLS
 
diff --git a/e-util/e-table-group-container.c b/e-util/e-table-group-container.c
index 72fee11..fece704 100644
--- a/e-util/e-table-group-container.c
+++ b/e-util/e-table-group-container.c
@@ -60,7 +60,8 @@ enum {
        PROP_CURSOR_MODE,
        PROP_SELECTION_MODEL,
        PROP_LENGTH_THRESHOLD,
-       PROP_UNIFORM_ROW_HEIGHT
+       PROP_UNIFORM_ROW_HEIGHT,
+       PROP_IS_EDITING
 };
 
 static EPrintable *
@@ -992,6 +993,9 @@ etgc_get_property (GObject *object,
        case PROP_UNIFORM_ROW_HEIGHT:
                g_value_set_boolean (value, etgc->uniform_row_height);
                break;
+       case PROP_IS_EDITING:
+               g_value_set_boolean (value, e_table_group_container_is_editing (etgc));
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
                break;
@@ -1148,6 +1152,11 @@ e_table_group_container_class_init (ETableGroupContainerClass *class)
                        "Minimum Width",
                        0.0, G_MAXDOUBLE, 0.0,
                        G_PARAM_READWRITE));
+
+       g_object_class_override_property (
+               object_class,
+               PROP_IS_EDITING,
+               "is-editing");
 }
 
 static void
@@ -1666,3 +1675,21 @@ etgc_get_printable (ETableGroup *etg)
 
        return printable;
 }
+
+gboolean
+e_table_group_container_is_editing (ETableGroupContainer *etgc)
+{
+       GList *list;
+
+       g_return_val_if_fail (E_IS_TABLE_GROUP_CONTAINER (etgc), FALSE);
+
+       for (list = etgc->children; list; list = g_list_next (list)) {
+               ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *) list->data;
+
+               if (e_table_group_is_editing (child_node->child)) {
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
diff --git a/e-util/e-table-group-container.h b/e-util/e-table-group-container.h
index 2f1457d..f06dc74 100644
--- a/e-util/e-table-group-container.h
+++ b/e-util/e-table-group-container.h
@@ -133,6 +133,8 @@ void                e_table_group_container_construct
                                                 ETableSortInfo *sort_info,
                                                 gint n);
 
+gboolean       e_table_group_container_is_editing (ETableGroupContainer *etgc);
+
 G_END_DECLS
 
 #endif /* _E_TABLE_GROUP_CONTAINER_H_ */
diff --git a/e-util/e-table-group-leaf.c b/e-util/e-table-group-leaf.c
index 027ba29..a052e36 100644
--- a/e-util/e-table-group-leaf.c
+++ b/e-util/e-table-group-leaf.c
@@ -55,10 +55,21 @@ enum {
        PROP_CURSOR_MODE,
        PROP_LENGTH_THRESHOLD,
        PROP_SELECTION_MODEL,
-       PROP_UNIFORM_ROW_HEIGHT
+       PROP_UNIFORM_ROW_HEIGHT,
+       PROP_IS_EDITING
 };
 
 static void
+etgl_item_is_editing_changed_cb (ETableItem *item,
+                                GParamSpec *param,
+                                ETableGroupLeaf *etgl)
+{
+       g_return_if_fail (E_IS_TABLE_GROUP_LEAF (etgl));
+
+       g_object_notify (G_OBJECT (etgl), "is-editing");
+}
+
+static void
 etgl_dispose (GObject *object)
 {
        ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (object);
@@ -98,6 +109,9 @@ etgl_dispose (GObject *object)
                                etgl->item,
                                etgl->etgl_start_drag_id);
 
+               g_signal_handlers_disconnect_by_func (etgl->item,
+                       etgl_item_is_editing_changed_cb, etgl);
+
                etgl->etgl_cursor_change_id = 0;
                etgl->etgl_cursor_activated_id = 0;
                etgl->etgl_double_click_id = 0;
@@ -354,6 +368,9 @@ etgl_realize (GnomeCanvasItem *item)
                etgl->item, "start_drag",
                G_CALLBACK (etgl_start_drag), etgl);
 
+       g_signal_connect (etgl->item, "notify::is-editing",
+               G_CALLBACK (etgl_item_is_editing_changed_cb), etgl);
+
        e_canvas_item_request_reflow (item);
 }
 
@@ -650,6 +667,10 @@ etgl_get_property (GObject *object,
                break;
        case PROP_UNIFORM_ROW_HEIGHT:
                g_value_set_boolean (value, etgl->uniform_row_height);
+               break;
+       case PROP_IS_EDITING:
+               g_value_set_boolean (value, e_table_group_leaf_is_editing (etgl));
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
                break;
@@ -804,6 +825,11 @@ e_table_group_leaf_class_init (ETableGroupLeafClass *class)
                        "Uniform row height",
                        FALSE,
                        G_PARAM_READWRITE));
+
+       g_object_class_override_property (
+               object_class,
+               PROP_IS_EDITING,
+               "is-editing");
 }
 
 static void
@@ -837,3 +863,10 @@ e_table_group_leaf_init (ETableGroupLeaf *etgl)
        e_canvas_item_set_reflow_callback (GNOME_CANVAS_ITEM (etgl), etgl_reflow);
 }
 
+gboolean
+e_table_group_leaf_is_editing (ETableGroupLeaf *etgl)
+{
+       g_return_val_if_fail (E_IS_TABLE_GROUP_LEAF (etgl), FALSE);
+
+       return etgl->item && e_table_item_is_editing (etgl->item);
+}
diff --git a/e-util/e-table-group-leaf.h b/e-util/e-table-group-leaf.h
index 8c47e2e..d9f1546 100644
--- a/e-util/e-table-group-leaf.h
+++ b/e-util/e-table-group-leaf.h
@@ -104,6 +104,8 @@ ETableGroup *       e_table_group_leaf_new          (GnomeCanvasGroup *parent,
                                                 ETableModel *model,
                                                 ETableSortInfo *sort_info);
 
+gboolean       e_table_group_leaf_is_editing   (ETableGroupLeaf *etgl);
+
 G_END_DECLS
 
 #endif /* _E_TABLE_GROUP_LEAF_H_ */
diff --git a/e-util/e-table-group.c b/e-util/e-table-group.c
index a4a23be..1c9ed2c 100644
--- a/e-util/e-table-group.c
+++ b/e-util/e-table-group.c
@@ -50,6 +50,11 @@ enum {
        LAST_SIGNAL
 };
 
+enum {
+       PROP_0,
+       PROP_IS_EDITING
+};
+
 static guint etg_signals[LAST_SIGNAL] = { 0, };
 
 static gboolean etg_get_focus (ETableGroup *table_group);
@@ -78,6 +83,24 @@ etg_dispose (GObject *object)
        G_OBJECT_CLASS (e_table_group_parent_class)->dispose (object);
 }
 
+static void
+etg_get_property (GObject *object,
+                 guint property_id,
+                 GValue *value,
+                 GParamSpec *pspec)
+{
+       ETableGroup *etg = E_TABLE_GROUP (object);
+
+       switch (property_id) {
+       case PROP_IS_EDITING:
+               g_value_set_boolean (value, e_table_group_is_editing (etg));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+               break;
+       }
+}
+
 /**
  * e_table_group_new
  * @parent: The %GnomeCanvasGroup to create a child of.
@@ -640,6 +663,7 @@ e_table_group_class_init (ETableGroupClass *class)
        GObjectClass *object_class = G_OBJECT_CLASS (class);
 
        object_class->dispose = etg_dispose;
+       object_class->get_property = etg_get_property;
 
        item_class->event = etg_event;
 
@@ -665,6 +689,16 @@ e_table_group_class_init (ETableGroupClass *class)
        class->get_mouse_over = NULL;
        class->get_cell_geometry = NULL;
 
+       g_object_class_install_property (
+               object_class,
+               PROP_IS_EDITING,
+               g_param_spec_boolean (
+                       "is-editing",
+                       "Whether is in an editing mode",
+                       "Whether is in an editing mode",
+                       FALSE,
+                       G_PARAM_READABLE));
+
        etg_signals[CURSOR_CHANGE] = g_signal_new (
                "cursor_change",
                G_OBJECT_CLASS_TYPE (object_class),
@@ -751,3 +785,28 @@ e_table_group_init (ETableGroup *table_group)
 {
        /* nothing to do */
 }
+
+gboolean
+e_table_group_is_editing (ETableGroup *table_group)
+{
+       static gboolean in = FALSE;
+       gboolean is_editing = FALSE;
+
+       g_return_val_if_fail (E_IS_TABLE_GROUP (table_group), FALSE);
+
+       /* this should be called from the main thread only,
+          and each descendant overrides the property,
+          thus might cause no call recursion */
+       if (in) {
+               g_warn_if_reached ();
+               return FALSE;
+       }
+
+       in = TRUE;
+
+       g_object_get (G_OBJECT (table_group), "is-editing", &is_editing, NULL);
+
+       in = FALSE;
+
+       return is_editing;
+}
diff --git a/e-util/e-table-group.h b/e-util/e-table-group.h
index 9854500..a1f0acb 100644
--- a/e-util/e-table-group.h
+++ b/e-util/e-table-group.h
@@ -237,6 +237,8 @@ void                e_table_group_apply_to_leafs    (ETableGroup *table_group,
                                                 ETableGroupLeafFn fn,
                                                 gpointer closure);
 
+gboolean       e_table_group_is_editing        (ETableGroup *table_group);
+
 G_END_DECLS
 
 #endif /* _E_TABLE_GROUP_H_ */
diff --git a/e-util/e-table-item.c b/e-util/e-table-item.c
index 289d26d..66477f5 100644
--- a/e-util/e-table-item.c
+++ b/e-util/e-table-item.c
@@ -100,6 +100,7 @@ enum {
        PROP_LENGTH_THRESHOLD,
        PROP_CURSOR_ROW,
        PROP_UNIFORM_ROW_HEIGHT,
+       PROP_IS_EDITING,
 
        PROP_MINIMUM_WIDTH,
        PROP_WIDTH,
@@ -1699,6 +1700,9 @@ eti_get_property (GObject *object,
        case PROP_UNIFORM_ROW_HEIGHT:
                g_value_set_boolean (value, eti->uniform_row_height);
                break;
+       case PROP_IS_EDITING:
+               g_value_set_boolean (value, e_table_item_is_editing (eti));
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
                break;
@@ -3275,6 +3279,16 @@ e_table_item_class_init (ETableItemClass *class)
                        FALSE,
                        G_PARAM_READWRITE));
 
+       g_object_class_install_property (
+               object_class,
+               PROP_IS_EDITING,
+               g_param_spec_boolean (
+                       "is-editing",
+                       "Whether is in an editing mode",
+                       "Whether is in an editing mode",
+                       FALSE,
+                       G_PARAM_READABLE));
+
        eti_signals[CURSOR_CHANGE] = g_signal_new (
                "cursor_change",
                G_OBJECT_CLASS_TYPE (object_class),
@@ -3584,6 +3598,8 @@ e_table_item_enter_edit (ETableItem *eti,
        eti->editing_row = row;
 
        eti->edit_ctx = e_cell_enter_edit (eti->cell_views[col], view_to_model_col (eti, col), col, row);
+
+       g_object_notify (G_OBJECT (eti), "is-editing");
 }
 
 /**
@@ -3618,6 +3634,8 @@ e_table_item_leave_edit (ETableItem *eti)
                eti->cell_views[col],
                view_to_model_col (eti, col),
                col, row, edit_ctx);
+
+       g_object_notify (G_OBJECT (eti), "is-editing");
 }
 
 /**
@@ -4041,3 +4059,17 @@ e_table_item_get_printable (ETableItem *item)
 
        return printable;
 }
+
+/**
+ * e_table_item_is_editing:
+ * @eti: an %ETableItem 
+ *
+ * Returns: Whether the table item is currently editing cell content.
+ **/
+gboolean
+e_table_item_is_editing (ETableItem *eti)
+{
+       g_return_val_if_fail (E_IS_TABLE_ITEM (eti), FALSE);
+
+       return eti_editing (eti);
+}
diff --git a/e-util/e-table-item.h b/e-util/e-table-item.h
index 656c46b..01e6a22 100644
--- a/e-util/e-table-item.h
+++ b/e-util/e-table-item.h
@@ -256,6 +256,8 @@ gint                e_table_item_row_diff           (ETableItem *eti,
                                                 gint start_row,
                                                 gint end_row);
 
+gboolean       e_table_item_is_editing         (ETableItem *eti);
+
 G_END_DECLS
 
 #endif /* _E_TABLE_ITEM_H_ */
diff --git a/e-util/e-table.c b/e-util/e-table.c
index 1777474..a4c809a 100644
--- a/e-util/e-table.c
+++ b/e-util/e-table.c
@@ -105,7 +105,8 @@ enum {
        PROP_HADJUSTMENT,
        PROP_VADJUSTMENT,
        PROP_HSCROLL_POLICY,
-       PROP_VSCROLL_POLICY
+       PROP_VSCROLL_POLICY,
+       PROP_IS_EDITING
 };
 
 enum {
@@ -1067,6 +1068,16 @@ et_table_rows_deleted (ETableModel *table_model,
 }
 
 static void
+group_is_editing_changed_cb (ETableClickToAdd *etcta,
+                            GParamSpec *param,
+                            ETable *table)
+{
+       g_return_if_fail (E_IS_TABLE (table));
+
+       g_object_notify (G_OBJECT (table), "is-editing");
+}
+
+static void
 et_build_groups (ETable *et)
 {
        gboolean was_grouped = et->is_grouped;
@@ -1123,6 +1134,9 @@ et_build_groups (ETable *et)
        g_signal_connect (
                et->group, "start_drag",
                G_CALLBACK (group_start_drag), et);
+       g_signal_connect (
+               et->group, "notify::is-editing",
+               G_CALLBACK (group_is_editing_changed_cb), et);
 
        if (!(et->is_grouped) && was_grouped)
                et_disconnect_model (et);
@@ -1352,6 +1366,16 @@ canvas_vbox_event (ECanvasVbox *vbox,
        return TRUE;
 }
 
+static void
+click_to_add_is_editing_changed_cb (ETableClickToAdd *etcta,
+                                   GParamSpec *param,
+                                   ETable *table)
+{
+       g_return_if_fail (E_IS_TABLE (table));
+
+       g_object_notify (G_OBJECT (table), "is-editing");
+}
+
 static gboolean
 click_to_add_event (ETableClickToAdd *etcta,
                     GdkEventKey *key,
@@ -1492,6 +1516,9 @@ e_table_setup_table (ETable *e_table,
                g_signal_connect (
                        e_table->click_to_add, "cursor_change",
                        G_CALLBACK (click_to_add_cursor_change), e_table);
+               g_signal_connect (
+                       e_table->click_to_add, "notify::is-editing",
+                       G_CALLBACK (click_to_add_is_editing_changed_cb), e_table);
        }
 }
 
@@ -2254,6 +2281,9 @@ et_get_property (GObject *object,
                else
                        g_value_set_enum (value, 0);
                break;
+       case PROP_IS_EDITING:
+               g_value_set_boolean (value, e_table_is_editing (etable));
+               break;
        default:
                break;
        }
@@ -2326,9 +2356,15 @@ et_set_property (GObject *object,
                                        etable->click_to_add);
 
                        g_signal_connect (
+                               etable->click_to_add, "event",
+                               G_CALLBACK (click_to_add_event), etable);
+                       g_signal_connect (
                                etable->click_to_add, "cursor_change",
                                G_CALLBACK (click_to_add_cursor_change),
                                etable);
+                       g_signal_connect (
+                               etable->click_to_add, "notify::is-editing",
+                               G_CALLBACK (click_to_add_is_editing_changed_cb), etable);
                } else {
                        g_object_run_dispose (G_OBJECT (etable->click_to_add));
                        etable->click_to_add = NULL;
@@ -3562,6 +3598,16 @@ e_table_class_init (ETableClass *class)
                        E_TYPE_TABLE_MODEL,
                        G_PARAM_READABLE));
 
+       g_object_class_install_property (
+               object_class,
+               PROP_IS_EDITING,
+               g_param_spec_boolean (
+                       "is-editing",
+                       "Whether is in an editing mode",
+                       "Whether is in an editing mode",
+                       FALSE,
+                       G_PARAM_READABLE));
+
        gtk_widget_class_install_style_property (
                widget_class,
                g_param_spec_int (
@@ -3610,3 +3656,12 @@ e_table_thaw_state_change (ETable *table)
                e_table_state_change (table);
        }
 }
+
+gboolean
+e_table_is_editing (ETable *table)
+{
+       g_return_val_if_fail (E_IS_TABLE (table), FALSE);
+
+       return (table->click_to_add && e_table_click_to_add_is_editing (E_TABLE_CLICK_TO_ADD 
(table->click_to_add))) ||
+              (table->group && e_table_group_is_editing (table->group));
+}
diff --git a/e-util/e-table.h b/e-util/e-table.h
index c18ca08..01e73cc 100644
--- a/e-util/e-table.h
+++ b/e-util/e-table.h
@@ -395,6 +395,7 @@ void                e_table_commit_click_to_add     (ETable *table);
 
 void           e_table_freeze_state_change     (ETable *table);
 void           e_table_thaw_state_change       (ETable *table);
+gboolean       e_table_is_editing              (ETable *table);
 
 G_END_DECLS
 
diff --git a/e-util/e-tree.c b/e-util/e-tree.c
index 8db2009..d8fb95e 100644
--- a/e-util/e-tree.c
+++ b/e-util/e-tree.c
@@ -97,6 +97,7 @@ enum {
        PROP_DRAW_FOCUS,
        PROP_ETTA,
        PROP_UNIFORM_ROW_HEIGHT,
+       PROP_IS_EDITING,
        PROP_ALWAYS_SEARCH,
        PROP_HADJUSTMENT,
        PROP_VADJUSTMENT,
@@ -259,6 +260,16 @@ G_DEFINE_TYPE_WITH_CODE (ETree, e_tree, GTK_TYPE_TABLE,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
 
 static void
+tree_item_is_editing_changed_cb (ETableItem *item,
+                                GParamSpec *param,
+                                ETree *tree)
+{
+       g_return_if_fail (E_IS_TREE (tree));
+
+       g_object_notify (G_OBJECT (tree), "is-editing");
+}
+
+static void
 et_disconnect_from_etta (ETree *tree)
 {
        if (tree->priv->table_model_change_id != 0)
@@ -1131,6 +1142,9 @@ et_build_item (ETree *tree)
        g_signal_connect (
                tree->priv->item, "start_drag",
                G_CALLBACK (item_start_drag), tree);
+       g_signal_connect (
+               tree->priv->item, "notify::is-editing",
+               G_CALLBACK (tree_item_is_editing_changed_cb), tree);
 }
 
 static void
@@ -1888,6 +1902,10 @@ et_get_property (GObject *object,
                g_value_set_boolean (value, tree->priv->uniform_row_height);
                break;
 
+       case PROP_IS_EDITING:
+               g_value_set_boolean (value, e_tree_is_editing (tree));
+               break;
+
        case PROP_ALWAYS_SEARCH:
                g_value_set_boolean (value, tree->priv->always_search);
                break;
@@ -3198,6 +3216,16 @@ e_tree_class_init (ETreeClass *class)
 
        g_object_class_install_property (
                object_class,
+               PROP_IS_EDITING,
+               g_param_spec_boolean (
+                       "is-editing",
+                       "Whether is in an editing mode",
+                       "Whether is in an editing mode",
+                       FALSE,
+                       G_PARAM_READABLE));
+
+       g_object_class_install_property (
+               object_class,
                PROP_ALWAYS_SEARCH,
                g_param_spec_boolean (
                        "always_search",
@@ -3336,3 +3364,11 @@ e_tree_thaw_state_change (ETree *tree)
                e_tree_state_change (tree);
        }
 }
+
+gboolean
+e_tree_is_editing (ETree *tree)
+{
+       g_return_val_if_fail (E_IS_TREE (tree), FALSE);
+
+       return tree->priv->item && e_table_item_is_editing (E_TABLE_ITEM (tree->priv->item));
+}
diff --git a/e-util/e-tree.h b/e-util/e-tree.h
index a443c94..5f97d54 100644
--- a/e-util/e-tree.h
+++ b/e-util/e-tree.h
@@ -268,6 +268,8 @@ void                e_tree_set_info_message         (ETree *tree,
 void           e_tree_freeze_state_change      (ETree *tree);
 void           e_tree_thaw_state_change        (ETree *tree);
 
+gboolean       e_tree_is_editing               (ETree *tree);
+
 G_END_DECLS
 
 #endif /* E_TREE_H */
diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c
index 545287d..38724ac 100644
--- a/modules/calendar/e-cal-shell-content.c
+++ b/modules/calendar/e-cal-shell-content.c
@@ -316,6 +316,16 @@ gc_get_default_time (ECalModel *model,
 }
 
 static void
+cal_shell_content_is_editing_changed_cb (gpointer cal_view_tasks_memos_table,
+                                        GParamSpec *param,
+                                        EShellView *shell_view)
+{
+       g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
+
+       e_shell_view_update_actions (shell_view);
+}
+
+static void
 cal_shell_content_constructed (GObject *object)
 {
        ECalShellContentPrivate *priv;
@@ -396,6 +406,9 @@ cal_shell_content_constructed (GObject *object)
        for (ii = 0; ii < GNOME_CAL_LAST_VIEW; ii++) {
                calendar_view = gnome_calendar_get_calendar_view (calendar, ii);
 
+               g_signal_connect (calendar_view, "notify::is-editing",
+                       G_CALLBACK (cal_shell_content_is_editing_changed_cb), shell_view);
+
                gtk_notebook_append_page (
                        GTK_NOTEBOOK (container),
                        GTK_WIDGET (calendar_view), NULL);
@@ -450,6 +463,9 @@ cal_shell_content_constructed (GObject *object)
                G_CALLBACK (e_cal_shell_view_taskpad_open_task),
                shell_view);
 
+       g_signal_connect (widget, "notify::is-editing",
+               G_CALLBACK (cal_shell_content_is_editing_changed_cb), shell_view);
+
        container = priv->vpaned;
 
        widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
@@ -492,6 +508,9 @@ cal_shell_content_constructed (GObject *object)
                G_CALLBACK (e_cal_shell_view_memopad_open_memo),
                shell_view);
 
+       g_signal_connect (widget, "notify::is-editing",
+               G_CALLBACK (cal_shell_content_is_editing_changed_cb), shell_view);
+
        /* Load the view instance. */
 
        view_instance = e_shell_view_new_view_instance (shell_view, NULL);
diff --git a/modules/calendar/e-cal-shell-view.c b/modules/calendar/e-cal-shell-view.c
index 39f1472..bacf4f4 100644
--- a/modules/calendar/e-cal-shell-view.c
+++ b/modules/calendar/e-cal-shell-view.c
@@ -340,6 +340,9 @@ cal_shell_view_update_actions (EShellView *shell_view)
        ESource *source;
        ESourceRegistry *registry;
        GnomeCalendar *calendar;
+       ECalendarView *cal_view;
+       EMemoTable *memo_table;
+       ETaskTable *task_table;
        ECalModel *model;
        GtkAction *action;
        const gchar *model_sexp;
@@ -382,6 +385,9 @@ cal_shell_view_update_actions (EShellView *shell_view)
 
        cal_shell_content = priv->cal_shell_content;
        calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+       cal_view = gnome_calendar_get_calendar_view (calendar, gnome_calendar_get_view (calendar));
+       memo_table = e_cal_shell_content_get_memo_table (cal_shell_content);
+       task_table = e_cal_shell_content_get_task_table (cal_shell_content);
        model = gnome_calendar_get_model (calendar);
        model_sexp = e_cal_model_get_search_query (model);
        is_searching = model_sexp && *model_sexp &&
@@ -536,6 +542,31 @@ cal_shell_view_update_actions (EShellView *shell_view)
 
        action = ACTION (EVENT_MEETING_NEW);
        gtk_action_set_visible (action, has_mail_identity);
+
+       if ((cal_view && e_calendar_view_is_editing (cal_view)) ||
+           e_table_is_editing (E_TABLE (memo_table)) ||
+           e_table_is_editing (E_TABLE (task_table))) {
+               EFocusTracker *focus_tracker;
+
+               /* disable all clipboard actions, if any of the views is in editing mode */
+               focus_tracker = e_shell_window_get_focus_tracker (shell_window);
+
+               action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
+               if (action)
+                       gtk_action_set_sensitive (action, FALSE);
+
+               action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
+               if (action)
+                       gtk_action_set_sensitive (action, FALSE);
+
+               action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
+               if (action)
+                       gtk_action_set_sensitive (action, FALSE);
+
+               action = e_focus_tracker_get_delete_selection_action (focus_tracker);
+               if (action)
+                       gtk_action_set_sensitive (action, FALSE);
+       }
 }
 
 static void
diff --git a/modules/calendar/e-memo-shell-content.c b/modules/calendar/e-memo-shell-content.c
index abb1ada..ded7e8a 100644
--- a/modules/calendar/e-memo-shell-content.c
+++ b/modules/calendar/e-memo-shell-content.c
@@ -300,6 +300,16 @@ memo_shell_content_restore_state_cb (EShellWindow *shell_window,
                G_SETTINGS_BIND_DEFAULT);
 }
 
+static void
+memo_shell_content_is_editing_changed_cb (EMemoTable *memo_table,
+                                         GParamSpec *param,
+                                         EShellView *shell_view)
+{
+       g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
+
+       e_shell_view_update_actions (shell_view);
+}
+
 static GtkOrientation
 memo_shell_content_get_orientation (EMemoShellContent *memo_shell_content)
 {
@@ -542,6 +552,9 @@ memo_shell_content_constructed (GObject *object)
                G_CALLBACK (memo_shell_content_selection_change_cb),
                object);
 
+       g_signal_connect (priv->memo_table, "notify::is-editing",
+               G_CALLBACK (memo_shell_content_is_editing_changed_cb), shell_view);
+
        g_signal_connect_swapped (
                priv->memo_model, "model-row-changed",
                G_CALLBACK (memo_shell_content_model_row_changed_cb),
diff --git a/modules/calendar/e-task-shell-content.c b/modules/calendar/e-task-shell-content.c
index 07d11a4..7bfb5b7 100644
--- a/modules/calendar/e-task-shell-content.c
+++ b/modules/calendar/e-task-shell-content.c
@@ -300,6 +300,16 @@ task_shell_content_restore_state_cb (EShellWindow *shell_window,
        g_object_unref (settings);
 }
 
+static void
+task_shell_content_is_editing_changed_cb (ETaskTable *task_table,
+                                         GParamSpec *param,
+                                         EShellView *shell_view)
+{
+       g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
+
+       e_shell_view_update_actions (shell_view);
+}
+
 static GtkOrientation
 task_shell_content_get_orientation (ETaskShellContent *task_shell_content)
 {
@@ -542,6 +552,9 @@ task_shell_content_constructed (GObject *object)
                G_CALLBACK (task_shell_content_selection_change_cb),
                object);
 
+       g_signal_connect (priv->task_table, "notify::is-editing",
+               G_CALLBACK (task_shell_content_is_editing_changed_cb), shell_view);
+
        g_signal_connect_swapped (
                priv->task_model, "model-row-changed",
                G_CALLBACK (task_shell_content_model_row_changed_cb),



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