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 | |
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')
-rw-r--r-- | calendar/gui/dialogs/comp-editor.c | 153 | ||||
-rw-r--r-- | calendar/gui/dialogs/comp-editor.h | 2 | ||||
-rw-r--r-- | calendar/gui/e-cal-list-view.h | 3 | ||||
-rw-r--r-- | calendar/gui/e-calendar-table.c | 540 | ||||
-rw-r--r-- | calendar/gui/e-calendar-table.h | 5 | ||||
-rw-r--r-- | calendar/gui/e-calendar-view.c | 682 | ||||
-rw-r--r-- | calendar/gui/e-calendar-view.h | 3 | ||||
-rw-r--r-- | calendar/gui/e-day-view-main-item.c | 1 | ||||
-rw-r--r-- | calendar/gui/e-memo-table.c | 544 | ||||
-rw-r--r-- | calendar/gui/e-memo-table.h | 5 | ||||
-rw-r--r-- | calendar/gui/gnome-cal.h | 2 | ||||
-rw-r--r-- | calendar/gui/goto.c | 1 | ||||
-rw-r--r-- | calendar/gui/print.h | 1 |
13 files changed, 1101 insertions, 841 deletions
diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c index 18bd574728..21384032d9 100644 --- a/calendar/gui/dialogs/comp-editor.c +++ b/calendar/gui/dialogs/comp-editor.c @@ -80,6 +80,9 @@ struct _CompEditorPrivate { gpointer shell; /* weak pointer */ + /* EFocusTracker keeps selection actions up-to-date. */ + EFocusTracker *focus_tracker; + /* Each CompEditor window gets its own GtkWindowGroup, so it * doesn't block the main window or other CompEditor windows. */ GtkWindowGroup *window_group; @@ -133,6 +136,7 @@ enum { PROP_CHANGED, PROP_CLIENT, PROP_FLAGS, + PROP_FOCUS_TRACKER, PROP_SHELL, PROP_SUMMARY }; @@ -149,9 +153,10 @@ static const gchar *ui = " <menuitem action='close'/>" " </menu>" " <menu action='edit-menu'>" -" <menuitem action='cut'/>" -" <menuitem action='copy'/>" -" <menuitem action='paste'/>" +" <menuitem action='cut-clipboard'/>" +" <menuitem action='copy-clipboard'/>" +" <menuitem action='paste-clipboard'/>" +" <menuitem action='delete-selection'/>" " <separator/>" " <menuitem action='select-all'/>" " </menu>" @@ -677,36 +682,6 @@ action_close_cb (GtkAction *action, } static void -action_copy_cb (GtkAction *action, - CompEditor *editor) -{ - GtkWidget *focus; - - focus = gtk_window_get_focus (GTK_WINDOW (editor)); - - if (GTK_IS_ENTRY (focus)) - gtk_editable_copy_clipboard (GTK_EDITABLE (focus)); - - if (GTK_IS_TEXT_VIEW (focus)) - g_signal_emit_by_name (focus, "copy-clipboard"); -} - -static void -action_cut_cb (GtkAction *action, - CompEditor *editor) -{ - GtkWidget *focus; - - focus = gtk_window_get_focus (GTK_WINDOW (editor)); - - if (GTK_IS_ENTRY (focus)) - gtk_editable_cut_clipboard (GTK_EDITABLE (focus)); - - if (GTK_IS_TEXT_VIEW (focus)) - g_signal_emit_by_name (focus, "cut-clipboard"); -} - -static void action_help_cb (GtkAction *action, CompEditor *editor) { @@ -714,21 +689,6 @@ action_help_cb (GtkAction *action, } static void -action_paste_cb (GtkAction *action, - CompEditor *editor) -{ - GtkWidget *focus; - - focus = gtk_window_get_focus (GTK_WINDOW (editor)); - - if (GTK_IS_ENTRY (focus)) - gtk_editable_paste_clipboard (GTK_EDITABLE (focus)); - - if (GTK_IS_TEXT_VIEW (focus)) - g_signal_emit_by_name (focus, "paste-clipboard"); -} - -static void action_print_cb (GtkAction *action, CompEditor *editor) { @@ -886,23 +846,6 @@ action_save_cb (GtkAction *action, } static void -action_select_all_cb (GtkAction *action, - CompEditor *editor) -{ - GtkWidget *focus; - - focus = gtk_window_get_focus (GTK_WINDOW (editor)); - - if (GTK_IS_ENTRY (focus)) { - gtk_editable_set_position (GTK_EDITABLE (focus), -1); - gtk_editable_select_region (GTK_EDITABLE (focus), 0, -1); - } - - if (GTK_IS_TEXT_VIEW (focus)) - g_signal_emit_by_name (focus, "select-all", TRUE); -} - -static void action_view_categories_cb (GtkToggleAction *action, CompEditor *editor) { @@ -995,19 +938,26 @@ static GtkActionEntry core_entries[] = { N_("Click here to close the current window"), G_CALLBACK (action_close_cb) }, - { "copy", + { "copy-clipboard", GTK_STOCK_COPY, NULL, NULL, - N_("Copy selected text to the clipboard"), - G_CALLBACK (action_copy_cb) }, + N_("Copy the selection"), + NULL }, /* Handled by EFocusTracker */ - { "cut", + { "cut-clipboard", GTK_STOCK_CUT, NULL, NULL, - N_("Cut selected text to the clipboard"), - G_CALLBACK (action_cut_cb) }, + N_("Cut the selection"), + NULL }, /* Handled by EFocusTracker */ + + { "delete-selection", + GTK_STOCK_DELETE, + NULL, + NULL, + N_("Delete the selection"), + NULL }, /* Handled by EFocusTracker */ { "help", GTK_STOCK_HELP, @@ -1016,12 +966,12 @@ static GtkActionEntry core_entries[] = { N_("Click here to view help available"), G_CALLBACK (action_help_cb) }, - { "paste", + { "paste-clipboard", GTK_STOCK_PASTE, NULL, NULL, - N_("Paste text from the clipboard"), - G_CALLBACK (action_paste_cb) }, + N_("Paste the clipboard"), + NULL }, /* Handled by EFocusTracker */ { "print", GTK_STOCK_PRINT, @@ -1047,9 +997,9 @@ static GtkActionEntry core_entries[] = { { "select-all", GTK_STOCK_SELECT_ALL, NULL, - NULL, + "<Control>a", N_("Select all text"), - G_CALLBACK (action_select_all_cb) }, + NULL }, /* Handled by EFocusTracker */ /* Menus */ @@ -1302,6 +1252,12 @@ comp_editor_get_property (GObject *object, COMP_EDITOR (object))); return; + case PROP_FOCUS_TRACKER: + g_value_set_object ( + value, comp_editor_get_focus_tracker ( + COMP_EDITOR (object))); + return; + case PROP_SHELL: g_value_set_object ( value, comp_editor_get_shell ( @@ -1331,6 +1287,11 @@ comp_editor_dispose (GObject *object) priv->shell = NULL; } + if (priv->focus_tracker != NULL) { + g_object_unref (priv->focus_tracker); + priv->focus_tracker = NULL; + } + if (priv->window_group != NULL) { g_object_unref (priv->window_group); priv->window_group = NULL; @@ -1566,6 +1527,16 @@ comp_editor_class_init (CompEditorClass *class) g_object_class_install_property ( object_class, + PROP_FOCUS_TRACKER, + g_param_spec_object ( + "focus-tracker", + NULL, + NULL, + E_TYPE_FOCUS_TRACKER, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, PROP_SHELL, g_param_spec_object ( "shell", @@ -1601,6 +1572,7 @@ comp_editor_init (CompEditor *editor) CompEditorPrivate *priv; EAttachmentView *view; EAttachmentStore *store; + EFocusTracker *focus_tracker; GdkDragAction drag_actions; GtkTargetList *target_list; GtkTargetEntry *targets; @@ -1684,6 +1656,27 @@ comp_editor_init (CompEditor *editor) priv->ui_manager, action_group, 0); g_object_unref (action_group); + /* Configure an EFocusTracker to manage selection actions. */ + + focus_tracker = e_focus_tracker_new (GTK_WINDOW (editor)); + + action = comp_editor_get_action (editor, "cut-clipboard"); + e_focus_tracker_set_cut_clipboard_action (focus_tracker, action); + + action = comp_editor_get_action (editor, "copy-clipboard"); + e_focus_tracker_set_copy_clipboard_action (focus_tracker, action); + + action = comp_editor_get_action (editor, "paste-clipboard"); + e_focus_tracker_set_paste_clipboard_action (focus_tracker, action); + + action = comp_editor_get_action (editor, "delete-selection"); + e_focus_tracker_set_delete_selection_action (focus_tracker, action); + + action = comp_editor_get_action (editor, "select-all"); + e_focus_tracker_set_select_all_action (focus_tracker, action); + + priv->focus_tracker = focus_tracker; + /* Fine Tuning */ action = comp_editor_get_action (editor, "attach"); @@ -2093,6 +2086,14 @@ comp_editor_get_changed (CompEditor *editor) return editor->priv->changed; } +EFocusTracker * +comp_editor_get_focus_tracker (CompEditor *editor) +{ + g_return_val_if_fail (IS_COMP_EDITOR (editor), NULL); + + return editor->priv->focus_tracker; +} + void comp_editor_set_flags (CompEditor *editor, CompEditorFlags flags) diff --git a/calendar/gui/dialogs/comp-editor.h b/calendar/gui/dialogs/comp-editor.h index 0b3ea047e7..54672ec3b8 100644 --- a/calendar/gui/dialogs/comp-editor.h +++ b/calendar/gui/dialogs/comp-editor.h @@ -30,6 +30,7 @@ #include "../itip-utils.h" #include "comp-editor-page.h" #include <shell/e-shell.h> +#include <misc/e-focus-tracker.h> /* Standard GObject macros */ #define TYPE_COMP_EDITOR \ @@ -92,6 +93,7 @@ GType comp_editor_get_type (void); void comp_editor_set_changed (CompEditor *editor, gboolean changed); gboolean comp_editor_get_changed (CompEditor *editor); +EFocusTracker * comp_editor_get_focus_tracker (CompEditor *editor); void comp_editor_set_needs_send (CompEditor *editor, gboolean needs_send); gboolean comp_editor_get_needs_send (CompEditor *editor); diff --git a/calendar/gui/e-cal-list-view.h b/calendar/gui/e-cal-list-view.h index 0874b73c5b..faf37bbc9f 100644 --- a/calendar/gui/e-cal-list-view.h +++ b/calendar/gui/e-cal-list-view.h @@ -27,6 +27,9 @@ #include <time.h> #include <gtk/gtk.h> +#include <table/e-table.h> +#include <table/e-cell-date-edit.h> + #include "e-calendar-view.h" #include "gnome-cal.h" 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) { diff --git a/calendar/gui/e-calendar-table.h b/calendar/gui/e-calendar-table.h index aa98aee7fa..71c7b716f2 100644 --- a/calendar/gui/e-calendar-table.h +++ b/calendar/gui/e-calendar-table.h @@ -92,11 +92,6 @@ EShellView * e_calendar_table_get_shell_view (ECalendarTable *cal_table); void e_calendar_table_delete_selected(ECalendarTable *cal_table); GSList * e_calendar_table_get_selected (ECalendarTable *cal_table); -/* Clipboard related functions */ -void e_calendar_table_cut_clipboard (ECalendarTable *cal_table); -void e_calendar_table_copy_clipboard (ECalendarTable *cal_table); -void e_calendar_table_paste_clipboard(ECalendarTable *cal_table); - ECalModelComponent * e_calendar_table_get_selected_comp (ECalendarTable *cal_table); diff --git a/calendar/gui/e-calendar-view.c b/calendar/gui/e-calendar-view.c index f23088af83..5c04c7848b 100644 --- a/calendar/gui/e-calendar-view.c +++ b/calendar/gui/e-calendar-view.c @@ -39,6 +39,7 @@ #include <e-util/e-icon-factory.h> #include <libecal/e-cal-time-util.h> #include <libecal/e-cal-component.h> +#include <misc/e-selectable.h> #include <shell/e-shell.h> #include "common/authentication.h" @@ -94,10 +95,9 @@ enum { LAST_SIGNAL }; +static gpointer parent_class; static guint signals[LAST_SIGNAL]; -G_DEFINE_TYPE (ECalendarView, e_calendar_view, GTK_TYPE_TABLE) - static void calendar_view_set_model (ECalendarView *calendar_view, ECalModel *model) @@ -158,7 +158,7 @@ calendar_view_dispose (GObject *object) } /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (e_calendar_view_parent_class)->dispose (object); + G_OBJECT_CLASS (parent_class)->dispose (object); } static void @@ -171,11 +171,352 @@ calendar_view_finalize (GObject *object) g_free (priv->default_category); /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (e_calendar_view_parent_class)->finalize (object); + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +calendar_view_update_actions (ESelectable *selectable, + EFocusTracker *focus_tracker, + GdkAtom *clipboard_targets, + gint n_clipboard_targets) +{ + ECalendarView *view; + GtkAction *action; + GList *list, *iter; + gboolean sources_are_editable = TRUE; + gboolean clipboard_has_calendar; + gboolean sensitive; + const gchar *tooltip; + gint n_selected; + + view = E_CALENDAR_VIEW (selectable); + + list = e_calendar_view_get_selected_events (view); + n_selected = g_list_length (list); + + for (iter = list; iter != NULL; iter = iter->next) { + ECalendarViewEvent *event = iter->data; + gboolean read_only; + + if (event == NULL || event->comp_data == NULL) + continue; + + e_cal_is_read_only (event->comp_data->client, &read_only, NULL); + sources_are_editable &= !read_only; + } + + g_list_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 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); + 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 && clipboard_has_calendar; + tooltip = _("Paste events from the clipboard"); + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, tooltip); +} + +static void +calendar_view_cut_clipboard (ESelectable *selectable) +{ + ECalendarView *cal_view; + GList *selected, *l; + const gchar *uid; + + cal_view = E_CALENDAR_VIEW (selectable); + + selected = e_calendar_view_get_selected_events (cal_view); + if (!selected) + return; + +#if 0 /* KILL-BONOBO */ + e_calendar_view_set_status_message (cal_view, _("Deleting selected objects"), -1); +#endif + + e_selectable_copy_clipboard (selectable); + + for (l = selected; l != NULL; l = l->next) { + ECalComponent *comp; + ECalendarViewEvent *event = (ECalendarViewEvent *) l->data; + GError *error = NULL; + + if (!event) + continue; + + comp = e_cal_component_new (); + e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp)); + + if ((itip_organizer_is_user (comp, event->comp_data->client) || itip_sentby_is_user (comp, event->comp_data->client)) + && cancel_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (cal_view)), + event->comp_data->client, comp, TRUE)) + itip_send_comp (E_CAL_COMPONENT_METHOD_CANCEL, comp, + event->comp_data->client, NULL, NULL, NULL, TRUE, FALSE); + + e_cal_component_get_uid (comp, &uid); + if (e_cal_component_is_instance (comp)) { + gchar *rid = NULL; + icalcomponent *icalcomp; + + /* when cutting detached instances, only cut that instance */ + rid = e_cal_component_get_recurid_as_string (comp); + if (e_cal_get_object (event->comp_data->client, uid, rid, &icalcomp, NULL)) { + e_cal_remove_object_with_mod (event->comp_data->client, uid, + rid, CALOBJ_MOD_THIS, + &error); + icalcomponent_free (icalcomp); + } else + e_cal_remove_object_with_mod (event->comp_data->client, uid, NULL, + CALOBJ_MOD_ALL, &error); + g_free (rid); + } else + e_cal_remove_object (event->comp_data->client, uid, &error); + delete_error_dialog (error, E_CAL_COMPONENT_EVENT); + + g_clear_error (&error); + + g_object_unref (comp); + } + +#if 0 /* KILL-BONOBO */ + e_calendar_view_set_status_message (cal_view, NULL, -1); +#endif + + g_list_free (selected); +} + +static void +add_related_timezones (icalcomponent *des_icalcomp, icalcomponent *src_icalcomp, ECal *client) +{ + icalproperty_kind look_in[] = { + ICAL_DTSTART_PROPERTY, + ICAL_DTEND_PROPERTY, + ICAL_NO_PROPERTY + }; + gint i; + + g_return_if_fail (des_icalcomp != NULL); + g_return_if_fail (src_icalcomp != NULL); + g_return_if_fail (client != NULL); + + for (i = 0; look_in[i] != ICAL_NO_PROPERTY; i++) { + icalproperty *prop = icalcomponent_get_first_property (src_icalcomp, look_in[i]); + + if (prop) { + icalparameter *par = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER); + + if (par) { + const gchar *tzid = icalparameter_get_tzid (par); + + if (tzid) { + GError *error = NULL; + icaltimezone *zone = NULL; + + if (!e_cal_get_timezone (client, tzid, &zone, &error)) { + g_warning ("%s: Cannot get timezone for '%s'. %s", G_STRFUNC, tzid, error ? error->message : ""); + if (error) + g_error_free (error); + } else if (zone && + icalcomponent_get_timezone (des_icalcomp, icaltimezone_get_tzid (zone)) == NULL) { + /* do not duplicate timezones in the component */ + icalcomponent *vtz_comp; + + vtz_comp = icaltimezone_get_component (zone); + if (vtz_comp) + icalcomponent_add_component (des_icalcomp, icalcomponent_new_clone (vtz_comp)); + } + } + } + } + } +} + +static void +calendar_view_copy_clipboard (ESelectable *selectable) +{ + ECalendarView *cal_view; + GList *selected, *l; + gchar *comp_str; + icalcomponent *vcal_comp; + icalcomponent *new_icalcomp; + ECalendarViewEvent *event; + GtkClipboard *clipboard; + + cal_view = E_CALENDAR_VIEW (selectable); + + selected = e_calendar_view_get_selected_events (cal_view); + if (!selected) + return; + + /* create top-level VCALENDAR component and add VTIMEZONE's */ + vcal_comp = e_cal_util_new_top_level (); + for (l = selected; l != NULL; l = l->next) { + event = (ECalendarViewEvent *) l->data; + + if (event) { + e_cal_util_add_timezones_from_component (vcal_comp, event->comp_data->icalcomp); + + add_related_timezones (vcal_comp, event->comp_data->icalcomp, event->comp_data->client); + } + } + + for (l = selected; l != NULL; l = l->next) { + event = (ECalendarViewEvent *) l->data; + + new_icalcomp = icalcomponent_new_clone (event->comp_data->icalcomp); + + /* remove RECURRENCE-IDs from copied objects */ + if (e_cal_util_component_is_instance (new_icalcomp)) { + icalproperty *prop; + + prop = icalcomponent_get_first_property (new_icalcomp, ICAL_RECURRENCEID_PROPERTY); + if (prop) + icalcomponent_remove_property (new_icalcomp, prop); + } + icalcomponent_add_component (vcal_comp, new_icalcomp); + } + + comp_str = icalcomponent_as_ical_string_r (vcal_comp); + + /* copy the VCALENDAR to the clipboard */ + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + e_clipboard_set_calendar (clipboard, comp_str, -1); + gtk_clipboard_store (clipboard); + + /* free memory */ + icalcomponent_free (vcal_comp); + g_free (comp_str); + g_list_free (selected); +} + +static void +clipboard_get_calendar_data (ECalendarView *cal_view, + const gchar *text) +{ + icalcomponent *icalcomp; + icalcomponent_kind kind; + time_t selected_time_start, selected_time_end; + icaltimezone *default_zone; + ECal *client; + gboolean in_top_canvas; + + g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view)); + + if (!text || !*text) + return; + + icalcomp = icalparser_parse_string ((const gchar *) text); + if (!icalcomp) + return; + + default_zone = calendar_config_get_icaltimezone (); + client = e_cal_model_get_default_client (cal_view->priv->model); + + /* check the type of the component */ + /* FIXME An error dialog if we return? */ + kind = icalcomponent_isa (icalcomp); + if (kind != ICAL_VCALENDAR_COMPONENT && kind != ICAL_VEVENT_COMPONENT) + return; + +#if 0 /* KILL-BONOBO */ + e_calendar_view_set_status_message (cal_view, _("Updating objects"), -1); +#endif + e_calendar_view_get_selected_time_range (cal_view, &selected_time_start, &selected_time_end); + + if ((selected_time_end - selected_time_start) == 60 * 60 * 24) + in_top_canvas = TRUE; + else + in_top_canvas = FALSE; + + if (kind == ICAL_VCALENDAR_COMPONENT) { + icalcomponent *subcomp; + + /* add timezones first, to have them ready */ + for (subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VTIMEZONE_COMPONENT); + subcomp; + subcomp = icalcomponent_get_next_component (icalcomp, ICAL_VTIMEZONE_COMPONENT)) { + icaltimezone *zone; + GError *error = NULL; + + zone = icaltimezone_new (); + icaltimezone_set_component (zone, subcomp); + if (!e_cal_add_timezone (client, zone, &error)) { + icalproperty *tzidprop = icalcomponent_get_first_property (subcomp, ICAL_TZID_PROPERTY); + + g_warning ("%s: Add zone '%s' failed. %s", G_STRFUNC, tzidprop ? icalproperty_get_tzid (tzidprop) : "???", error ? error->message : ""); + if (error) + g_error_free (error); + } + + icaltimezone_free (zone, 1); + } + + for (subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VEVENT_COMPONENT); + subcomp; + subcomp = icalcomponent_get_next_component (icalcomp, ICAL_VEVENT_COMPONENT)) { + if (e_cal_util_component_has_recurrences (subcomp)) { + icalproperty *icalprop = icalcomponent_get_first_property (subcomp, ICAL_RRULE_PROPERTY); + if (icalprop) + icalproperty_remove_parameter_by_name (icalprop, "X-EVOLUTION-ENDDATE"); + } + + e_calendar_view_add_event (cal_view, client, selected_time_start, default_zone, subcomp, in_top_canvas); + } + + icalcomponent_free (icalcomp); + } else { + e_calendar_view_add_event (cal_view, client, selected_time_start, default_zone, icalcomp, in_top_canvas); + } + +#if 0 /* KILL-BONOBO */ + e_calendar_view_set_status_message (cal_view, NULL, -1); +#endif +} + +static void +calendar_view_paste_clipboard (ESelectable *selectable) +{ + ECalendarView *cal_view; + GtkClipboard *clipboard; + + cal_view = E_CALENDAR_VIEW (selectable); + + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + + /* Paste text into an event being edited. */ + if (gtk_clipboard_wait_is_text_available (clipboard)) { + ECalendarViewClass *class; + + class = E_CALENDAR_VIEW_GET_CLASS (cal_view); + g_return_if_fail (class->paste_text != NULL); + + class->paste_text (cal_view); + + /* Paste iCalendar data into the view. */ + } 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_view, calendar_source); + g_free (calendar_source); + } } static void -e_calendar_view_class_init (ECalendarViewClass *class) +calendar_view_class_init (ECalendarViewClass *class) { GObjectClass *object_class; GtkBindingSet *binding_set; @@ -290,9 +631,7 @@ e_calendar_view_class_init (ECalendarViewClass *class) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - /* - * Key bindings - */ + /* Key bindings */ binding_set = gtk_binding_set_by_class (class); @@ -304,11 +643,56 @@ e_calendar_view_class_init (ECalendarViewClass *class) } static void -e_calendar_view_init (ECalendarView *calendar_view) +calendar_view_init (ECalendarView *calendar_view) { calendar_view->priv = E_CALENDAR_VIEW_GET_PRIVATE (calendar_view); } +static void +calendar_view_selectable_init (ESelectableInterface *interface) +{ + interface->update_actions = calendar_view_update_actions; + interface->cut_clipboard = calendar_view_cut_clipboard; + interface->copy_clipboard = calendar_view_copy_clipboard; + interface->paste_clipboard = calendar_view_paste_clipboard; +} + +GType +e_calendar_view_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (ECalendarViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) calendar_view_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ECalendarView), + 0, /* n_preallocs */ + (GInstanceInitFunc) calendar_view_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo selectable_info = { + (GInterfaceInitFunc) calendar_view_selectable_init, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + + type = g_type_register_static ( + GTK_TYPE_TABLE, "ECalendarView", &type_info, + G_TYPE_FLAG_ABSTRACT); + + g_type_add_interface_static ( + type, E_TYPE_SELECTABLE, &selectable_info); + } + + return type; +} + void e_calendar_view_popup_event (ECalendarView *calendar_view, GdkEventButton *event) @@ -586,286 +970,6 @@ e_calendar_view_update_query (ECalendarView *cal_view) class->update_query (cal_view); } -void -e_calendar_view_cut_clipboard (ECalendarView *cal_view) -{ - GList *selected, *l; - const gchar *uid; - - g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view)); - - selected = e_calendar_view_get_selected_events (cal_view); - if (!selected) - return; - -#if 0 /* KILL-BONOBO */ - e_calendar_view_set_status_message (cal_view, _("Deleting selected objects"), -1); -#endif - - e_calendar_view_copy_clipboard (cal_view); - for (l = selected; l != NULL; l = l->next) { - ECalComponent *comp; - ECalendarViewEvent *event = (ECalendarViewEvent *) l->data; - GError *error = NULL; - - if (!event) - continue; - - comp = e_cal_component_new (); - e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp)); - - if ((itip_organizer_is_user (comp, event->comp_data->client) || itip_sentby_is_user (comp, event->comp_data->client)) - && cancel_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (cal_view)), - event->comp_data->client, comp, TRUE)) - itip_send_comp (E_CAL_COMPONENT_METHOD_CANCEL, comp, - event->comp_data->client, NULL, NULL, NULL, TRUE, FALSE); - - e_cal_component_get_uid (comp, &uid); - if (e_cal_component_is_instance (comp)) { - gchar *rid = NULL; - icalcomponent *icalcomp; - - /* when cutting detached instances, only cut that instance */ - rid = e_cal_component_get_recurid_as_string (comp); - if (e_cal_get_object (event->comp_data->client, uid, rid, &icalcomp, NULL)) { - e_cal_remove_object_with_mod (event->comp_data->client, uid, - rid, CALOBJ_MOD_THIS, - &error); - icalcomponent_free (icalcomp); - } else - e_cal_remove_object_with_mod (event->comp_data->client, uid, NULL, - CALOBJ_MOD_ALL, &error); - g_free (rid); - } else - e_cal_remove_object (event->comp_data->client, uid, &error); - delete_error_dialog (error, E_CAL_COMPONENT_EVENT); - - g_clear_error (&error); - - g_object_unref (comp); - } - -#if 0 /* KILL-BONOBO */ - e_calendar_view_set_status_message (cal_view, NULL, -1); -#endif - - g_list_free (selected); -} - -static void -add_related_timezones (icalcomponent *des_icalcomp, icalcomponent *src_icalcomp, ECal *client) -{ - icalproperty_kind look_in[] = { - ICAL_DTSTART_PROPERTY, - ICAL_DTEND_PROPERTY, - ICAL_NO_PROPERTY - }; - gint i; - - g_return_if_fail (des_icalcomp != NULL); - g_return_if_fail (src_icalcomp != NULL); - g_return_if_fail (client != NULL); - - for (i = 0; look_in[i] != ICAL_NO_PROPERTY; i++) { - icalproperty *prop = icalcomponent_get_first_property (src_icalcomp, look_in[i]); - - if (prop) { - icalparameter *par = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER); - - if (par) { - const gchar *tzid = icalparameter_get_tzid (par); - - if (tzid) { - GError *error = NULL; - icaltimezone *zone = NULL; - - if (!e_cal_get_timezone (client, tzid, &zone, &error)) { - g_warning ("%s: Cannot get timezone for '%s'. %s", G_STRFUNC, tzid, error ? error->message : ""); - if (error) - g_error_free (error); - } else if (zone && - icalcomponent_get_timezone (des_icalcomp, icaltimezone_get_tzid (zone)) == NULL) { - /* do not duplicate timezones in the component */ - icalcomponent *vtz_comp; - - vtz_comp = icaltimezone_get_component (zone); - if (vtz_comp) - icalcomponent_add_component (des_icalcomp, icalcomponent_new_clone (vtz_comp)); - } - } - } - } - } -} - -void -e_calendar_view_copy_clipboard (ECalendarView *cal_view) -{ - GList *selected, *l; - gchar *comp_str; - icalcomponent *vcal_comp; - icalcomponent *new_icalcomp; - ECalendarViewEvent *event; - GtkClipboard *clipboard; - - g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view)); - - selected = e_calendar_view_get_selected_events (cal_view); - if (!selected) - return; - - /* create top-level VCALENDAR component and add VTIMEZONE's */ - vcal_comp = e_cal_util_new_top_level (); - for (l = selected; l != NULL; l = l->next) { - event = (ECalendarViewEvent *) l->data; - - if (event) { - e_cal_util_add_timezones_from_component (vcal_comp, event->comp_data->icalcomp); - - add_related_timezones (vcal_comp, event->comp_data->icalcomp, event->comp_data->client); - } - } - - for (l = selected; l != NULL; l = l->next) { - event = (ECalendarViewEvent *) l->data; - - new_icalcomp = icalcomponent_new_clone (event->comp_data->icalcomp); - - /* remove RECURRENCE-IDs from copied objects */ - if (e_cal_util_component_is_instance (new_icalcomp)) { - icalproperty *prop; - - prop = icalcomponent_get_first_property (new_icalcomp, ICAL_RECURRENCEID_PROPERTY); - if (prop) - icalcomponent_remove_property (new_icalcomp, prop); - } - icalcomponent_add_component (vcal_comp, new_icalcomp); - } - - comp_str = icalcomponent_as_ical_string_r (vcal_comp); - - /* copy the VCALENDAR to the clipboard */ - clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - e_clipboard_set_calendar (clipboard, comp_str, -1); - gtk_clipboard_store (clipboard); - - /* free memory */ - icalcomponent_free (vcal_comp); - g_free (comp_str); - g_list_free (selected); -} - -static void -clipboard_get_calendar_data (ECalendarView *cal_view, const gchar *text) -{ - icalcomponent *icalcomp; - icalcomponent_kind kind; - time_t selected_time_start, selected_time_end; - icaltimezone *default_zone; - ECal *client; - gboolean in_top_canvas; - - g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view)); - - if (!text || !*text) - return; - - icalcomp = icalparser_parse_string ((const gchar *) text); - if (!icalcomp) - return; - - default_zone = calendar_config_get_icaltimezone (); - client = e_cal_model_get_default_client (cal_view->priv->model); - - /* check the type of the component */ - /* FIXME An error dialog if we return? */ - kind = icalcomponent_isa (icalcomp); - if (kind != ICAL_VCALENDAR_COMPONENT && kind != ICAL_VEVENT_COMPONENT) - return; - -#if 0 /* KILL-BONOBO */ - e_calendar_view_set_status_message (cal_view, _("Updating objects"), -1); -#endif - e_calendar_view_get_selected_time_range (cal_view, &selected_time_start, &selected_time_end); - - if ((selected_time_end - selected_time_start) == 60 * 60 * 24) - in_top_canvas = TRUE; - else - in_top_canvas = FALSE; - - if (kind == ICAL_VCALENDAR_COMPONENT) { - icalcomponent *subcomp; - - /* add timezones first, to have them ready */ - for (subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VTIMEZONE_COMPONENT); - subcomp; - subcomp = icalcomponent_get_next_component (icalcomp, ICAL_VTIMEZONE_COMPONENT)) { - icaltimezone *zone; - GError *error = NULL; - - zone = icaltimezone_new (); - icaltimezone_set_component (zone, subcomp); - if (!e_cal_add_timezone (client, zone, &error)) { - icalproperty *tzidprop = icalcomponent_get_first_property (subcomp, ICAL_TZID_PROPERTY); - - g_warning ("%s: Add zone '%s' failed. %s", G_STRFUNC, tzidprop ? icalproperty_get_tzid (tzidprop) : "???", error ? error->message : ""); - if (error) - g_error_free (error); - } - - icaltimezone_free (zone, 1); - } - - for (subcomp = icalcomponent_get_first_component (icalcomp, ICAL_VEVENT_COMPONENT); - subcomp; - subcomp = icalcomponent_get_next_component (icalcomp, ICAL_VEVENT_COMPONENT)) { - if (e_cal_util_component_has_recurrences (subcomp)) { - icalproperty *icalprop = icalcomponent_get_first_property (subcomp, ICAL_RRULE_PROPERTY); - if (icalprop) - icalproperty_remove_parameter_by_name (icalprop, "X-EVOLUTION-ENDDATE"); - } - - e_calendar_view_add_event (cal_view, client, selected_time_start, default_zone, subcomp, in_top_canvas); - } - - icalcomponent_free (icalcomp); - } else { - e_calendar_view_add_event (cal_view, client, selected_time_start, default_zone, icalcomp, in_top_canvas); - } - -#if 0 /* KILL-BONOBO */ - e_calendar_view_set_status_message (cal_view, NULL, -1); -#endif -} - -void -e_calendar_view_paste_clipboard (ECalendarView *cal_view) -{ - GtkClipboard *clipboard; - - g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view)); - - clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - - /* Paste text into an event being edited. */ - if (gtk_clipboard_wait_is_text_available (clipboard)) { - ECalendarViewClass *class; - - class = E_CALENDAR_VIEW_GET_CLASS (cal_view); - g_return_if_fail (class->paste_text != NULL); - - class->paste_text (cal_view); - - /* Paste iCalendar data into the view. */ - } 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_view, calendar_source); - g_free (calendar_source); - } -} - static void add_retract_data (ECalComponent *comp, const gchar *retract_comment, CalObjModType mod) { diff --git a/calendar/gui/e-calendar-view.h b/calendar/gui/e-calendar-view.h index 7ae643a707..a7ed224fcb 100644 --- a/calendar/gui/e-calendar-view.h +++ b/calendar/gui/e-calendar-view.h @@ -174,9 +174,6 @@ gboolean e_calendar_view_get_visible_time_range time_t *end_time); void e_calendar_view_update_query (ECalendarView *cal_view); -void e_calendar_view_cut_clipboard (ECalendarView *cal_view); -void e_calendar_view_copy_clipboard (ECalendarView *cal_view); -void e_calendar_view_paste_clipboard (ECalendarView *cal_view); void e_calendar_view_delete_selected_event (ECalendarView *cal_view); void e_calendar_view_delete_selected_events diff --git a/calendar/gui/e-day-view-main-item.c b/calendar/gui/e-day-view-main-item.c index 6b34018fe7..16be4ffc89 100644 --- a/calendar/gui/e-day-view-main-item.c +++ b/calendar/gui/e-day-view-main-item.c @@ -33,6 +33,7 @@ #include <e-calendar-view.h> #include "e-util/e-categories-config.h" +#include "e-util/e-util.h" #include "e-day-view-layout.h" #include "e-day-view-main-item.h" #include "ea-calendar.h" diff --git a/calendar/gui/e-memo-table.c b/calendar/gui/e-memo-table.c index 977715898e..4df17c5487 100644 --- a/calendar/gui/e-memo-table.c +++ b/calendar/gui/e-memo-table.c @@ -36,7 +36,8 @@ #include <glib/gi18n.h> #include <glib/gstdio.h> #include <e-util/e-binding.h> -#include <widgets/misc/e-gui-utils.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> @@ -181,6 +182,33 @@ memo_table_model_cal_view_done_cb (EMemoTable *memo_table, memo_table_emit_status_message (memo_table, NULL, -1.0); } +/* Deletes all of the selected components in the table */ +static void +delete_selected_components (EMemoTable *memo_table) +{ + GSList *objs, *l; + const gchar *status_message; + + objs = e_memo_table_get_selected (memo_table); + + status_message = _("Deleting selected objects"); + memo_table_emit_status_message (memo_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_JOURNAL); + g_clear_error (&error); + } + + memo_table_emit_status_message (memo_table, NULL, -1.0); + + g_slist_free (objs); +} + static void memo_table_set_model (EMemoTable *memo_table, ECalModel *model) @@ -629,6 +657,270 @@ memo_table_right_click (ETable *table, } static void +memo_table_update_actions (ESelectable *selectable, + EFocusTracker *focus_tracker, + GdkAtom *clipboard_targets, + gint n_clipboard_targets) +{ + EMemoTable *memo_table; + GtkAction *action; + GSList *list, *iter; + gboolean sources_are_editable = TRUE; + gboolean clipboard_has_calendar; + gboolean sensitive; + const gchar *tooltip; + gint n_selected; + + memo_table = E_MEMO_TABLE (selectable); + n_selected = e_table_selected_count (E_TABLE (memo_table)); + + list = e_memo_table_get_selected (memo_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 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); + 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 && clipboard_has_calendar; + tooltip = _("Paste memos 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 memos"); + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, tooltip); +} + +static void +memo_table_cut_clipboard (ESelectable *selectable) +{ + EMemoTable *memo_table; + + memo_table = E_MEMO_TABLE (selectable); + + e_selectable_copy_clipboard (selectable); + delete_selected_components (memo_table); +} + +/* Helper for memo_table_copy_clipboard() */ +static void +copy_row_cb (gint model_row, gpointer data) +{ + EMemoTable *memo_table; + ECalModelComponent *comp_data; + ECalModel *model; + gchar *comp_str; + icalcomponent *child; + + memo_table = E_MEMO_TABLE (data); + + g_return_if_fail (memo_table->tmp_vcal != NULL); + + model = e_memo_table_get_model (memo_table); + comp_data = e_cal_model_get_component_at (model, model_row); + if (comp_data == NULL) + return; + + /* Add timezones to the VCALENDAR component. */ + e_cal_util_add_timezones_from_component ( + memo_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 ( + memo_table->tmp_vcal, + icalcomponent_new_clone (child)); + icalcomponent_free (child); + } + g_free (comp_str); +} + +static void +memo_table_copy_clipboard (ESelectable *selectable) +{ + EMemoTable *memo_table; + GtkClipboard *clipboard; + gchar *comp_str; + + memo_table = E_MEMO_TABLE (selectable); + + /* Create a temporary VCALENDAR object. */ + memo_table->tmp_vcal = e_cal_util_new_top_level (); + + e_table_selected_row_foreach ( + E_TABLE (memo_table), copy_row_cb, memo_table); + comp_str = icalcomponent_as_ical_string_r (memo_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 (memo_table->tmp_vcal); + memo_table->tmp_vcal = NULL; +} + +/* Helper for memo_table_paste_clipboard() */ +static void +clipboard_get_calendar_data (EMemoTable *memo_table, + const gchar *text) +{ + icalcomponent *icalcomp; + gchar *uid; + ECalComponent *comp; + ECal *client; + ECalModel *model; + icalcomponent_kind kind; + const gchar *status_message; + + g_return_if_fail (E_IS_MEMO_TABLE (memo_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_memo_table_get_model (memo_table); + client = e_cal_model_get_default_client (model); + + status_message = _("Updating objects"); + memo_table_emit_status_message (memo_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); + } + + memo_table_emit_status_message (memo_table, NULL, -1.0); +} + +static void +memo_table_paste_clipboard (ESelectable *selectable) +{ + EMemoTable *memo_table; + GtkClipboard *clipboard; + GnomeCanvasItem *item; + GnomeCanvas *table_canvas; + + memo_table = E_MEMO_TABLE (selectable); + + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + + table_canvas = E_TABLE (memo_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 (memo_table, calendar_source); + g_free (calendar_source); + } +} + +static void +memo_table_select_all (ESelectable *selectable) +{ + e_table_select_all (E_TABLE (selectable)); +} + +static void memo_table_class_init (EMemoTableClass *class) { GObjectClass *object_class; @@ -720,6 +1012,16 @@ memo_table_init (EMemoTable *memo_table) memo_table->priv = E_MEMO_TABLE_GET_PRIVATE (memo_table); } +static void +memo_table_selectable_init (ESelectableInterface *interface) +{ + interface->update_actions = memo_table_update_actions; + interface->cut_clipboard = memo_table_cut_clipboard; + interface->copy_clipboard = memo_table_copy_clipboard; + interface->paste_clipboard = memo_table_paste_clipboard; + interface->select_all = memo_table_select_all; +} + GType e_memo_table_get_type (void) { @@ -739,8 +1041,17 @@ e_memo_table_get_type (void) NULL /* value_table */ }; + static const GInterfaceInfo selectable_info = { + (GInterfaceInitFunc) memo_table_selectable_init, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + type = g_type_register_static ( E_TABLE_TYPE, "EMemoTable", &type_info, 0); + + g_type_add_interface_static ( + type, E_TYPE_SELECTABLE, &selectable_info); } return type; @@ -847,33 +1158,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 (EMemoTable *memo_table) -{ - GSList *objs, *l; - const gchar *status_message; - - objs = e_memo_table_get_selected (memo_table); - - status_message = _("Deleting selected objects"); - memo_table_emit_status_message (memo_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_JOURNAL); - g_clear_error (&error); - } - - memo_table_emit_status_message (memo_table, NULL, -1.0); - - g_slist_free (objs); -} - /** * e_memo_table_delete_selected: * @memo_table: A memo table. @@ -938,210 +1222,6 @@ e_memo_table_get_selected (EMemoTable *memo_table) return closure.objects; } -/** - * e_memo_table_cut_clipboard: - * @memo_table: A calendar table. - * - * Cuts selected tasks in the given calendar table - */ -void -e_memo_table_cut_clipboard (EMemoTable *memo_table) -{ - g_return_if_fail (E_IS_MEMO_TABLE (memo_table)); - - e_memo_table_copy_clipboard (memo_table); - delete_selected_components (memo_table); -} - -/* callback for e_table_selected_row_foreach */ -static void -copy_row_cb (gint model_row, gpointer data) -{ - EMemoTable *memo_table; - ECalModelComponent *comp_data; - ECalModel *model; - gchar *comp_str; - icalcomponent *child; - - memo_table = E_MEMO_TABLE (data); - - g_return_if_fail (memo_table->tmp_vcal != NULL); - - model = e_memo_table_get_model (memo_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 (memo_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 (memo_table->tmp_vcal, - icalcomponent_new_clone (child)); - icalcomponent_free (child); - } - g_free (comp_str); -} - -/** - * e_memo_table_copy_clipboard: - * @memo_table: A calendar table. - * - * Copies selected tasks into the clipboard - */ -void -e_memo_table_copy_clipboard (EMemoTable *memo_table) -{ - GtkClipboard *clipboard; - gchar *comp_str; - - g_return_if_fail (E_IS_MEMO_TABLE (memo_table)); - - /* create temporary VCALENDAR object */ - memo_table->tmp_vcal = e_cal_util_new_top_level (); - - e_table_selected_row_foreach ( - E_TABLE (memo_table), copy_row_cb, memo_table); - comp_str = icalcomponent_as_ical_string_r (memo_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 (memo_table->tmp_vcal); - g_free (comp_str); - memo_table->tmp_vcal = NULL; -} - -static void -clipboard_get_calendar_data (EMemoTable *memo_table, const gchar *text) -{ - icalcomponent *icalcomp; - gchar *uid; - ECalComponent *comp; - ECal *client; - ECalModel *model; - icalcomponent_kind kind; - const gchar *status_message; - - g_return_if_fail (E_IS_MEMO_TABLE (memo_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_memo_table_get_model (memo_table); - client = e_cal_model_get_default_client (model); - - status_message = _("Updating objects"); - memo_table_emit_status_message (memo_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); - } - - memo_table_emit_status_message (memo_table, NULL, -1.0); -} - -/** - * e_memo_table_paste_clipboard: - * @memo_table: A calendar table. - * - * Pastes tasks currently in the clipboard into the given calendar table - */ -void -e_memo_table_paste_clipboard (EMemoTable *memo_table) -{ - GtkClipboard *clipboard; - GnomeCanvasItem *item; - GnomeCanvas *table_canvas; - - g_return_if_fail (E_IS_MEMO_TABLE (memo_table)); - - clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - - table_canvas = E_TABLE (memo_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 (memo_table, calendar_source); - g_free (calendar_source); - } -} - /* Returns the current time, for the ECellDateEdit items. FIXME: Should probably use the timezone of the item rather than the current timezone, though that may be difficult to get from here. */ diff --git a/calendar/gui/e-memo-table.h b/calendar/gui/e-memo-table.h index 4d4347db4a..b55ddc5e66 100644 --- a/calendar/gui/e-memo-table.h +++ b/calendar/gui/e-memo-table.h @@ -106,11 +106,6 @@ void e_memo_table_set_use_24_hour_format void e_memo_table_delete_selected (EMemoTable *memo_table); GSList * e_memo_table_get_selected (EMemoTable *memo_table); -/* Clipboard related functions */ -void e_memo_table_cut_clipboard (EMemoTable *memo_table); -void e_memo_table_copy_clipboard (EMemoTable *memo_table); -void e_memo_table_paste_clipboard (EMemoTable *memo_table); - G_END_DECLS #endif /* _E_MEMO_TABLE_H_ */ diff --git a/calendar/gui/gnome-cal.h b/calendar/gui/gnome-cal.h index 0cc528fe3c..197396dbd6 100644 --- a/calendar/gui/gnome-cal.h +++ b/calendar/gui/gnome-cal.h @@ -33,7 +33,7 @@ #include <libecal/e-cal.h> #include <shell/e-shell-settings.h> -#include "e-calendar-table.h" +#include "e-cal-model.h" /* Standard GObject macros */ #define GNOME_TYPE_CALENDAR \ diff --git a/calendar/gui/goto.c b/calendar/gui/goto.c index 86f06f32dc..569c15f38f 100644 --- a/calendar/gui/goto.c +++ b/calendar/gui/goto.c @@ -26,6 +26,7 @@ #include <config.h> #include <gtk/gtk.h> +#include "e-util/e-util.h" #include "e-util/e-util-private.h" #include "calendar-config.h" #include "tag-calendar.h" diff --git a/calendar/gui/print.h b/calendar/gui/print.h index 39d5608222..5217c473a1 100644 --- a/calendar/gui/print.h +++ b/calendar/gui/print.h @@ -25,6 +25,7 @@ #ifndef PRINT_H #define PRINT_H +#include <table/e-table.h> #include "calendar/gui/gnome-cal.h" typedef enum { |