diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2009-12-08 00:31:17 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2009-12-26 04:42:17 +0800 |
commit | abc0e4c694fb3d9624e890384880def730769fa0 (patch) | |
tree | 8d411f90f4edb0859ffe0b260c85e02e7d273088 /calendar/gui/e-calendar-table.c | |
parent | 83dc7625983470bff4ce8b9070fbc23c3370c472 (diff) | |
download | gsoc2013-evolution-abc0e4c694fb3d9624e890384880def730769fa0.tar gsoc2013-evolution-abc0e4c694fb3d9624e890384880def730769fa0.tar.gz gsoc2013-evolution-abc0e4c694fb3d9624e890384880def730769fa0.tar.bz2 gsoc2013-evolution-abc0e4c694fb3d9624e890384880def730769fa0.tar.lz gsoc2013-evolution-abc0e4c694fb3d9624e890384880def730769fa0.tar.xz gsoc2013-evolution-abc0e4c694fb3d9624e890384880def730769fa0.tar.zst gsoc2013-evolution-abc0e4c694fb3d9624e890384880def730769fa0.zip |
Introduce ESelectable and EFocusTracker.
EFocusTracker tracks the input focus within a window and helps keep
the sensitivity of "selectable" actions in the main menu up-to-date.
Selectable actions include Cut, Copy, Paste, Select All and Delete.
EFocusTracker has built-in support for widgets that implement the
GtkEditable interface such as GtkEntry and GtkTextView. It also
supports custom widgets that implement the ESelectable interface,
which is a subset of GtkEditable and can apply to anything that
displays selectable content (esp. tree views and ETables).
This commit integrates EFocusTracker with EShellWindow, CompEditor,
EMsgComposer, and ESignatureManager.
It also bumps the GtkHTML requirement to 2.29.5 to utilize the new
GtkhtmlEditor:html constructor property.
Diffstat (limited to 'calendar/gui/e-calendar-table.c')
-rw-r--r-- | calendar/gui/e-calendar-table.c | 540 |
1 files changed, 310 insertions, 230 deletions
diff --git a/calendar/gui/e-calendar-table.c b/calendar/gui/e-calendar-table.c index a1495fb005..9ac534e333 100644 --- a/calendar/gui/e-calendar-table.c +++ b/calendar/gui/e-calendar-table.c @@ -37,6 +37,7 @@ #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> #include <misc/e-gui-utils.h> +#include <misc/e-selectable.h> #include <table/e-cell-checkbox.h> #include <table/e-cell-toggle.h> #include <table/e-cell-text.h> @@ -248,6 +249,32 @@ calendar_table_model_cal_view_done_cb (ECalendarTable *cal_table, calendar_table_emit_status_message (cal_table, NULL, -1.0); } +/* Deletes all of the selected components in the table */ +static void +delete_selected_components (ECalendarTable *cal_table) +{ + GSList *objs, *l; + const gchar *status_message; + + objs = e_calendar_table_get_selected (cal_table); + + status_message = _("Deleting selected objects"); + calendar_table_emit_status_message (cal_table, status_message, -1.0); + + for (l = objs; l; l = l->next) { + ECalModelComponent *comp_data = (ECalModelComponent *) l->data; + GError *error = NULL; + + e_cal_remove_object (comp_data->client, + icalcomponent_get_uid (comp_data->icalcomp), &error); + delete_error_dialog (error, E_CAL_COMPONENT_TODO); + g_clear_error (&error); + } + + calendar_table_emit_status_message (cal_table, NULL, -1.0); + + g_slist_free (objs); +} static void calendar_table_set_model (ECalendarTable *cal_table, ECalModel *model) @@ -846,6 +873,270 @@ calendar_table_right_click (ETable *table, } static void +calendar_table_update_actions (ESelectable *selectable, + EFocusTracker *focus_tracker, + GdkAtom *clipboard_targets, + gint n_clipboard_targets) +{ + ECalendarTable *cal_table; + GtkAction *action; + GSList *list, *iter; + gboolean sources_are_editable = TRUE; + gboolean clipboard_has_calendar; + gboolean sensitive; + const gchar *tooltip; + gint n_selected; + + cal_table = E_CALENDAR_TABLE (selectable); + n_selected = e_table_selected_count (E_TABLE (cal_table)); + + list = e_calendar_table_get_selected (cal_table); + for (iter = list; iter != NULL; iter = iter->next) { + ECalModelComponent *comp_data = iter->data; + gboolean read_only; + + e_cal_is_read_only (comp_data->client, &read_only, NULL); + sources_are_editable &= !read_only; + } + g_slist_free (list); + + clipboard_has_calendar = (clipboard_targets != NULL) && + e_targets_include_calendar ( + clipboard_targets, n_clipboard_targets); + + action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); + sensitive = (n_selected > 0) && sources_are_editable; + 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); + 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 && clipboard_has_calendar; + tooltip = _("Paste tasks from the clipboard"); + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, tooltip); + + action = e_focus_tracker_get_select_all_action (focus_tracker); + sensitive = TRUE; + tooltip = _("Select all visible tasks"); + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, tooltip); +} + +static void +calendar_table_cut_clipboard (ESelectable *selectable) +{ + ECalendarTable *cal_table; + + cal_table = E_CALENDAR_TABLE (selectable); + + e_selectable_copy_clipboard (selectable); + delete_selected_components (cal_table); +} + +/* Helper for calendar_table_copy_clipboard() */ +static void +copy_row_cb (gint model_row, gpointer data) +{ + ECalendarTable *cal_table; + ECalModelComponent *comp_data; + ECalModel *model; + gchar *comp_str; + icalcomponent *child; + + cal_table = E_CALENDAR_TABLE (data); + + g_return_if_fail (cal_table->tmp_vcal != NULL); + + model = e_calendar_table_get_model (cal_table); + comp_data = e_cal_model_get_component_at (model, model_row); + if (!comp_data) + return; + + /* Add timezones to the VCALENDAR component. */ + e_cal_util_add_timezones_from_component ( + cal_table->tmp_vcal, comp_data->icalcomp); + + /* Add the new component to the VCALENDAR component. */ + comp_str = icalcomponent_as_ical_string_r (comp_data->icalcomp); + child = icalparser_parse_string (comp_str); + if (child) { + icalcomponent_add_component ( + cal_table->tmp_vcal, + icalcomponent_new_clone (child)); + icalcomponent_free (child); + } + g_free (comp_str); +} + +static void +calendar_table_copy_clipboard (ESelectable *selectable) +{ + ECalendarTable *cal_table; + GtkClipboard *clipboard; + gchar *comp_str; + + cal_table = E_CALENDAR_TABLE (selectable); + + /* Create a temporary VCALENDAR object. */ + cal_table->tmp_vcal = e_cal_util_new_top_level (); + + e_table_selected_row_foreach ( + E_TABLE (cal_table), copy_row_cb, cal_table); + comp_str = icalcomponent_as_ical_string_r (cal_table->tmp_vcal); + + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + e_clipboard_set_calendar (clipboard, comp_str, -1); + gtk_clipboard_store (clipboard); + + g_free (comp_str); + + icalcomponent_free (cal_table->tmp_vcal); + cal_table->tmp_vcal = NULL; +} + +/* Helper for calenable_table_paste_clipboard() */ +static void +clipboard_get_calendar_data (ECalendarTable *cal_table, + const gchar *text) +{ + icalcomponent *icalcomp; + gchar *uid; + ECalComponent *comp; + ECalModel *model; + ECal *client; + icalcomponent_kind kind; + const gchar *status_message; + + g_return_if_fail (E_IS_CALENDAR_TABLE (cal_table)); + + if (!text || !*text) + return; + + icalcomp = icalparser_parse_string (text); + if (!icalcomp) + return; + + /* check the type of the component */ + kind = icalcomponent_isa (icalcomp); + if (kind != ICAL_VCALENDAR_COMPONENT && + kind != ICAL_VEVENT_COMPONENT && + kind != ICAL_VTODO_COMPONENT && + kind != ICAL_VJOURNAL_COMPONENT) { + return; + } + + model = e_calendar_table_get_model (cal_table); + client = e_cal_model_get_default_client (model); + + status_message = _("Updating objects"); + calendar_table_emit_status_message (cal_table, status_message, -1.0); + + if (kind == ICAL_VCALENDAR_COMPONENT) { + icalcomponent_kind child_kind; + icalcomponent *subcomp; + icalcomponent *vcal_comp; + + vcal_comp = icalcomp; + subcomp = icalcomponent_get_first_component ( + vcal_comp, ICAL_ANY_COMPONENT); + while (subcomp) { + child_kind = icalcomponent_isa (subcomp); + if (child_kind == ICAL_VEVENT_COMPONENT || + child_kind == ICAL_VTODO_COMPONENT || + child_kind == ICAL_VJOURNAL_COMPONENT) { + ECalComponent *tmp_comp; + + uid = e_cal_component_gen_uid (); + tmp_comp = e_cal_component_new (); + e_cal_component_set_icalcomponent ( + tmp_comp, + icalcomponent_new_clone (subcomp)); + e_cal_component_set_uid (tmp_comp, uid); + free (uid); + + /* FIXME should we convert start/due/complete + * times? Also, need error handling. */ + e_cal_create_object ( + client, e_cal_component_get_icalcomponent (tmp_comp), + NULL, NULL); + + g_object_unref (tmp_comp); + } + subcomp = icalcomponent_get_next_component ( + vcal_comp, ICAL_ANY_COMPONENT); + } + } else { + comp = e_cal_component_new (); + e_cal_component_set_icalcomponent (comp, icalcomp); + uid = e_cal_component_gen_uid (); + e_cal_component_set_uid (comp, (const gchar *) uid); + free (uid); + + e_cal_create_object ( + client, e_cal_component_get_icalcomponent (comp), + NULL, NULL); + + g_object_unref (comp); + } + + calendar_table_emit_status_message (cal_table, NULL, -1.0); +} + +static void +calendar_table_paste_clipboard (ESelectable *selectable) +{ + ECalendarTable *cal_table; + GtkClipboard *clipboard; + GnomeCanvasItem *item; + GnomeCanvas *table_canvas; + + cal_table = E_CALENDAR_TABLE (selectable); + + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + + table_canvas = E_TABLE (cal_table)->table_canvas; + item = table_canvas->focused_item; + + /* XXX Should ECellText implement GtkEditable? */ + + /* Paste text into a cell being edited. */ + if (gtk_clipboard_wait_is_text_available (clipboard) && + GTK_WIDGET_HAS_FOCUS (table_canvas) && + E_IS_TABLE_ITEM (item) && + E_TABLE_ITEM (item)->editing_col >= 0 && + E_TABLE_ITEM (item)->editing_row >= 0) { + + ETableItem *etable_item = E_TABLE_ITEM (item); + + e_cell_text_paste_clipboard ( + etable_item->cell_views[etable_item->editing_col], + etable_item->editing_col, + etable_item->editing_row); + + /* Paste iCalendar data into the table. */ + } else if (e_clipboard_wait_is_calendar_available (clipboard)) { + gchar *calendar_source; + + calendar_source = e_clipboard_wait_for_calendar (clipboard); + clipboard_get_calendar_data (cal_table, calendar_source); + g_free (calendar_source); + } +} + +static void +calendar_table_select_all (ESelectable *selectable) +{ + e_table_select_all (E_TABLE (selectable)); +} + +static void calendar_table_class_init (ECalendarTableClass *class) { GObjectClass *object_class; @@ -937,6 +1228,16 @@ calendar_table_init (ECalendarTable *cal_table) cal_table->priv = E_CALENDAR_TABLE_GET_PRIVATE (cal_table); } +static void +calendar_table_selectable_init (ESelectableInterface *interface) +{ + interface->update_actions = calendar_table_update_actions; + interface->cut_clipboard = calendar_table_cut_clipboard; + interface->copy_clipboard = calendar_table_copy_clipboard; + interface->paste_clipboard = calendar_table_paste_clipboard; + interface->select_all = calendar_table_select_all; +} + GType e_calendar_table_get_type (void) { @@ -956,8 +1257,17 @@ e_calendar_table_get_type (void) NULL /* value_table */ }; + static const GInterfaceInfo selectable_info = { + (GInterfaceInitFunc) calendar_table_selectable_init, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + type = g_type_register_static ( E_TABLE_TYPE, "ECalendarTable", &type_info, 0); + + g_type_add_interface_static ( + type, E_TYPE_SELECTABLE, &selectable_info); } return type; @@ -1061,32 +1371,6 @@ add_uid_cb (gint model_row, gpointer data) closure->objects = g_slist_prepend (closure->objects, comp_data); } -/* Deletes all of the selected components in the table */ -static void -delete_selected_components (ECalendarTable *cal_table) -{ - GSList *objs, *l; - const gchar *status_message; - - objs = e_calendar_table_get_selected (cal_table); - - status_message = _("Deleting selected objects"); - calendar_table_emit_status_message (cal_table, status_message, -1.0); - - for (l = objs; l; l = l->next) { - ECalModelComponent *comp_data = (ECalModelComponent *) l->data; - GError *error = NULL; - - e_cal_remove_object (comp_data->client, - icalcomponent_get_uid (comp_data->icalcomp), &error); - delete_error_dialog (error, E_CAL_COMPONENT_TODO); - g_clear_error (&error); - } - - calendar_table_emit_status_message (cal_table, NULL, -1.0); - - g_slist_free (objs); -} static void add_retract_data (ECalComponent *comp, const gchar *retract_comment) { @@ -1223,210 +1507,6 @@ e_calendar_table_get_selected (ECalendarTable *cal_table) return closure.objects; } -/** - * e_calendar_table_cut_clipboard: - * @cal_table: A calendar table. - * - * Cuts selected tasks in the given calendar table - */ -void -e_calendar_table_cut_clipboard (ECalendarTable *cal_table) -{ - g_return_if_fail (E_IS_CALENDAR_TABLE (cal_table)); - - e_calendar_table_copy_clipboard (cal_table); - delete_selected_components (cal_table); -} - -/* callback for e_table_selected_row_foreach */ -static void -copy_row_cb (gint model_row, gpointer data) -{ - ECalendarTable *cal_table; - ECalModelComponent *comp_data; - ECalModel *model; - gchar *comp_str; - icalcomponent *child; - - cal_table = E_CALENDAR_TABLE (data); - - g_return_if_fail (cal_table->tmp_vcal != NULL); - - model = e_calendar_table_get_model (cal_table); - comp_data = e_cal_model_get_component_at (model, model_row); - if (!comp_data) - return; - - /* add timezones to the VCALENDAR component */ - e_cal_util_add_timezones_from_component (cal_table->tmp_vcal, comp_data->icalcomp); - - /* add the new component to the VCALENDAR component */ - comp_str = icalcomponent_as_ical_string_r (comp_data->icalcomp); - child = icalparser_parse_string (comp_str); - if (child) { - icalcomponent_add_component (cal_table->tmp_vcal, - icalcomponent_new_clone (child)); - icalcomponent_free (child); - } - g_free (comp_str); -} - -/** - * e_calendar_table_copy_clipboard: - * @cal_table: A calendar table. - * - * Copies selected tasks into the clipboard - */ -void -e_calendar_table_copy_clipboard (ECalendarTable *cal_table) -{ - GtkClipboard *clipboard; - gchar *comp_str; - - g_return_if_fail (E_IS_CALENDAR_TABLE (cal_table)); - - /* create temporary VCALENDAR object */ - cal_table->tmp_vcal = e_cal_util_new_top_level (); - - e_table_selected_row_foreach ( - E_TABLE (cal_table), copy_row_cb, cal_table); - comp_str = icalcomponent_as_ical_string_r (cal_table->tmp_vcal); - - clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - e_clipboard_set_calendar (clipboard, comp_str, -1); - gtk_clipboard_store (clipboard); - - /* free memory */ - icalcomponent_free (cal_table->tmp_vcal); - g_free (comp_str); - cal_table->tmp_vcal = NULL; -} - -static void -clipboard_get_calendar_data (ECalendarTable *cal_table, const gchar *text) -{ - icalcomponent *icalcomp; - gchar *uid; - ECalComponent *comp; - ECalModel *model; - ECal *client; - icalcomponent_kind kind; - const gchar *status_message; - - g_return_if_fail (E_IS_CALENDAR_TABLE (cal_table)); - - if (!text || !*text) - return; - - icalcomp = icalparser_parse_string (text); - if (!icalcomp) - return; - - /* check the type of the component */ - kind = icalcomponent_isa (icalcomp); - if (kind != ICAL_VCALENDAR_COMPONENT && - kind != ICAL_VEVENT_COMPONENT && - kind != ICAL_VTODO_COMPONENT && - kind != ICAL_VJOURNAL_COMPONENT) { - return; - } - - model = e_calendar_table_get_model (cal_table); - client = e_cal_model_get_default_client (model); - - status_message = _("Updating objects"); - calendar_table_emit_status_message (cal_table, status_message, -1.0); - - if (kind == ICAL_VCALENDAR_COMPONENT) { - icalcomponent_kind child_kind; - icalcomponent *subcomp; - icalcomponent *vcal_comp; - - vcal_comp = icalcomp; - subcomp = icalcomponent_get_first_component ( - vcal_comp, ICAL_ANY_COMPONENT); - while (subcomp) { - child_kind = icalcomponent_isa (subcomp); - if (child_kind == ICAL_VEVENT_COMPONENT || - child_kind == ICAL_VTODO_COMPONENT || - child_kind == ICAL_VJOURNAL_COMPONENT) { - ECalComponent *tmp_comp; - - uid = e_cal_component_gen_uid (); - tmp_comp = e_cal_component_new (); - e_cal_component_set_icalcomponent ( - tmp_comp, icalcomponent_new_clone (subcomp)); - e_cal_component_set_uid (tmp_comp, uid); - free (uid); - - /* FIXME should we convert start/due/complete times? */ - /* FIXME Error handling */ - e_cal_create_object (client, e_cal_component_get_icalcomponent (tmp_comp), NULL, NULL); - - g_object_unref (tmp_comp); - } - subcomp = icalcomponent_get_next_component ( - vcal_comp, ICAL_ANY_COMPONENT); - } - } else { - comp = e_cal_component_new (); - e_cal_component_set_icalcomponent (comp, icalcomp); - uid = e_cal_component_gen_uid (); - e_cal_component_set_uid (comp, (const gchar *) uid); - free (uid); - - e_cal_create_object (client, e_cal_component_get_icalcomponent (comp), NULL, NULL); - - g_object_unref (comp); - } - - calendar_table_emit_status_message (cal_table, NULL, -1.0); -} - -/** - * e_calendar_table_paste_clipboard: - * @cal_table: A calendar table. - * - * Pastes tasks currently in the clipboard into the given calendar table - */ -void -e_calendar_table_paste_clipboard (ECalendarTable *cal_table) -{ - GtkClipboard *clipboard; - GnomeCanvasItem *item; - GnomeCanvas *table_canvas; - - g_return_if_fail (E_IS_CALENDAR_TABLE (cal_table)); - - clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - - table_canvas = E_TABLE (cal_table)->table_canvas; - item = table_canvas->focused_item; - - /* Paste text into a cell being edited. */ - if (gtk_clipboard_wait_is_text_available (clipboard) && - GTK_WIDGET_HAS_FOCUS (table_canvas) && - E_IS_TABLE_ITEM (item) && - E_TABLE_ITEM (item)->editing_col >= 0 && - E_TABLE_ITEM (item)->editing_row >= 0) { - - ETableItem *etable_item = E_TABLE_ITEM (item); - - e_cell_text_paste_clipboard ( - etable_item->cell_views[etable_item->editing_col], - etable_item->editing_col, - etable_item->editing_row); - - /* Paste iCalendar data into the table. */ - } else if (e_clipboard_wait_is_calendar_available (clipboard)) { - gchar *calendar_source; - - calendar_source = e_clipboard_wait_for_calendar (clipboard); - clipboard_get_calendar_data (cal_table, calendar_source); - g_free (calendar_source); - } -} - static void hide_completed_rows (ECalModel *model, GList *clients_list, gchar *hide_sexp, GPtrArray *comp_objects) { |