diff options
74 files changed, 3140 insertions, 2049 deletions
diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c index a48ea8c351..91fdb16e4b 100644 --- a/addressbook/gui/widgets/e-addressbook-view.c +++ b/addressbook/gui/widgets/e-addressbook-view.c @@ -28,6 +28,7 @@ #include <table/e-table-model.h> #include <table/e-cell-date.h> #include <misc/e-gui-utils.h> +#include <misc/e-selectable.h> #include <widgets/menus/gal-view-factory-etable.h> #include <filter/e-rule-editor.h> #include <widgets/menus/gal-view-etable.h> @@ -539,6 +540,140 @@ addressbook_view_constructed (GObject *object) } static void +addressbook_view_update_actions (ESelectable *selectable, + EFocusTracker *focus_tracker, + GdkAtom *clipboard_targets, + gint n_clipboard_targets) +{ + EAddressbookView *view; + EAddressbookModel *model; + ESelectionModel *selection_model; + GtkAction *action; + gboolean clipboard_has_directory; + gboolean source_is_editable; + gboolean sensitive; + const gchar *tooltip; + gint n_contacts; + gint n_selected; + + view = E_ADDRESSBOOK_VIEW (selectable); + model = e_addressbook_view_get_model (view); + selection_model = e_addressbook_view_get_selection_model (view); + + source_is_editable = e_addressbook_model_get_editable (model); + n_contacts = (selection_model != NULL) ? + e_selection_model_row_count (selection_model) : 0; + n_selected = (selection_model != NULL) ? + e_selection_model_selected_count (selection_model) : 0; + + clipboard_has_directory = (clipboard_targets != NULL) && + e_targets_include_directory ( + clipboard_targets, n_clipboard_targets); + + action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); + sensitive = source_is_editable && (n_selected > 0); + tooltip = _("Cut selected contacts 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 contacts 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 = source_is_editable && clipboard_has_directory; + tooltip = _("Paste contacts 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 = (n_contacts > 0); + tooltip = _("Select all visible contacts"); + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, tooltip); +} + +static void +addressbook_view_cut_clipboard (ESelectable *selectable) +{ + EAddressbookView *view; + + view = E_ADDRESSBOOK_VIEW (selectable); + + e_selectable_copy_clipboard (selectable); + e_addressbook_view_delete_selection (view, FALSE); +} + +static void +addressbook_view_copy_clipboard (ESelectable *selectable) +{ + EAddressbookView *view; + GtkClipboard *clipboard; + GList *contact_list; + gchar *string; + + view = E_ADDRESSBOOK_VIEW (selectable); + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + + contact_list = e_addressbook_view_get_selected (view); + + string = eab_contact_list_to_string (contact_list); + e_clipboard_set_directory (clipboard, string, -1); + g_free (string); + + g_list_foreach (contact_list, (GFunc) g_object_unref, NULL); + g_list_free (contact_list); +} + +static void +addressbook_view_paste_clipboard (ESelectable *selectable) +{ + EBook *book; + EAddressbookView *view; + EAddressbookModel *model; + GtkClipboard *clipboard; + GList *contact_list, *iter; + gchar *string; + + view = E_ADDRESSBOOK_VIEW (selectable); + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + + if (!e_clipboard_wait_is_directory_available (clipboard)) + return; + + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); + + string = e_clipboard_wait_for_directory (clipboard); + contact_list = eab_contact_list_from_string (string); + g_free (string); + + for (iter = contact_list; iter != NULL; iter = iter->next) { + EContact *contact = iter->data; + + eab_merging_book_add_contact (book, contact, NULL, NULL); + } + + g_list_foreach (contact_list, (GFunc) g_object_unref, NULL); + g_list_free (contact_list); +} + +static void +addressbook_view_select_all (ESelectable *selectable) +{ + EAddressbookView *view; + ESelectionModel *selection_model; + + view = E_ADDRESSBOOK_VIEW (selectable); + selection_model = e_addressbook_view_get_selection_model (view); + + if (selection_model != NULL) + e_selection_model_select_all (selection_model); +} + +static void addressbook_view_class_init (EAddressbookViewClass *class) { GObjectClass *object_class; @@ -641,6 +776,16 @@ addressbook_view_init (EAddressbookView *view) GTK_SCROLLED_WINDOW (view), GTK_SHADOW_IN); } +static void +addressbook_view_selectable_init (ESelectableInterface *interface) +{ + interface->update_actions = addressbook_view_update_actions; + interface->cut_clipboard = addressbook_view_cut_clipboard; + interface->copy_clipboard = addressbook_view_copy_clipboard; + interface->paste_clipboard = addressbook_view_paste_clipboard; + interface->select_all = addressbook_view_select_all; +} + GType e_addressbook_view_get_type (void) { @@ -660,9 +805,18 @@ e_addressbook_view_get_type (void) NULL /* value_table */ }; + static const GInterfaceInfo selectable_info = { + (GInterfaceInitFunc) addressbook_view_selectable_init, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + type = g_type_register_static ( GTK_TYPE_SCROLLED_WINDOW, "EAddressbookView", &type_info, 0); + + g_type_add_interface_static ( + type, E_TYPE_SELECTABLE, &selectable_info); } return type; @@ -1238,82 +1392,6 @@ e_addressbook_view_view (EAddressbookView *view) } void -e_addressbook_view_cut (EAddressbookView *view) -{ - g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - - e_addressbook_view_copy (view); - e_addressbook_view_delete_selection (view, FALSE); -} - -void -e_addressbook_view_copy (EAddressbookView *view) -{ - GtkClipboard *clipboard; - GList *contact_list; - gchar *string; - - g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - - clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - - contact_list = e_addressbook_view_get_selected (view); - - string = eab_contact_list_to_string (contact_list); - e_clipboard_set_directory (clipboard, string, -1); - g_free (string); - - g_list_foreach (contact_list, (GFunc) g_object_unref, NULL); - g_list_free (contact_list); -} - -void -e_addressbook_view_paste (EAddressbookView *view) -{ - EBook *book; - EAddressbookModel *model; - GtkClipboard *clipboard; - GList *contact_list, *iter; - gchar *string; - - g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - - clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - - if (!e_clipboard_wait_is_directory_available (clipboard)) - return; - - model = e_addressbook_view_get_model (view); - book = e_addressbook_model_get_book (model); - - string = e_clipboard_wait_for_directory (clipboard); - contact_list = eab_contact_list_from_string (string); - g_free (string); - - for (iter = contact_list; iter != NULL; iter = iter->next) { - EContact *contact = iter->data; - - eab_merging_book_add_contact (book, contact, NULL, NULL); - } - - g_list_foreach (contact_list, (GFunc) g_object_unref, NULL); - g_list_free (contact_list); -} - -void -e_addressbook_view_select_all (EAddressbookView *view) -{ - ESelectionModel *model; - - g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - - model = e_addressbook_view_get_selection_model (view); - g_return_if_fail (model); - - e_selection_model_select_all (model); -} - -void e_addressbook_view_show_all (EAddressbookView *view) { g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); diff --git a/addressbook/gui/widgets/e-addressbook-view.h b/addressbook/gui/widgets/e-addressbook-view.h index 319d060b89..55f114a538 100644 --- a/addressbook/gui/widgets/e-addressbook-view.h +++ b/addressbook/gui/widgets/e-addressbook-view.h @@ -103,10 +103,6 @@ void e_addressbook_view_print (EAddressbookView *view, void e_addressbook_view_delete_selection (EAddressbookView *view, gboolean is_delete); -void e_addressbook_view_cut (EAddressbookView *view); -void e_addressbook_view_copy (EAddressbookView *view); -void e_addressbook_view_paste (EAddressbookView *view); -void e_addressbook_view_select_all (EAddressbookView *view); void e_addressbook_view_show_all (EAddressbookView *view); void e_addressbook_view_stop (EAddressbookView *view); void e_addressbook_view_copy_to_folder 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 { diff --git a/composer/e-composer-private.c b/composer/e-composer-private.c index d16afa32f0..8dfdeeb4b0 100644 --- a/composer/e-composer-private.c +++ b/composer/e-composer-private.c @@ -83,12 +83,13 @@ composer_setup_recent_menu (EMsgComposer *composer) } void -e_composer_private_init (EMsgComposer *composer) +e_composer_private_constructed (EMsgComposer *composer) { EMsgComposerPrivate *priv = composer->priv; - + EFocusTracker *focus_tracker; GtkhtmlEditor *editor; GtkUIManager *ui_manager; + GtkAction *action; GtkWidget *container; GtkWidget *widget; GtkWidget *send_widget; @@ -157,6 +158,24 @@ e_composer_private_init (EMsgComposer *composer) g_clear_error (&error); } + /* Configure an EFocusTracker to manage selection actions. */ + + focus_tracker = e_focus_tracker_new (GTK_WINDOW (composer)); + + action = gtkhtml_editor_get_action (editor, "cut"); + e_focus_tracker_set_cut_clipboard_action (focus_tracker, action); + + action = gtkhtml_editor_get_action (editor, "copy"); + e_focus_tracker_set_copy_clipboard_action (focus_tracker, action); + + action = gtkhtml_editor_get_action (editor, "paste"); + e_focus_tracker_set_paste_clipboard_action (focus_tracker, action); + + action = gtkhtml_editor_get_action (editor, "select-all"); + e_focus_tracker_set_select_all_action (focus_tracker, action); + + priv->focus_tracker = focus_tracker; + /* Construct the header table. */ container = editor->vbox; @@ -314,6 +333,11 @@ e_composer_private_dispose (EMsgComposer *composer) composer->priv->attachment_paned = NULL; } + if (composer->priv->focus_tracker != NULL) { + g_object_unref (composer->priv->focus_tracker); + composer->priv->focus_tracker = NULL; + } + if (composer->priv->window_group != NULL) { g_object_unref (composer->priv->window_group); composer->priv->window_group = NULL; diff --git a/composer/e-composer-private.h b/composer/e-composer-private.h index 54837b9093..bab8dd160a 100644 --- a/composer/e-composer-private.h +++ b/composer/e-composer-private.h @@ -94,6 +94,7 @@ struct _EMsgComposerPrivate { GtkWidget *header_table; GtkWidget *attachment_paned; + EFocusTracker *focus_tracker; GtkWindowGroup *window_group; GtkActionGroup *charset_actions; @@ -130,7 +131,7 @@ struct _EMsgComposerPrivate { gboolean mail_sent; }; -void e_composer_private_init (EMsgComposer *composer); +void e_composer_private_constructed (EMsgComposer *composer); void e_composer_private_dispose (EMsgComposer *composer); void e_composer_private_finalize (EMsgComposer *composer); diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c index 6477936011..eed3893d95 100644 --- a/composer/e-msg-composer.c +++ b/composer/e-msg-composer.c @@ -55,6 +55,7 @@ #include "shell/e-shell.h" #include "em-format/em-format.h" #include "em-format/em-format-quote.h" +#include "misc/e-web-view.h" #include <camel/camel-charset-map.h> #include <camel/camel-cipher-context.h> @@ -92,6 +93,11 @@ ((obj), E_TYPE_MSG_COMPOSER, EMsgComposerPrivate)) enum { + PROP_0, + PROP_FOCUS_TRACKER +}; + +enum { SEND, SAVE_DRAFT, PRINT, @@ -118,6 +124,14 @@ static void handle_multipart_alternative (EMsgComposer *composer, CamelMultipart static void handle_multipart_encrypted (EMsgComposer *composer, CamelMimePart *multipart, gint depth); static void handle_multipart_signed (EMsgComposer *composer, CamelMultipart *multipart, gint depth); +static void msg_composer_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection, + guint info, + guint time); + /** * emcu_part_to_html: * @part: @@ -1514,32 +1528,90 @@ msg_composer_notify_header_cb (EMsgComposer *composer) gtkhtml_editor_set_changed (editor, TRUE); } -static GObject * -msg_composer_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_properties) +static void +msg_composer_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FOCUS_TRACKER: + g_value_set_object ( + value, e_msg_composer_get_focus_tracker ( + E_MSG_COMPOSER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +msg_composer_dispose (GObject *object) +{ + EMsgComposer *composer = E_MSG_COMPOSER (object); + + e_composer_private_dispose (composer); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +msg_composer_finalize (GObject *object) +{ + EMsgComposer *composer = E_MSG_COMPOSER (object); + + e_composer_autosave_unregister (composer); + e_composer_private_finalize (composer); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +msg_composer_constructed (GObject *object) { EShell *shell; EShellSettings *shell_settings; - GObject *object; + GtkhtmlEditor *editor; EMsgComposer *composer; + EAttachmentView *view; + EAttachmentStore *store; + EComposerHeaderTable *table; + GdkDragAction drag_actions; + GtkTargetList *target_list; + GtkTargetEntry *targets; + GtkUIManager *ui_manager; GtkToggleAction *action; + GtkHTML *html; GArray *array; + const gchar *id; gboolean active; guint binding_id; + gint n_targets; - /* Chain up to parent's constructor() method. */ - object = G_OBJECT_CLASS (parent_class)->constructor ( - type, n_construct_properties, construct_properties); - + editor = GTKHTML_EDITOR (object); composer = E_MSG_COMPOSER (object); - array = composer->priv->gconf_bridge_binding_ids; shell = e_shell_get_default (); shell_settings = e_shell_get_shell_settings (shell); + e_composer_private_constructed (composer); + + html = gtkhtml_editor_get_html (editor); + ui_manager = gtkhtml_editor_get_ui_manager (editor); + view = e_msg_composer_get_attachment_view (composer); + table = E_COMPOSER_HEADER_TABLE (composer->priv->header_table); + + gtk_window_set_title (GTK_WINDOW (composer), _("Compose Message")); + gtk_window_set_icon_name (GTK_WINDOW (composer), "mail-message-new"); + + e_shell_watch_window (shell, GTK_WINDOW (object)); + /* Restore Persistent State */ + array = composer->priv->gconf_bridge_binding_ids; + binding_id = gconf_bridge_bind_property ( gconf_bridge_get (), COMPOSER_GCONF_CURRENT_FOLDER_KEY, @@ -1563,32 +1635,77 @@ msg_composer_constructor (GType type, shell_settings, "composer-request-receipt"); gtk_toggle_action_set_active (action, active); - e_shell_watch_window (shell, GTK_WINDOW (object)); + /* Drag-and-Drop Support */ - return object; -} + target_list = e_attachment_view_get_target_list (view); + drag_actions = e_attachment_view_get_drag_actions (view); -static void -msg_composer_dispose (GObject *object) -{ - EMsgComposer *composer = E_MSG_COMPOSER (object); + targets = gtk_target_table_new_from_list (target_list, &n_targets); - e_composer_private_dispose (composer); + gtk_drag_dest_set ( + GTK_WIDGET (composer), GTK_DEST_DEFAULT_ALL, + targets, n_targets, drag_actions); - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} + g_signal_connect ( + html, "drag-data-received", + G_CALLBACK (msg_composer_drag_data_received), NULL); -static void -msg_composer_finalize (GObject *object) -{ - EMsgComposer *composer = E_MSG_COMPOSER (object); + gtk_target_table_free (targets, n_targets); - e_composer_autosave_unregister (composer); - e_composer_private_finalize (composer); + /* Configure Headers */ - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); + e_composer_header_table_set_account_list ( + table, e_get_account_list ()); + e_composer_header_table_set_signature_list ( + table, e_get_signature_list ()); + + g_signal_connect_swapped ( + table, "notify::account", + G_CALLBACK (msg_composer_account_changed_cb), composer); + g_signal_connect_swapped ( + table, "notify::destinations-bcc", + G_CALLBACK (msg_composer_notify_header_cb), composer); + g_signal_connect_swapped ( + table, "notify::destinations-cc", + G_CALLBACK (msg_composer_notify_header_cb), composer); + g_signal_connect_swapped ( + table, "notify::destinations-to", + G_CALLBACK (msg_composer_notify_header_cb), composer); + g_signal_connect_swapped ( + table, "notify::reply-to", + G_CALLBACK (msg_composer_notify_header_cb), composer); + g_signal_connect_swapped ( + table, "notify::signature", + G_CALLBACK (e_msg_composer_show_sig_file), composer); + g_signal_connect_swapped ( + table, "notify::subject", + G_CALLBACK (msg_composer_subject_changed_cb), composer); + g_signal_connect_swapped ( + table, "notify::subject", + G_CALLBACK (msg_composer_notify_header_cb), composer); + + msg_composer_account_changed_cb (composer); + + /* Attachments */ + + store = e_attachment_view_get_store (view); + + g_signal_connect_swapped ( + store, "row-deleted", + G_CALLBACK (attachment_store_changed_cb), composer); + + g_signal_connect_swapped ( + store, "row-inserted", + G_CALLBACK (attachment_store_changed_cb), composer); + + e_composer_autosave_register (composer); + + /* Initialization may have tripped the "changed" state. */ + gtkhtml_editor_set_changed (editor, FALSE); + + id = "org.gnome.evolution.composer"; + e_plugin_ui_register_manager (ui_manager, id, composer); + e_plugin_ui_enable_manager (ui_manager, id); } static void @@ -2045,9 +2162,10 @@ msg_composer_class_init (EMsgComposerClass *class) g_type_class_add_private (class, sizeof (EMsgComposerPrivate)); object_class = G_OBJECT_CLASS (class); - object_class->constructor = msg_composer_constructor; + object_class->get_property = msg_composer_get_property; object_class->dispose = msg_composer_dispose; object_class->finalize = msg_composer_finalize; + object_class->constructed = msg_composer_constructed; gtk_object_class = GTK_OBJECT_CLASS (class); gtk_object_class->destroy = msg_composer_destroy; @@ -2071,6 +2189,16 @@ msg_composer_class_init (EMsgComposerClass *class) editor_class->object_deleted = msg_composer_object_deleted; editor_class->uri_requested = msg_composer_uri_requested; + 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)); + signals[SEND] = g_signal_new ( "send", G_OBJECT_CLASS_TYPE (class), @@ -2100,103 +2228,8 @@ msg_composer_class_init (EMsgComposerClass *class) static void msg_composer_init (EMsgComposer *composer) { - EAttachmentView *view; - EAttachmentStore *store; - EComposerHeaderTable *table; - GdkDragAction drag_actions; - GtkTargetList *target_list; - GtkTargetEntry *targets; - GtkUIManager *ui_manager; - GtkhtmlEditor *editor; - GtkHTML *html; - const gchar *id; - gint n_targets; - composer->lite = composer_lite; composer->priv = E_MSG_COMPOSER_GET_PRIVATE (composer); - - e_composer_private_init (composer); - - editor = GTKHTML_EDITOR (composer); - html = gtkhtml_editor_get_html (editor); - ui_manager = gtkhtml_editor_get_ui_manager (editor); - view = e_msg_composer_get_attachment_view (composer); - table = E_COMPOSER_HEADER_TABLE (composer->priv->header_table); - - gtk_window_set_title (GTK_WINDOW (composer), _("Compose Message")); - gtk_window_set_icon_name (GTK_WINDOW (composer), "mail-message-new"); - - /* Drag-and-Drop Support */ - - target_list = e_attachment_view_get_target_list (view); - drag_actions = e_attachment_view_get_drag_actions (view); - - targets = gtk_target_table_new_from_list (target_list, &n_targets); - - gtk_drag_dest_set ( - GTK_WIDGET (composer), GTK_DEST_DEFAULT_ALL, - targets, n_targets, drag_actions); - - g_signal_connect ( - html, "drag-data-received", - G_CALLBACK (msg_composer_drag_data_received), NULL); - - gtk_target_table_free (targets, n_targets); - - /* Configure Headers */ - - e_composer_header_table_set_account_list ( - table, e_get_account_list ()); - e_composer_header_table_set_signature_list ( - table, e_get_signature_list ()); - - g_signal_connect_swapped ( - table, "notify::account", - G_CALLBACK (msg_composer_account_changed_cb), composer); - g_signal_connect_swapped ( - table, "notify::destinations-bcc", - G_CALLBACK (msg_composer_notify_header_cb), composer); - g_signal_connect_swapped ( - table, "notify::destinations-cc", - G_CALLBACK (msg_composer_notify_header_cb), composer); - g_signal_connect_swapped ( - table, "notify::destinations-to", - G_CALLBACK (msg_composer_notify_header_cb), composer); - g_signal_connect_swapped ( - table, "notify::reply-to", - G_CALLBACK (msg_composer_notify_header_cb), composer); - g_signal_connect_swapped ( - table, "notify::signature", - G_CALLBACK (e_msg_composer_show_sig_file), composer); - g_signal_connect_swapped ( - table, "notify::subject", - G_CALLBACK (msg_composer_subject_changed_cb), composer); - g_signal_connect_swapped ( - table, "notify::subject", - G_CALLBACK (msg_composer_notify_header_cb), composer); - - msg_composer_account_changed_cb (composer); - - /* Attachments */ - - store = e_attachment_view_get_store (view); - - g_signal_connect_swapped ( - store, "row-deleted", - G_CALLBACK (attachment_store_changed_cb), composer); - - g_signal_connect_swapped ( - store, "row-inserted", - G_CALLBACK (attachment_store_changed_cb), composer); - - e_composer_autosave_register (composer); - - /* Initialization may have tripped the "changed" state. */ - gtkhtml_editor_set_changed (editor, FALSE); - - id = "org.gnome.evolution.composer"; - e_plugin_ui_register_manager (ui_manager, id, composer); - e_plugin_ui_enable_manager (ui_manager, id); } GType @@ -2237,7 +2270,9 @@ e_msg_composer_get_type (void) EMsgComposer * e_msg_composer_new (void) { - return g_object_new (E_TYPE_MSG_COMPOSER, NULL); + return g_object_new ( + E_TYPE_MSG_COMPOSER, + "html", e_web_view_new (), NULL); } void @@ -2265,6 +2300,14 @@ e_msg_composer_lite_new (void) return composer; } +EFocusTracker * +e_msg_composer_get_focus_tracker (EMsgComposer *composer) +{ + g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL); + + return composer->priv->focus_tracker; +} + static void e_msg_composer_set_pending_body (EMsgComposer *composer, gchar *text, diff --git a/composer/e-msg-composer.h b/composer/e-msg-composer.h index 74128e0c0f..c55237ce52 100644 --- a/composer/e-msg-composer.h +++ b/composer/e-msg-composer.h @@ -31,6 +31,7 @@ #include <libebook/e-destination.h> #include <gtkhtml-editor.h> #include <misc/e-attachment-view.h> +#include <misc/e-focus-tracker.h> #include "e-composer-header-table.h" @@ -78,6 +79,7 @@ EMsgComposer * e_msg_composer_new_with_message (CamelMimeMessage *msg); EMsgComposer * e_msg_composer_new_from_url (const gchar *url); EMsgComposer * e_msg_composer_new_redirect (CamelMimeMessage *message, const gchar *resent_from); +EFocusTracker * e_msg_composer_get_focus_tracker(EMsgComposer *composer); CamelSession * e_msg_composer_get_session (EMsgComposer *composer); void e_msg_composer_send (EMsgComposer *composer); diff --git a/configure.ac b/configure.ac index 1d97d640a2..ecf88edd00 100644 --- a/configure.ac +++ b/configure.ac @@ -46,7 +46,7 @@ m4_define([gtk_minimum_version], [2.16.0]) m4_define([eds_minimum_version], [evo_version]) m4_define([gnome_icon_theme_minimum_version], [2.19.91]) m4_define([gnome_desktop_minimum_version], [2.26.0]) -m4_define([libgtkhtml_minimum_version], [3.29.2]) +m4_define([libgtkhtml_minimum_version], [3.29.5]) m4_define([gconf_minimum_version], [2.0.0]) dnl XXX Just a Guess m4_define([libgnomecanvas_minimum_version], [2.0.0]) dnl XXX Just a Guess m4_define([libxml_minimum_version], [2.7.3]) diff --git a/doc/reference/shell/tmpl/e-shell-window.sgml b/doc/reference/shell/tmpl/e-shell-window.sgml index 33a5928476..89da4a143c 100644 --- a/doc/reference/shell/tmpl/e-shell-window.sgml +++ b/doc/reference/shell/tmpl/e-shell-window.sgml @@ -28,6 +28,11 @@ EShellWindow </para> +<!-- ##### ARG EShellWindow:focus-tracker ##### --> +<para> + +</para> + <!-- ##### ARG EShellWindow:geometry ##### --> <para> diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c index 6dae4ded13..9b7cc4d887 100644 --- a/mail/e-mail-reader.c +++ b/mail/e-mail-reader.c @@ -166,19 +166,6 @@ action_mail_check_for_junk_cb (GtkAction *action, } static void -action_mail_clipboard_copy_cb (GtkAction *action, - EMailReader *reader) -{ - EMFormatHTMLDisplay *html_display; - EWebView *web_view; - - html_display = e_mail_reader_get_html_display (reader); - web_view = E_WEB_VIEW (EM_FORMAT_HTML (html_display)->html); - - e_web_view_clipboard_copy (web_view); -} - -static void action_mail_copy_cb (GtkAction *action, EMailReader *reader) { @@ -875,26 +862,6 @@ action_mail_search_folder_from_subject_cb (GtkAction *action, } static void -action_mail_select_all_cb (GtkAction *action, - EMailReader *reader) -{ - EMFormatHTMLDisplay *html_display; - EWebView *web_view; - const gchar *action_name; - gboolean selection_active; - - html_display = e_mail_reader_get_html_display (reader); - web_view = E_WEB_VIEW (EM_FORMAT_HTML (html_display)->html); - - e_web_view_select_all (web_view); - - action_name = "mail-clipboard-copy"; - action = e_mail_reader_get_action (reader, action_name); - selection_active = e_web_view_is_selection_active (web_view); - gtk_action_set_sensitive (action, selection_active); -} - -static void action_mail_show_all_headers_cb (GtkToggleAction *action, EMailReader *reader) { @@ -1112,13 +1079,6 @@ static GtkActionEntry mail_reader_entries[] = { N_("Filter the selected messages for junk status"), G_CALLBACK (action_mail_check_for_junk_cb) }, - { "mail-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy selected messages to the clipboard"), - G_CALLBACK (action_mail_clipboard_copy_cb) }, - { "mail-copy", "mail-copy", N_("_Copy to Folder..."), @@ -1441,13 +1401,6 @@ static GtkActionEntry mail_reader_entries[] = { N_("Create a search folder for this subject"), G_CALLBACK (action_mail_search_folder_from_subject_cb) }, - { "mail-select-all", - NULL, - N_("Select _All Text"), - "<Shift><Control>x", - N_("Select all the text in a message"), - G_CALLBACK (action_mail_select_all_cb) }, - { "mail-show-source", NULL, N_("_Message Source"), @@ -1544,10 +1497,6 @@ static GtkActionEntry mail_reader_entries[] = { static EPopupActionEntry mail_reader_popup_entries[] = { - { "mail-popup-clipboard-copy", - NULL, - "mail-clipboard-copy" }, - { "mail-popup-copy", NULL, "mail-copy" }, @@ -1644,25 +1593,6 @@ static GtkToggleActionEntry mail_reader_toggle_entries[] = { FALSE } }; -static gboolean -mail_reader_button_release_event_cb (EMailReader *reader, - GdkEventButton *button, - GtkHTML *html) -{ - GtkAction *action; - EWebView *web_view; - const gchar *action_name; - gboolean selection_active; - - web_view = E_WEB_VIEW (html); - action_name = "mail-clipboard-copy"; - action = e_mail_reader_get_action (reader, action_name); - selection_active = e_web_view_is_selection_active (web_view); - gtk_action_set_sensitive (action, selection_active); - - return FALSE; -} - static void mail_reader_double_click_cb (EMailReader *reader, gint row, @@ -2377,11 +2307,6 @@ mail_reader_update_actions (EMailReader *reader) action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); - action_name = "mail-select-all"; - sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); - action_name = "mail-show-source"; sensitive = single_message_selected; action = e_mail_reader_get_action (reader, action_name); @@ -2585,10 +2510,6 @@ e_mail_reader_init (EMailReader *reader) /* Fine tuning. */ - action_name = "mail-clipboard-copy"; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, FALSE); - action_name = "mail-delete"; action = e_mail_reader_get_action (reader, action_name); g_object_set (action, "short-label", _("Delete"), NULL); @@ -2661,10 +2582,6 @@ e_mail_reader_init (EMailReader *reader) /* Connect signals. */ g_signal_connect_swapped ( - web_view, "button-release-event", - G_CALLBACK (mail_reader_button_release_event_cb), reader); - - g_signal_connect_swapped ( web_view, "key-press-event", G_CALLBACK (mail_reader_key_press_event_cb), reader); diff --git a/mail/message-list.c b/mail/message-list.c index dcf2e4fed1..49a839a7ba 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -52,6 +52,7 @@ #include "e-util/e-util.h" #include "misc/e-gui-utils.h" +#include "misc/e-selectable.h" #include "shell/e-shell.h" #include "shell/e-shell-settings.h" @@ -126,6 +127,8 @@ enum { PROP_SHELL_BACKEND }; +static gpointer parent_class; + static struct { const gchar *target; GdkAtom atom; @@ -197,8 +200,6 @@ struct _EMailAddress { typedef struct _EMailAddress EMailAddress; #endif /* SMART_ADDRESS_COMPARE */ -G_DEFINE_TYPE (MessageList, message_list, E_TREE_TYPE) - static void on_cursor_activated_cmd (ETree *tree, gint row, ETreePath path, gpointer user_data); static void on_selection_changed_cmd(ETree *tree, MessageList *ml); static gint on_click (ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event, MessageList *list); @@ -718,6 +719,18 @@ message_list_select_next_thread (MessageList *ml) } } +static gboolean +message_list_select_all_timeout_cb (MessageList *message_list) +{ + ESelectionModel *etsm; + + etsm = e_tree_get_selection_model (E_TREE (message_list)); + + e_selection_model_select_all (etsm); + + return FALSE; +} + /** * message_list_select_all: * @message_list: Message List widget @@ -727,11 +740,21 @@ message_list_select_next_thread (MessageList *ml) void message_list_select_all (MessageList *message_list) { - ESelectionModel *etsm; - - etsm = e_tree_get_selection_model (E_TREE (message_list)); + g_return_if_fail (IS_MESSAGE_LIST (message_list)); - e_selection_model_select_all (etsm); + if (message_list->threaded) { + /* XXX The timeout below is added so that the execution + * thread to expand all conversation threads would + * have completed. The timeout 505 is just to ensure + * that the value is a small delta more than the + * timeout value in mail_regen_list(). */ + g_timeout_add ( + 505, (GSourceFunc) + message_list_select_all_timeout_cb, + message_list); + } else + /* If there is no threading, just select all immediately. */ + message_list_select_all_timeout_cb (message_list); } typedef struct thread_select_info { @@ -2295,9 +2318,6 @@ message_list_init (MessageList *message_list) message_list->priv = MESSAGE_LIST_GET_PRIVATE (message_list); -/* adjustment = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, G_MAXDOUBLE, 0.0, 0.0, 0.0); - gtk_scrolled_window_set_vadjustment ((GtkScrolledWindow *) message_list, adjustment);*/ - message_list->normalised_hash = g_hash_table_new_full ( g_str_hash, g_str_equal, (GDestroyNotify) NULL, @@ -2390,7 +2410,7 @@ message_list_destroy(GtkObject *object) } /* Chain up to parent's destroy() method. */ - GTK_OBJECT_CLASS (message_list_parent_class)->destroy(object); + GTK_OBJECT_CLASS (parent_class)->destroy(object); } static void @@ -2440,7 +2460,7 @@ message_list_dispose (GObject *object) } /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (message_list_parent_class)->dispose (object); + G_OBJECT_CLASS (parent_class)->dispose (object); } static void @@ -2480,7 +2500,7 @@ message_list_finalize (GObject *object) clear_selection(message_list, &priv->clipboard); /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (message_list_parent_class)->finalize (object); + G_OBJECT_CLASS (parent_class)->finalize (object); } static void @@ -2490,6 +2510,25 @@ message_list_built (MessageList *message_list) } static void +message_list_selectable_update_actions (ESelectable *selectable, + EFocusTracker *focus_tracker, + GdkAtom *clipboard_targets, + gint n_clipboard_targets) +{ + GtkAction *action; + + action = e_focus_tracker_get_select_all_action (focus_tracker); + gtk_action_set_tooltip (action, _("Select all visible messages")); + gtk_action_set_sensitive (action, TRUE); +} + +static void +message_list_selectable_select_all (ESelectable *selectable) +{ + message_list_select_all (MESSAGE_LIST (selectable)); +} + +static void message_list_class_init (MessageListClass *class) { GObjectClass *object_class; @@ -2499,6 +2538,7 @@ message_list_class_init (MessageListClass *class) for (i = 0; i < G_N_ELEMENTS (ml_drag_info); i++) ml_drag_info[i].atom = gdk_atom_intern(ml_drag_info[i].target, FALSE); + parent_class = g_type_class_peek_parent (class); g_type_class_add_private (class, sizeof (MessageListPrivate)); object_class = G_OBJECT_CLASS (class); @@ -2546,6 +2586,13 @@ message_list_class_init (MessageListClass *class) message_list_init_images (); } +static void +message_list_selectable_init (ESelectableInterface *interface) +{ + interface->update_actions = message_list_selectable_update_actions; + interface->select_all = message_list_selectable_select_all; +} + static gboolean read_boolean_with_default (GConfClient *gconf, const gchar *key, gboolean def_value) { @@ -2668,6 +2715,41 @@ message_list_construct (MessageList *message_list) G_CALLBACK (ml_tree_sorting_changed), message_list); } +GType +message_list_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (MessageListClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) message_list_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (MessageList), + 0, /* n_preallocs */ + (GInstanceInitFunc) message_list_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo selectable_info = { + (GInterfaceInitFunc) message_list_selectable_init, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + + type = g_type_register_static ( + E_TREE_TYPE, "MessageList", &type_info, 0); + + g_type_add_interface_static ( + type, E_TYPE_SELECTABLE, &selectable_info); + } + + return type; +} + /** * message_list_new: * diff --git a/mail/message-list.h b/mail/message-list.h index 72960babe1..e239944783 100644 --- a/mail/message-list.h +++ b/mail/message-list.h @@ -170,9 +170,9 @@ struct _MessageListClass { ETreeClass parent_class; /* signals - select a message */ - void (*message_selected) (MessageList *ml, const gchar *uid); - void (*message_list_built) (MessageList *ml); - void (*message_list_scrolled) (MessageList *ml); + void (*message_selected) (MessageList *message_list, const gchar *uid); + void (*message_list_built) (MessageList *message_list); + void (*message_list_scrolled) (MessageList *message_list); }; typedef enum { @@ -182,58 +182,59 @@ typedef enum { MESSAGE_LIST_SELECT_WRAP = 1<<1 /* option bit */ } MessageListSelectDirection; -GType message_list_get_type (void); -GtkWidget *message_list_new (EShellBackend *shell_backend); -EShellBackend *message_list_get_shell_backend (MessageList *message_list); -void message_list_set_folder (MessageList *message_list, CamelFolder *camel_folder, const gchar *uri, gboolean outgoing); - -void message_list_freeze(MessageList *ml); -void message_list_thaw(MessageList *ml); - -GPtrArray *message_list_get_uids(MessageList *message_list); -GPtrArray *message_list_get_selected(MessageList *ml); -void message_list_set_selected(MessageList *ml, GPtrArray *uids); - -/* select next/prev message helpers */ -gboolean message_list_select (MessageList *message_list, - MessageListSelectDirection direction, - guint32 flags, - guint32 mask); -gboolean message_list_can_select(MessageList *ml, MessageListSelectDirection direction, guint32 flags, guint32 mask); - -void message_list_select_uid (MessageList *message_list, - const gchar *uid); - -void message_list_select_next_thread (MessageList *ml); - -/* selection manipulation */ -void message_list_select_all (MessageList *ml); -void message_list_select_thread (MessageList *ml); -void message_list_select_subthread (MessageList *ml); -void message_list_invert_selection (MessageList *ml); - -/* clipboard stuff */ -void message_list_copy(MessageList *ml, gboolean cut); -void message_list_paste (MessageList *ml); - -/* info */ -guint message_list_length (MessageList *ml); -guint message_list_hidden (MessageList *ml); - -/* hide specific messages */ -void message_list_hide_add (MessageList *ml, const gchar *expr, guint lower, guint upper); -void message_list_hide_uids (MessageList *ml, GPtrArray *uids); -void message_list_hide_clear (MessageList *ml); - -void message_list_set_threaded (MessageList *ml, gboolean threaded); -void message_list_set_threaded_expand_all (MessageList *ml); -void message_list_set_threaded_collapse_all (MessageList *ml); - -void message_list_set_hidedeleted (MessageList *ml, gboolean hidedeleted); -void message_list_set_search (MessageList *ml, const gchar *search); -void message_list_ensure_message (MessageList *ml, const gchar *uid); - -void message_list_save_state (MessageList *ml); +GType message_list_get_type (void); +GtkWidget * message_list_new (EShellBackend *shell_backend); +EShellBackend * message_list_get_shell_backend (MessageList *message_list); +void message_list_set_folder (MessageList *message_list, + CamelFolder *camel_folder, + const gchar *uri, + gboolean outgoing); +void message_list_freeze (MessageList *message_list); +void message_list_thaw (MessageList *message_list); +GPtrArray * message_list_get_uids (MessageList *message_list); +GPtrArray * message_list_get_selected (MessageList *message_list); +void message_list_set_selected (MessageList *message_list, + GPtrArray *uids); +gboolean message_list_select (MessageList *message_list, + MessageListSelectDirection direction, + guint32 flags, + guint32 mask); +gboolean message_list_can_select (MessageList *message_list, + MessageListSelectDirection direction, + guint32 flags, + guint32 mask); +void message_list_select_uid (MessageList *message_list, + const gchar *uid); +void message_list_select_next_thread (MessageList *message_list); +void message_list_select_all (MessageList *message_list); +void message_list_select_thread (MessageList *message_list); +void message_list_select_subthread (MessageList *message_list); +void message_list_invert_selection (MessageList *message_list); +void message_list_copy (MessageList *message_list, + gboolean cut); +void message_list_paste (MessageList *message_list); +guint message_list_length (MessageList *message_list); +guint message_list_hidden (MessageList *message_list); +void message_list_hide_add (MessageList *message_list, + const gchar *expr, + guint lower, + guint upper); +void message_list_hide_uids (MessageList *message_list, + GPtrArray *uids); +void message_list_hide_clear (MessageList *message_list); +void message_list_set_threaded (MessageList *message_list, + gboolean threaded); +void message_list_set_threaded_expand_all + (MessageList *message_list); +void message_list_set_threaded_collapse_all + (MessageList *message_list); +void message_list_set_hidedeleted (MessageList *message_list, + gboolean hidedeleted); +void message_list_set_search (MessageList *message_list, + const gchar *search); +void message_list_ensure_message (MessageList *message_list, + const gchar *uid); +void message_list_save_state (MessageList *message_list); #define MESSAGE_LIST_LOCK(m, l) g_mutex_lock(((MessageList *)m)->l) #define MESSAGE_LIST_UNLOCK(m, l) g_mutex_unlock(((MessageList *)m)->l) diff --git a/modules/addressbook/e-book-shell-content.c b/modules/addressbook/e-book-shell-content.c index 5eb4459b7b..a7a616fc18 100644 --- a/modules/addressbook/e-book-shell-content.c +++ b/modules/addressbook/e-book-shell-content.c @@ -284,11 +284,9 @@ book_shell_content_check_state (EShellContent *shell_content) ESelectionModel *selection_model; EAddressbookModel *model; EAddressbookView *view; - GtkClipboard *clipboard; gboolean has_email = TRUE; gboolean is_contact_list = TRUE; guint32 state = 0; - gint n_contacts; gint n_selected; struct { @@ -301,8 +299,6 @@ book_shell_content_check_state (EShellContent *shell_content) model = e_addressbook_view_get_model (view); selection_model = e_addressbook_view_get_selection_model (view); - n_contacts = (selection_model != NULL) ? - e_selection_model_row_count (selection_model) : 0; n_selected = (selection_model != NULL) ? e_selection_model_selected_count (selection_model) : 0; @@ -333,8 +329,6 @@ book_shell_content_check_state (EShellContent *shell_content) foreach_data.list, foreach_data.list); } - clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - if (n_selected == 1) state |= E_BOOK_SHELL_CONTENT_SELECTION_SINGLE; if (n_selected > 1) @@ -347,10 +341,6 @@ book_shell_content_check_state (EShellContent *shell_content) state |= E_BOOK_SHELL_CONTENT_SOURCE_IS_BUSY; if (e_addressbook_model_get_editable (model)) state |= E_BOOK_SHELL_CONTENT_SOURCE_IS_EDITABLE; - if (n_contacts == 0) - state |= E_BOOK_SHELL_CONTENT_SOURCE_IS_EMPTY; - if (e_clipboard_wait_is_directory_available (clipboard)) - state |= E_BOOK_SHELL_CONTENT_CLIPBOARD_HAS_DIRECTORY; return state; } @@ -649,24 +639,3 @@ e_book_shell_content_get_searchbar (EBookShellContent *book_shell_content) return E_SHELL_SEARCHBAR (widget); } - -void -e_book_shell_content_clipboard_copy (EBookShellContent *book_shell_content) -{ - EAddressbookView *addressbook_view; - EWebView *web_view; - - g_return_if_fail (E_IS_BOOK_SHELL_CONTENT (book_shell_content)); - - web_view = E_WEB_VIEW (book_shell_content->priv->preview); - addressbook_view = - e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (addressbook_view != NULL); - - if (!GTK_WIDGET_HAS_FOCUS (web_view)) { - e_addressbook_view_copy (addressbook_view); - return; - } - - e_web_view_clipboard_copy (web_view); -} diff --git a/modules/addressbook/e-book-shell-content.h b/modules/addressbook/e-book-shell-content.h index 62cc7bf80f..6ed5b38a62 100644 --- a/modules/addressbook/e-book-shell-content.h +++ b/modules/addressbook/e-book-shell-content.h @@ -62,9 +62,7 @@ enum { E_BOOK_SHELL_CONTENT_SELECTION_HAS_EMAIL = 1 << 2, E_BOOK_SHELL_CONTENT_SELECTION_IS_CONTACT_LIST = 1 << 3, E_BOOK_SHELL_CONTENT_SOURCE_IS_BUSY = 1 << 4, - E_BOOK_SHELL_CONTENT_SOURCE_IS_EDITABLE = 1 << 5, - E_BOOK_SHELL_CONTENT_SOURCE_IS_EMPTY = 1 << 6, - E_BOOK_SHELL_CONTENT_CLIPBOARD_HAS_DIRECTORY = 1 << 7 + E_BOOK_SHELL_CONTENT_SOURCE_IS_EDITABLE = 1 << 5 }; struct _EBookShellContent { @@ -108,8 +106,6 @@ void e_book_shell_content_set_preview_visible EShellSearchbar * e_book_shell_content_get_searchbar (EBookShellContent *book_shell_content); -void e_book_shell_content_clipboard_copy - (EBookShellContent *book_shell_content); G_END_DECLS diff --git a/modules/addressbook/e-book-shell-view-actions.c b/modules/addressbook/e-book-shell-view-actions.c index 904b777c8b..5cfdbd347d 100644 --- a/modules/addressbook/e-book-shell-view-actions.c +++ b/modules/addressbook/e-book-shell-view-actions.c @@ -312,44 +312,6 @@ action_address_book_stop_cb (GtkAction *action, } static void -action_contact_clipboard_copy_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - - book_shell_content = book_shell_view->priv->book_shell_content; - e_book_shell_content_clipboard_copy (book_shell_content); -} - -static void -action_contact_clipboard_cut_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_cut (view); -} - -static void -action_contact_clipboard_paste_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_paste (view); -} - -static void action_contact_copy_cb (GtkAction *action, EBookShellView *book_shell_view) { @@ -599,20 +561,6 @@ exit: } static void -action_contact_select_all_cb (GtkAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - EAddressbookView *view; - - book_shell_content = book_shell_view->priv->book_shell_content; - view = e_book_shell_content_get_current_view (book_shell_content); - g_return_if_fail (view != NULL); - - e_addressbook_view_select_all (view); -} - -static void action_contact_send_message_cb (GtkAction *action, EBookShellView *book_shell_view) { @@ -758,27 +706,6 @@ static GtkActionEntry contact_entries[] = { N_("Stop loading"), G_CALLBACK (action_address_book_stop_cb) }, - { "contact-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy the selection"), - G_CALLBACK (action_contact_clipboard_copy_cb) }, - - { "contact-clipboard-cut", - GTK_STOCK_CUT, - NULL, - NULL, - N_("Cut the selection"), - G_CALLBACK (action_contact_clipboard_cut_cb) }, - - { "contact-clipboard-paste", - GTK_STOCK_PASTE, - NULL, - NULL, - N_("Paste the clipboard"), - G_CALLBACK (action_contact_clipboard_paste_cb) }, - { "contact-copy", NULL, N_("_Copy Contact To..."), @@ -828,13 +755,6 @@ static GtkActionEntry contact_entries[] = { N_("View the current contact"), G_CALLBACK (action_contact_open_cb) }, - { "contact-select-all", - GTK_STOCK_SELECT_ALL, - NULL, - NULL, - N_("Select all contacts"), - G_CALLBACK (action_contact_select_all_cb) }, - { "contact-send-message", "mail-message-new", N_("_Send Message to Contact..."), @@ -877,18 +797,6 @@ static EPopupActionEntry contact_popup_entries[] = { N_("_Save as vCard..."), "address-book-save-as" }, - { "contact-popup-clipboard-copy", - NULL, - "contact-clipboard-copy" }, - - { "contact-popup-clipboard-cut", - NULL, - "contact-clipboard-cut" }, - - { "contact-popup-clipboard-paste", - NULL, - "contact-clipboard-paste" }, - { "contact-popup-copy", NULL, "contact-copy" }, diff --git a/modules/addressbook/e-book-shell-view-actions.h b/modules/addressbook/e-book-shell-view-actions.h index 98cd8b6689..250ec5fa99 100644 --- a/modules/addressbook/e-book-shell-view-actions.h +++ b/modules/addressbook/e-book-shell-view-actions.h @@ -45,12 +45,6 @@ E_SHELL_WINDOW_ACTION ((window), "address-book-stop") /* Contact Actions */ -#define E_SHELL_WINDOW_ACTION_CONTACT_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_CONTACT_CLIPBOARD_CUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-clipboard-cut") -#define E_SHELL_WINDOW_ACTION_CONTACT_CLIPBOARD_PASTE(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-clipboard-paste") #define E_SHELL_WINDOW_ACTION_CONTACT_COPY(window) \ E_SHELL_WINDOW_ACTION ((window), "contact-copy") #define E_SHELL_WINDOW_ACTION_CONTACT_DELETE(window) \ @@ -71,8 +65,6 @@ E_SHELL_WINDOW_ACTION ((window), "contact-print") #define E_SHELL_WINDOW_ACTION_CONTACT_SAVE_AS(window) \ E_SHELL_WINDOW_ACTION ((window), "contact-save-as") -#define E_SHELL_WINDOW_ACTION_CONTACT_SELECT_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-select-all") #define E_SHELL_WINDOW_ACTION_CONTACT_SEND_MESSAGE(window) \ E_SHELL_WINDOW_ACTION ((window), "contact-send-message") #define E_SHELL_WINDOW_ACTION_CONTACT_VIEW_CLASSIC(window) \ diff --git a/modules/addressbook/e-book-shell-view.c b/modules/addressbook/e-book-shell-view.c index fa5e5bbe29..9ab9cb743a 100644 --- a/modules/addressbook/e-book-shell-view.c +++ b/modules/addressbook/e-book-shell-view.c @@ -268,8 +268,9 @@ book_shell_view_update_actions (EShellView *shell_view) gboolean selection_has_email; gboolean source_is_busy; gboolean source_is_editable; - gboolean source_is_empty; - gboolean clipboard_has_directory; + + /* Chain up to parent's update_actions() method. */ + E_SHELL_VIEW_CLASS (parent_class)->update_actions (shell_view); priv = E_BOOK_SHELL_VIEW_GET_PRIVATE (shell_view); @@ -290,10 +291,6 @@ book_shell_view_update_actions (EShellView *shell_view) (state & E_BOOK_SHELL_CONTENT_SOURCE_IS_BUSY); source_is_editable = (state & E_BOOK_SHELL_CONTENT_SOURCE_IS_EDITABLE); - source_is_empty = - (state & E_BOOK_SHELL_CONTENT_SOURCE_IS_EMPTY); - clipboard_has_directory = - (state & E_BOOK_SHELL_CONTENT_CLIPBOARD_HAS_DIRECTORY); shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); state = e_shell_sidebar_check_state (shell_sidebar); @@ -328,18 +325,6 @@ book_shell_view_update_actions (EShellView *shell_view) sensitive = source_is_busy; gtk_action_set_sensitive (action, sensitive); - action = ACTION (CONTACT_CLIPBOARD_COPY); - sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_CLIPBOARD_CUT); - sensitive = source_is_editable && any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_CLIPBOARD_PASTE); - sensitive = source_is_editable && clipboard_has_directory; - gtk_action_set_sensitive (action, sensitive); - action = ACTION (CONTACT_COPY); sensitive = any_contacts_selected; gtk_action_set_sensitive (action, sensitive); @@ -381,10 +366,6 @@ book_shell_view_update_actions (EShellView *shell_view) sensitive = any_contacts_selected; gtk_action_set_sensitive (action, sensitive); - action = ACTION (CONTACT_SELECT_ALL); - sensitive = !(source_is_empty); - gtk_action_set_sensitive (action, sensitive); - action = ACTION (CONTACT_SEND_MESSAGE); sensitive = any_contacts_selected && selection_has_email; gtk_action_set_sensitive (action, sensitive); diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index c3112cf42c..4946972efd 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -721,114 +721,6 @@ e_cal_shell_content_get_view_instance (ECalShellContent *cal_shell_content) } void -e_cal_shell_content_copy_clipboard (ECalShellContent *cal_shell_content) -{ - GnomeCalendar *calendar; - EMemoTable *memo_table; - ECalendarTable *task_table; - GnomeCalendarViewType view_type; - ECalendarView *calendar_view; - - g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); - - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - view_type = gnome_calendar_get_view (calendar); - calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); - - switch (cal_shell_content_get_focus_location (cal_shell_content)) { - case FOCUS_CALENDAR: - e_calendar_view_copy_clipboard (calendar_view); - break; - - case FOCUS_MEMO_TABLE: - e_memo_table_copy_clipboard (memo_table); - break; - - case FOCUS_TASK_TABLE: - e_calendar_table_copy_clipboard (task_table); - break; - - default: - g_return_if_reached (); - } -} - -void -e_cal_shell_content_cut_clipboard (ECalShellContent *cal_shell_content) -{ - GnomeCalendar *calendar; - EMemoTable *memo_table; - ECalendarTable *task_table; - GnomeCalendarViewType view_type; - ECalendarView *calendar_view; - - g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); - - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - view_type = gnome_calendar_get_view (calendar); - calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); - - switch (cal_shell_content_get_focus_location (cal_shell_content)) { - case FOCUS_CALENDAR: - e_calendar_view_cut_clipboard (calendar_view); - break; - - case FOCUS_MEMO_TABLE: - e_memo_table_copy_clipboard (memo_table); - break; - - case FOCUS_TASK_TABLE: - e_calendar_table_copy_clipboard (task_table); - break; - - default: - g_return_if_reached (); - } -} - -void -e_cal_shell_content_paste_clipboard (ECalShellContent *cal_shell_content) -{ - GnomeCalendar *calendar; - EMemoTable *memo_table; - ECalendarTable *task_table; - GnomeCalendarViewType view_type; - ECalendarView *calendar_view; - - g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content)); - - calendar = e_cal_shell_content_get_calendar (cal_shell_content); - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - view_type = gnome_calendar_get_view (calendar); - calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); - - switch (cal_shell_content_get_focus_location (cal_shell_content)) { - case FOCUS_CALENDAR: - e_calendar_view_paste_clipboard (calendar_view); - break; - - case FOCUS_MEMO_TABLE: - e_memo_table_paste_clipboard (memo_table); - break; - - case FOCUS_TASK_TABLE: - e_calendar_table_paste_clipboard (task_table); - break; - - default: - g_return_if_reached (); - } -} - -void e_cal_shell_content_delete_selection (ECalShellContent *cal_shell_content) { GnomeCalendar *calendar; diff --git a/modules/calendar/e-cal-shell-content.h b/modules/calendar/e-cal-shell-content.h index eae8bf3301..db82889eab 100644 --- a/modules/calendar/e-cal-shell-content.h +++ b/modules/calendar/e-cal-shell-content.h @@ -26,6 +26,7 @@ #include <shell/e-shell-searchbar.h> #include <shell/e-shell-view.h> +#include <calendar/gui/e-calendar-table.h> #include <calendar/gui/e-memo-table.h> #include <calendar/gui/gnome-cal.h> #include <menus/gal-view-instance.h> @@ -96,12 +97,6 @@ EShellSearchbar * GalViewInstance * e_cal_shell_content_get_view_instance (ECalShellContent *cal_shell_content); -void e_cal_shell_content_copy_clipboard - (ECalShellContent *cal_shell_content); -void e_cal_shell_content_cut_clipboard - (ECalShellContent *cal_shell_content); -void e_cal_shell_content_paste_clipboard - (ECalShellContent *cal_shell_content); void e_cal_shell_content_delete_selection (ECalShellContent *cal_shell_content); void e_cal_shell_content_delete_selected_occurrence diff --git a/modules/calendar/e-cal-shell-view-actions.c b/modules/calendar/e-cal-shell-view-actions.c index 148cc4a426..117868d646 100644 --- a/modules/calendar/e-cal-shell-view-actions.c +++ b/modules/calendar/e-cal-shell-view-actions.c @@ -482,36 +482,6 @@ action_event_all_day_new_cb (GtkAction *action, } static void -action_event_clipboard_copy_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - e_cal_shell_content_copy_clipboard (cal_shell_content); -} - -static void -action_event_clipboard_cut_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - e_cal_shell_content_cut_clipboard (cal_shell_content); -} - -static void -action_event_clipboard_paste_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - e_cal_shell_content_paste_clipboard (cal_shell_content); -} - -static void action_event_copy_cb (GtkAction *action, ECalShellView *cal_shell_view) { @@ -1314,27 +1284,6 @@ static GtkActionEntry calendar_entries[] = { NULL, /* XXX Add a tooltip! */ G_CALLBACK (action_calendar_select_one_cb) }, - { "event-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy the selection"), - G_CALLBACK (action_event_clipboard_copy_cb) }, - - { "event-clipboard-cut", - GTK_STOCK_CUT, - NULL, - NULL, - N_("Cut the selection"), - G_CALLBACK (action_event_clipboard_cut_cb) }, - - { "event-clipboard-paste", - GTK_STOCK_PASTE, - NULL, - NULL, - N_("Paste the clipboard"), - G_CALLBACK (action_event_clipboard_paste_cb) }, - { "event-copy", NULL, N_("Cop_y to Calendar..."), @@ -1502,18 +1451,6 @@ static EPopupActionEntry calendar_popup_entries[] = { NULL, "calendar-select-one" }, - { "event-popup-clipboard-copy", - NULL, - "event-clipboard-copy" }, - - { "event-popup-clipboard-cut", - NULL, - "event-clipboard-cut" }, - - { "event-popup-clipboard-paste", - NULL, - "event-clipboard-paste" }, - { "event-popup-copy", NULL, "event-copy" }, diff --git a/modules/calendar/e-cal-shell-view-actions.h b/modules/calendar/e-cal-shell-view-actions.h index a6b1c3d01c..a1cb31398b 100644 --- a/modules/calendar/e-cal-shell-view-actions.h +++ b/modules/calendar/e-cal-shell-view-actions.h @@ -65,12 +65,6 @@ E_SHELL_WINDOW_ACTION ((window), "calendar-view-workweek") /* Event Actions */ -#define E_SHELL_WINDOW_ACTION_EVENT_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_EVENT_CLIPBOARD_CUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-clipboard-cut") -#define E_SHELL_WINDOW_ACTION_EVENT_CLIPBOARD_PASTE(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-clipboard-paste") #define E_SHELL_WINDOW_ACTION_EVENT_DELEGATE(window) \ E_SHELL_WINDOW_ACTION ((window), "event-delegate") #define E_SHELL_WINDOW_ACTION_EVENT_DELETE(window) \ @@ -97,12 +91,6 @@ E_SHELL_WINDOW_ACTION ((window), "event-occurrence-movable") /* Memo Pad Actions */ -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_CLIPBOARD_CUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-clipboard-cut") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_CLIPBOARD_PASTE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-clipboard-paste") #define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_DELETE(window) \ E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-delete") #define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_FORWARD(window) \ @@ -121,12 +109,6 @@ /* Task Pad Actions */ #define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_ASSIGN(window) \ E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-assign") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_CLIPBOARD_CUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-clipboard-cut") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_CLIPBOARD_PASTE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-clipboard-paste") #define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_DELETE(window) \ E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-delete") #define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_FORWARD(window) \ diff --git a/modules/calendar/e-cal-shell-view-memopad.c b/modules/calendar/e-cal-shell-view-memopad.c index 3a92cbc777..a65bf82cdd 100644 --- a/modules/calendar/e-cal-shell-view-memopad.c +++ b/modules/calendar/e-cal-shell-view-memopad.c @@ -24,45 +24,6 @@ /* Much of this file is based on e-memo-shell-view-actions.c. */ static void -action_calendar_memopad_clipboard_copy_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - e_memo_table_copy_clipboard (memo_table); -} - -static void -action_calendar_memopad_clipboard_cut_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - e_memo_table_cut_clipboard (memo_table); -} - -static void -action_calendar_memopad_clipboard_paste_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - EMemoTable *memo_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); - - e_memo_table_paste_clipboard (memo_table); -} - -static void action_calendar_memopad_delete_cb (GtkAction *action, ECalShellView *cal_shell_view) { @@ -292,27 +253,6 @@ action_calendar_memopad_save_as_cb (GtkAction *action, static GtkActionEntry calendar_memopad_entries[] = { - { "calendar-memopad-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy selected memo"), - G_CALLBACK (action_calendar_memopad_clipboard_copy_cb) }, - - { "calendar-memopad-clipboard-cut", - GTK_STOCK_CUT, - NULL, - NULL, - N_("Cut selected memo"), - G_CALLBACK (action_calendar_memopad_clipboard_cut_cb) }, - - { "calendar-memopad-clipboard-paste", - GTK_STOCK_PASTE, - NULL, - NULL, - N_("Paste memo from the clipboard"), - G_CALLBACK (action_calendar_memopad_clipboard_paste_cb) }, - { "calendar-memopad-delete", GTK_STOCK_DELETE, N_("_Delete Memo"), @@ -427,18 +367,6 @@ e_cal_shell_view_memopad_actions_update (ECalShellView *cal_shell_view) } g_slist_free (list); - action = ACTION (CALENDAR_MEMOPAD_CLIPBOARD_COPY); - sensitive = (n_selected > 0); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_MEMOPAD_CLIPBOARD_CUT); - sensitive = (n_selected > 0) && editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_MEMOPAD_CLIPBOARD_PASTE); - sensitive = editable; - gtk_action_set_sensitive (action, sensitive); - action = ACTION (CALENDAR_MEMOPAD_DELETE); sensitive = (n_selected > 0) && editable; gtk_action_set_sensitive (action, sensitive); diff --git a/modules/calendar/e-cal-shell-view-taskpad.c b/modules/calendar/e-cal-shell-view-taskpad.c index c88dee0d4c..f73d5839d1 100644 --- a/modules/calendar/e-cal-shell-view-taskpad.c +++ b/modules/calendar/e-cal-shell-view-taskpad.c @@ -47,45 +47,6 @@ action_calendar_taskpad_assign_cb (GtkAction *action, } static void -action_calendar_taskpad_clipboard_copy_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - e_calendar_table_copy_clipboard (task_table); -} - -static void -action_calendar_taskpad_clipboard_cut_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - e_calendar_table_cut_clipboard (task_table); -} - -static void -action_calendar_taskpad_clipboard_paste_cb (GtkAction *action, - ECalShellView *cal_shell_view) -{ - ECalShellContent *cal_shell_content; - ECalendarTable *task_table; - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - task_table = e_cal_shell_content_get_task_table (cal_shell_content); - - e_calendar_table_paste_clipboard (task_table); -} - -static void action_calendar_taskpad_delete_cb (GtkAction *action, ECalShellView *cal_shell_view) { @@ -366,27 +327,6 @@ static GtkActionEntry calendar_taskpad_entries[] = { NULL, /* XXX Add a tooltip! */ G_CALLBACK (action_calendar_taskpad_assign_cb) }, - { "calendar-taskpad-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy selected tasks"), - G_CALLBACK (action_calendar_taskpad_clipboard_copy_cb) }, - - { "calendar-taskpad-clipboard-cut", - GTK_STOCK_CUT, - NULL, - NULL, - N_("Cut selected tasks"), - G_CALLBACK (action_calendar_taskpad_clipboard_cut_cb) }, - - { "calendar-taskpad-clipboard-paste", - GTK_STOCK_PASTE, - NULL, - NULL, - N_("Paste tasks from the clipboard"), - G_CALLBACK (action_calendar_taskpad_clipboard_paste_cb) }, - { "calendar-taskpad-delete", GTK_STOCK_DELETE, N_("_Delete Task"), @@ -538,18 +478,6 @@ e_cal_shell_view_taskpad_actions_update (ECalShellView *cal_shell_view) sensitive = (n_selected == 1) && editable && assignable; gtk_action_set_sensitive (action, sensitive); - action = ACTION (CALENDAR_TASKPAD_CLIPBOARD_COPY); - sensitive = (n_selected > 0); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_TASKPAD_CLIPBOARD_CUT); - sensitive = (n_selected > 0) && editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CALENDAR_TASKPAD_CLIPBOARD_PASTE); - sensitive = editable; - gtk_action_set_sensitive (action, sensitive); - action = ACTION (CALENDAR_TASKPAD_DELETE); sensitive = (n_selected > 0) && editable; gtk_action_set_sensitive (action, sensitive); diff --git a/modules/calendar/e-cal-shell-view.c b/modules/calendar/e-cal-shell-view.c index 262cd39246..5b9940b1dd 100644 --- a/modules/calendar/e-cal-shell-view.c +++ b/modules/calendar/e-cal-shell-view.c @@ -296,9 +296,11 @@ cal_shell_view_update_actions (EShellView *shell_view) gboolean is_instance = FALSE; gboolean is_meeting = FALSE; gboolean is_delegatable = FALSE; - gboolean clipboard_has_calendar; gboolean refresh_supported = FALSE; + /* Chain up to parent's update_actions() method. */ + E_SHELL_VIEW_CLASS (parent_class)->update_actions (shell_view); + priv = E_CAL_SHELL_VIEW_GET_PRIVATE (shell_view); shell_window = e_shell_view_get_shell_window (shell_view); @@ -361,10 +363,6 @@ cal_shell_view_update_actions (EShellView *shell_view) g_list_free (list); - clipboard_has_calendar = - e_clipboard_wait_is_calendar_available ( - gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)); - shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); state = e_shell_sidebar_check_state (shell_sidebar); @@ -397,18 +395,6 @@ cal_shell_view_update_actions (EShellView *shell_view) sensitive = can_delete_primary_source; gtk_action_set_sensitive (action, sensitive); - action = ACTION (EVENT_CLIPBOARD_COPY); - sensitive = (n_selected > 0); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (EVENT_CLIPBOARD_CUT); - sensitive = (n_selected > 0) && editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (EVENT_CLIPBOARD_PASTE); - sensitive = editable && clipboard_has_calendar; - gtk_action_set_sensitive (action, sensitive); - action = ACTION (EVENT_DELEGATE); sensitive = (n_selected == 1) && editable && diff --git a/modules/calendar/e-memo-shell-content.c b/modules/calendar/e-memo-shell-content.c index 4de685cd4b..709ae9a8e6 100644 --- a/modules/calendar/e-memo-shell-content.c +++ b/modules/calendar/e-memo-shell-content.c @@ -537,7 +537,6 @@ memo_shell_content_check_state (EShellContent *shell_content) EMemoShellContent *memo_shell_content; EMemoTable *memo_table; GSList *list, *iter; - GtkClipboard *clipboard; gboolean editable = TRUE; gboolean has_url = FALSE; gint n_selected; @@ -563,8 +562,6 @@ memo_shell_content_check_state (EShellContent *shell_content) } g_slist_free (list); - clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - if (n_selected == 1) state |= E_MEMO_SHELL_CONTENT_SELECTION_SINGLE; if (n_selected > 1) @@ -573,8 +570,6 @@ memo_shell_content_check_state (EShellContent *shell_content) state |= E_MEMO_SHELL_CONTENT_SELECTION_CAN_EDIT; if (has_url) state |= E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL; - if (e_clipboard_wait_is_calendar_available (clipboard)) - state |= E_MEMO_SHELL_CONTENT_CLIPBOARD_HAS_CALENDAR; return state; } diff --git a/modules/calendar/e-memo-shell-content.h b/modules/calendar/e-memo-shell-content.h index a923b27f0b..16aae229b2 100644 --- a/modules/calendar/e-memo-shell-content.h +++ b/modules/calendar/e-memo-shell-content.h @@ -60,8 +60,7 @@ enum { E_MEMO_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, E_MEMO_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, E_MEMO_SHELL_CONTENT_SELECTION_CAN_EDIT = 1 << 2, - E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL = 1 << 3, - E_MEMO_SHELL_CONTENT_CLIPBOARD_HAS_CALENDAR = 1 << 4 + E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL = 1 << 3 }; struct _EMemoShellContent { diff --git a/modules/calendar/e-memo-shell-view-actions.c b/modules/calendar/e-memo-shell-view-actions.c index baf90f5a73..7a0fdaf8af 100644 --- a/modules/calendar/e-memo-shell-view-actions.c +++ b/modules/calendar/e-memo-shell-view-actions.c @@ -43,45 +43,6 @@ action_gal_save_custom_view_cb (GtkAction *action, } static void -action_memo_clipboard_copy_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - e_memo_table_copy_clipboard (memo_table); -} - -static void -action_memo_clipboard_cut_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - e_memo_table_cut_clipboard (memo_table); -} - -static void -action_memo_clipboard_paste_cb (GtkAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - EMemoTable *memo_table; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - memo_table = e_memo_shell_content_get_memo_table (memo_shell_content); - - e_memo_table_paste_clipboard (memo_table); -} - -static void action_memo_delete_cb (GtkAction *action, EMemoShellView *memo_shell_view) { @@ -590,27 +551,6 @@ action_search_filter_cb (GtkRadioAction *action, static GtkActionEntry memo_entries[] = { - { "memo-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy selected memo"), - G_CALLBACK (action_memo_clipboard_copy_cb) }, - - { "memo-clipboard-cut", - GTK_STOCK_CUT, - NULL, - NULL, - N_("Cut selected memo"), - G_CALLBACK (action_memo_clipboard_cut_cb) }, - - { "memo-clipboard-paste", - GTK_STOCK_PASTE, - NULL, - NULL, - N_("Paste memo from the clipboard"), - G_CALLBACK (action_memo_clipboard_paste_cb) }, - { "memo-delete", GTK_STOCK_DELETE, N_("_Delete Memo"), @@ -731,18 +671,6 @@ static EPopupActionEntry memo_popup_entries[] = { NULL, "memo-list-select-one" }, - { "memo-popup-clipboard-copy", - NULL, - "memo-clipboard-copy" }, - - { "memo-popup-clipboard-cut", - NULL, - "memo-clipboard-cut" }, - - { "memo-popup-clipboard-paste", - NULL, - "memo-clipboard-paste" }, - { "memo-popup-delete", NULL, "memo-delete" }, diff --git a/modules/calendar/e-memo-shell-view-actions.h b/modules/calendar/e-memo-shell-view-actions.h index cb4309c18a..5b49ca06b1 100644 --- a/modules/calendar/e-memo-shell-view-actions.h +++ b/modules/calendar/e-memo-shell-view-actions.h @@ -25,12 +25,6 @@ #include <shell/e-shell-window-actions.h> /* Memo Actions */ -#define E_SHELL_WINDOW_ACTION_MEMO_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_MEMO_CLIPBOARD_CUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-cut") -#define E_SHELL_WINDOW_ACTION_MEMO_CLIPBOARD_PASTE(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-clipboard-paste") #define E_SHELL_WINDOW_ACTION_MEMO_DELETE(window) \ E_SHELL_WINDOW_ACTION ((window), "memo-delete") #define E_SHELL_WINDOW_ACTION_MEMO_FORWARD(window) \ diff --git a/modules/calendar/e-memo-shell-view.c b/modules/calendar/e-memo-shell-view.c index 29a82524c4..0afbe18e77 100644 --- a/modules/calendar/e-memo-shell-view.c +++ b/modules/calendar/e-memo-shell-view.c @@ -175,7 +175,6 @@ memo_shell_view_update_actions (EShellView *shell_view) /* Be descriptive. */ gboolean any_memos_selected; gboolean can_delete_primary_source; - gboolean clipboard_has_calendar; gboolean has_primary_source; gboolean multiple_memos_selected; gboolean primary_source_is_system; @@ -184,6 +183,9 @@ memo_shell_view_update_actions (EShellView *shell_view) gboolean sources_are_editable; gboolean refresh_supported; + /* Chain up to parent's update_actions() method. */ + E_SHELL_VIEW_CLASS (parent_class)->update_actions (shell_view); + priv = E_MEMO_SHELL_VIEW_GET_PRIVATE (shell_view); shell_window = e_shell_view_get_shell_window (shell_view); @@ -199,8 +201,6 @@ memo_shell_view_update_actions (EShellView *shell_view) (state & E_MEMO_SHELL_CONTENT_SELECTION_CAN_EDIT); selection_has_url = (state & E_MEMO_SHELL_CONTENT_SELECTION_HAS_URL); - clipboard_has_calendar = - (state & E_MEMO_SHELL_CONTENT_CLIPBOARD_HAS_CALENDAR); shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); state = e_shell_sidebar_check_state (shell_sidebar); @@ -217,18 +217,6 @@ memo_shell_view_update_actions (EShellView *shell_view) any_memos_selected = (single_memo_selected || multiple_memos_selected); - action = ACTION (MEMO_CLIPBOARD_COPY); - sensitive = any_memos_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_CLIPBOARD_CUT); - sensitive = any_memos_selected && sources_are_editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (MEMO_CLIPBOARD_PASTE); - sensitive = sources_are_editable && clipboard_has_calendar; - gtk_action_set_sensitive (action, sensitive); - action = ACTION (MEMO_DELETE); sensitive = any_memos_selected && sources_are_editable; gtk_action_set_sensitive (action, sensitive); diff --git a/modules/calendar/e-task-shell-content.c b/modules/calendar/e-task-shell-content.c index 4692e7bf7e..e50b67bf5a 100644 --- a/modules/calendar/e-task-shell-content.c +++ b/modules/calendar/e-task-shell-content.c @@ -535,7 +535,6 @@ task_shell_content_check_state (EShellContent *shell_content) ETaskShellContent *task_shell_content; ECalendarTable *task_table; GSList *list, *iter; - GtkClipboard *clipboard; gboolean assignable = TRUE; gboolean editable = TRUE; gboolean has_url = FALSE; @@ -580,8 +579,6 @@ task_shell_content_check_state (EShellContent *shell_content) } g_slist_free (list); - clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - if (n_selected == 1) state |= E_TASK_SHELL_CONTENT_SELECTION_SINGLE; if (n_selected > 1) @@ -596,8 +593,6 @@ task_shell_content_check_state (EShellContent *shell_content) state |= E_TASK_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE; if (has_url) state |= E_TASK_SHELL_CONTENT_SELECTION_HAS_URL; - if (e_clipboard_wait_is_calendar_available (clipboard)) - state |= E_TASK_SHELL_CONTENT_CLIPBOARD_HAS_CALENDAR; return state; } diff --git a/modules/calendar/e-task-shell-content.h b/modules/calendar/e-task-shell-content.h index 971d46ad95..7a5e8efd81 100644 --- a/modules/calendar/e-task-shell-content.h +++ b/modules/calendar/e-task-shell-content.h @@ -64,8 +64,7 @@ enum { E_TASK_SHELL_CONTENT_SELECTION_CAN_EDIT = 1 << 3, E_TASK_SHELL_CONTENT_SELECTION_HAS_COMPLETE = 1 << 4, E_TASK_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE = 1 << 5, - E_TASK_SHELL_CONTENT_SELECTION_HAS_URL = 1 << 6, - E_TASK_SHELL_CONTENT_CLIPBOARD_HAS_CALENDAR = 1 << 7 + E_TASK_SHELL_CONTENT_SELECTION_HAS_URL = 1 << 6 }; struct _ETaskShellContent { diff --git a/modules/calendar/e-task-shell-view-actions.c b/modules/calendar/e-task-shell-view-actions.c index 8e28b55863..067bd48370 100644 --- a/modules/calendar/e-task-shell-view-actions.c +++ b/modules/calendar/e-task-shell-view-actions.c @@ -74,45 +74,6 @@ action_task_assign_cb (GtkAction *action, } static void -action_task_clipboard_copy_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - e_calendar_table_copy_clipboard (task_table); -} - -static void -action_task_clipboard_cut_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - e_calendar_table_cut_clipboard (task_table); -} - -static void -action_task_clipboard_paste_cb (GtkAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - ECalendarTable *task_table; - - task_shell_content = task_shell_view->priv->task_shell_content; - task_table = e_task_shell_content_get_task_table (task_shell_content); - - e_calendar_table_paste_clipboard (task_table); -} - -static void action_task_delete_cb (GtkAction *action, ETaskShellView *task_shell_view) { @@ -714,27 +675,6 @@ static GtkActionEntry task_entries[] = { NULL, /* XXX Add a tooltip! */ G_CALLBACK (action_task_assign_cb) }, - { "task-clipboard-copy", - GTK_STOCK_COPY, - NULL, - NULL, - N_("Copy selected tasks"), - G_CALLBACK (action_task_clipboard_copy_cb) }, - - { "task-clipboard-cut", - GTK_STOCK_CUT, - NULL, - NULL, - N_("Cut selected tasks"), - G_CALLBACK (action_task_clipboard_cut_cb) }, - - { "task-clipboard-paste", - GTK_STOCK_PASTE, - NULL, - NULL, - N_("Paste tasks from the clipboard"), - G_CALLBACK (action_task_clipboard_paste_cb) }, - { "task-delete", GTK_STOCK_DELETE, N_("_Delete Task"), @@ -887,18 +827,6 @@ static EPopupActionEntry task_popup_entries[] = { NULL, "task-assign" }, - { "task-popup-clipboard-copy", - NULL, - "task-clipboard-copy" }, - - { "task-popup-clipboard-cut", - NULL, - "task-clipboard-cut" }, - - { "task-popup-clipboard-paste", - NULL, - "task-clipboard-paste" }, - { "task-popup-delete", NULL, "task-delete" }, diff --git a/modules/calendar/e-task-shell-view-actions.h b/modules/calendar/e-task-shell-view-actions.h index 3d49ff636e..f323fb38f9 100644 --- a/modules/calendar/e-task-shell-view-actions.h +++ b/modules/calendar/e-task-shell-view-actions.h @@ -27,12 +27,6 @@ /* Task Actions */ #define E_SHELL_WINDOW_ACTION_TASK_ASSIGN(window) \ E_SHELL_WINDOW_ACTION ((window), "task-assign") -#define E_SHELL_WINDOW_ACTION_TASK_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_TASK_CLIPBOARD_CUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-clipboard-cut") -#define E_SHELL_WINDOW_ACTION_TASK_CLIPBOARD_PASTE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-clipboard-paste") #define E_SHELL_WINDOW_ACTION_TASK_DELETE(window) \ E_SHELL_WINDOW_ACTION ((window), "task-delete") #define E_SHELL_WINDOW_ACTION_TASK_FORWARD(window) \ diff --git a/modules/calendar/e-task-shell-view.c b/modules/calendar/e-task-shell-view.c index a481356690..07fb12e369 100644 --- a/modules/calendar/e-task-shell-view.c +++ b/modules/calendar/e-task-shell-view.c @@ -297,9 +297,11 @@ task_shell_view_update_actions (EShellView *shell_view) gboolean some_tasks_complete; gboolean some_tasks_incomplete; gboolean sources_are_editable; - gboolean clipboard_has_calendar; gboolean refresh_supported; + /* Chain up to parent's update_actions() method. */ + E_SHELL_VIEW_CLASS (parent_class)->update_actions (shell_view); + priv = E_TASK_SHELL_VIEW_GET_PRIVATE (shell_view); shell_window = e_shell_view_get_shell_window (shell_view); @@ -321,8 +323,6 @@ task_shell_view_update_actions (EShellView *shell_view) (state & E_TASK_SHELL_CONTENT_SELECTION_HAS_INCOMPLETE); selection_has_url = (state & E_TASK_SHELL_CONTENT_SELECTION_HAS_URL); - clipboard_has_calendar = - (state & E_TASK_SHELL_CONTENT_CLIPBOARD_HAS_CALENDAR); shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); state = e_shell_sidebar_check_state (shell_sidebar); @@ -345,18 +345,6 @@ task_shell_view_update_actions (EShellView *shell_view) selection_is_assignable; gtk_action_set_sensitive (action, sensitive); - action = ACTION (TASK_CLIPBOARD_COPY); - sensitive = any_tasks_selected; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_CLIPBOARD_CUT); - sensitive = any_tasks_selected && sources_are_editable; - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (TASK_CLIPBOARD_PASTE); - sensitive = sources_are_editable && clipboard_has_calendar; - gtk_action_set_sensitive (action, sensitive); - action = ACTION (TASK_DELETE); sensitive = any_tasks_selected && sources_are_editable; gtk_action_set_sensitive (action, sensitive); diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c index 2ab36d46fb..139dd9474f 100644 --- a/modules/mail/e-mail-shell-view-actions.c +++ b/modules/mail/e-mail-shell-view-actions.c @@ -353,48 +353,6 @@ action_mail_folder_rename_cb (GtkAction *action, em_folder_tree_edit_selected (folder_tree); } -/* Helper for action_mail_folder_select_all_cb() */ -static gboolean -action_mail_folder_select_all_timeout_cb (GtkWidget *message_list) -{ - message_list_select_all (MESSAGE_LIST (message_list)); - gtk_widget_grab_focus (message_list); - - return FALSE; -} - -static void -action_mail_folder_select_all_cb (GtkAction *action, - EMailShellView *mail_shell_view) -{ - EMailReader *reader; - GtkWidget *message_list; - EShellWindow *shell_window; - EShellView *shell_view; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); - message_list = e_mail_reader_get_message_list (reader); - - if (MESSAGE_LIST (message_list)->threaded) { - gtk_action_activate (ACTION (MAIL_THREADS_EXPAND_ALL)); - - /* XXX The timeout below is added so that the execution - * thread to expand all conversation threads would - * have completed. The timeout 505 is just to ensure - * that the value is a small delta more than the - * timeout value in mail_regen_list(). */ - g_timeout_add ( - 505, (GSourceFunc) - action_mail_folder_select_all_timeout_cb, - message_list); - } else - /* If there is no threading, just select all immediately. */ - action_mail_folder_select_all_timeout_cb (message_list); -} - static void action_mail_folder_select_thread_cb (GtkAction *action, EMailShellView *mail_shell_view) @@ -1059,13 +1017,6 @@ static GtkActionEntry mail_entries[] = { N_("Change the name of this folder"), G_CALLBACK (action_mail_folder_rename_cb) }, - { "mail-folder-select-all", - NULL, - N_("Select _All Messages"), - "<Control>a", - N_("Select all visible messages"), - G_CALLBACK (action_mail_folder_select_all_cb) }, - { "mail-folder-select-thread", NULL, N_("Select Message _Thread"), diff --git a/modules/mail/e-mail-shell-view-private.c b/modules/mail/e-mail-shell-view-private.c index b198b69cd1..85395fd8ed 100644 --- a/modules/mail/e-mail-shell-view-private.c +++ b/modules/mail/e-mail-shell-view-private.c @@ -443,6 +443,7 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) shell_content = e_shell_view_get_shell_content (shell_view); shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); shell_window = e_shell_view_get_shell_window (shell_view); + ui_manager = e_shell_window_get_ui_manager (shell_window); shell = e_shell_window_get_shell (shell_window); diff --git a/modules/mail/e-mail-shell-view.c b/modules/mail/e-mail-shell-view.c index de81e131c5..bd0b3cbe48 100644 --- a/modules/mail/e-mail-shell-view.c +++ b/modules/mail/e-mail-shell-view.c @@ -440,6 +440,9 @@ mail_shell_view_update_actions (EShellView *shell_view) gboolean folder_has_unread_rec = FALSE; gboolean folder_tree_and_message_list_agree = TRUE; + /* Chain up to parent's update_actions() method. */ + E_SHELL_VIEW_CLASS (parent_class)->update_actions (shell_view); + mail_shell_view = E_MAIL_SHELL_VIEW (shell_view); shell_window = e_shell_view_get_shell_window (shell_view); @@ -554,10 +557,6 @@ mail_shell_view_update_actions (EShellView *shell_view) folder_tree_and_message_list_agree; gtk_action_set_sensitive (action, sensitive); - action = ACTION (MAIL_FOLDER_SELECT_ALL); - sensitive = !folder_is_store; - gtk_action_set_sensitive (action, sensitive); - action = ACTION (MAIL_FOLDER_SELECT_THREAD); sensitive = !folder_is_store; gtk_action_set_sensitive (action, sensitive); diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c index d87f8b7632..fdffe92fd6 100644 --- a/shell/e-shell-view.c +++ b/shell/e-shell-view.c @@ -507,21 +507,6 @@ shell_view_constructed (GObject *object) } static void -shell_view_clear_search (EShellView *shell_view) -{ - e_shell_view_set_search_rule (shell_view, NULL); - e_shell_view_execute_search (shell_view); -} - -static void -shell_view_custom_search (EShellView *shell_view, - EFilterRule *custom_rule) -{ - e_shell_view_set_search_rule (shell_view, custom_rule); - e_shell_view_execute_search (shell_view); -} - -static void shell_view_toggled (EShellView *shell_view) { EShellViewPrivate *priv = shell_view->priv; @@ -553,6 +538,33 @@ shell_view_toggled (EShellView *shell_view) } static void +shell_view_clear_search (EShellView *shell_view) +{ + e_shell_view_set_search_rule (shell_view, NULL); + e_shell_view_execute_search (shell_view); +} + +static void +shell_view_custom_search (EShellView *shell_view, + EFilterRule *custom_rule) +{ + e_shell_view_set_search_rule (shell_view, custom_rule); + e_shell_view_execute_search (shell_view); +} + +static void +shell_view_update_actions (EShellView *shell_view) +{ + EShellWindow *shell_window; + EFocusTracker *focus_tracker; + + shell_window = e_shell_view_get_shell_window (shell_view); + focus_tracker = e_shell_window_get_focus_tracker (shell_window); + + e_focus_tracker_update_actions (focus_tracker); +} + +static void shell_view_class_init (EShellViewClass *class) { GObjectClass *object_class; @@ -574,9 +586,10 @@ shell_view_class_init (EShellViewClass *class) class->new_shell_sidebar = e_shell_sidebar_new; class->new_shell_taskbar = e_shell_taskbar_new; + class->toggled = shell_view_toggled; class->clear_search = shell_view_clear_search; class->custom_search = shell_view_custom_search; - class->toggled = shell_view_toggled; + class->update_actions = shell_view_update_actions; /** * EShellView:action: diff --git a/shell/e-shell-window-actions.c b/shell/e-shell-window-actions.c index 4483347beb..5cdf2a932f 100644 --- a/shell/e-shell-window-actions.c +++ b/shell/e-shell-window-actions.c @@ -1437,6 +1437,27 @@ static GtkActionEntry shell_entries[] = { N_("Open the Evolution User Guide"), G_CALLBACK (action_contents_cb) }, + { "copy-clipboard", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy the selection"), + NULL }, /* Handled by EFocusTracker */ + + { "cut-clipboard", + GTK_STOCK_CUT, + NULL, + NULL, + N_("Cut the selection"), + NULL }, /* Handled by EFocusTracker */ + + { "delete-selection", + GTK_STOCK_DELETE, + NULL, + NULL, + N_("Delete the selection"), + NULL }, /* Handled by EFocusTracker */ + { "faq", "help-faq", N_("Evolution _FAQ"), @@ -1465,6 +1486,13 @@ static GtkActionEntry shell_entries[] = { N_("Create a new window displaying this view"), G_CALLBACK (action_new_window_cb) }, + { "paste-clipboard", + GTK_STOCK_PASTE, + NULL, + NULL, + N_("Paste the clipboard"), + NULL }, /* Handled by EFocusTracker */ + { "preferences", GTK_STOCK_PREFERENCES, NULL, @@ -1528,6 +1556,13 @@ static GtkActionEntry shell_entries[] = { N_("Save the current search parameters"), G_CALLBACK (action_search_save_cb) }, + { "select-all", + GTK_STOCK_SELECT_ALL, + NULL, + "<Control>a", + N_("Select all text"), + NULL }, /* Handled by EFocusTracker */ + { "send-receive", "mail-send-receive", N_("Send / _Receive"), @@ -1629,6 +1664,25 @@ static GtkActionEntry shell_entries[] = { NULL } }; +static EPopupActionEntry shell_popup_entries[] = { + + { "popup-copy-clipboard", + NULL, + "copy-clipboard" }, + + { "popup-cut-clipboard", + NULL, + "cut-clipboard" }, + + { "popup-delete-selection", + NULL, + "delete-selection" }, + + { "popup-paste-clipboard", + NULL, + "paste-clipboard" } +}; + static GtkToggleActionEntry shell_toggle_entries[] = { { "show-sidebar", @@ -1811,6 +1865,7 @@ void e_shell_window_actions_init (EShellWindow *shell_window) { GtkActionGroup *action_group; + EFocusTracker *focus_tracker; GtkUIManager *ui_manager; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); @@ -1824,6 +1879,9 @@ e_shell_window_actions_init (EShellWindow *shell_window) gtk_action_group_add_actions ( action_group, shell_entries, G_N_ELEMENTS (shell_entries), shell_window); + e_action_group_add_popup_actions ( + action_group, shell_popup_entries, + G_N_ELEMENTS (shell_popup_entries)); gtk_action_group_add_toggle_actions ( action_group, shell_toggle_entries, G_N_ELEMENTS (shell_toggle_entries), shell_window); @@ -1854,6 +1912,21 @@ e_shell_window_actions_init (EShellWindow *shell_window) G_N_ELEMENTS (shell_lockdown_print_setup_entries), shell_window); + /* Configure an EFocusTracker to manage selection actions. */ + + focus_tracker = e_focus_tracker_new (GTK_WINDOW (shell_window)); + e_focus_tracker_set_cut_clipboard_action ( + focus_tracker, ACTION (CUT_CLIPBOARD)); + e_focus_tracker_set_copy_clipboard_action ( + focus_tracker, ACTION (COPY_CLIPBOARD)); + e_focus_tracker_set_paste_clipboard_action ( + focus_tracker, ACTION (PASTE_CLIPBOARD)); + e_focus_tracker_set_delete_selection_action ( + focus_tracker, ACTION (DELETE_SELECTION)); + e_focus_tracker_set_select_all_action ( + focus_tracker, ACTION (SELECT_ALL)); + shell_window->priv->focus_tracker = focus_tracker; + /* Fine tuning. */ gtk_action_set_sensitive (ACTION (SEARCH_QUICK), FALSE); diff --git a/shell/e-shell-window-actions.h b/shell/e-shell-window-actions.h index 8636b69648..4833ad0c9f 100644 --- a/shell/e-shell-window-actions.h +++ b/shell/e-shell-window-actions.h @@ -35,6 +35,12 @@ E_SHELL_WINDOW_ACTION ((window), "close") #define E_SHELL_WINDOW_ACTION_CONTENTS(window) \ E_SHELL_WINDOW_ACTION ((window), "contents") +#define E_SHELL_WINDOW_ACTION_COPY_CLIPBOARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "copy-clipboard") +#define E_SHELL_WINDOW_ACTION_CUT_CLIPBOARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "cut-clipboard") +#define E_SHELL_WINDOW_ACTION_DELETE_SELECTION(window) \ + E_SHELL_WINDOW_ACTION ((window), "delete-selection") #define E_SHELL_WINDOW_ACTION_FAQ(window) \ E_SHELL_WINDOW_ACTION ((window), "faq") #define E_SHELL_WINDOW_ACTION_FORGET_PASSWORDS(window) \ @@ -51,6 +57,8 @@ E_SHELL_WINDOW_ACTION ((window), "new-window") #define E_SHELL_WINDOW_ACTION_PAGE_SETUP(window) \ E_SHELL_WINDOW_ACTION ((window), "page-setup") +#define E_SHELL_WINDOW_ACTION_PASTE_CLIPBOARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "paste-clipboard") #define E_SHELL_WINDOW_ACTION_PREFERENCES(window) \ E_SHELL_WINDOW_ACTION ((window), "preferences") #define E_SHELL_WINDOW_ACTION_QUICK_REFERENCE(window) \ @@ -69,6 +77,8 @@ E_SHELL_WINDOW_ACTION ((window), "search-quick") #define E_SHELL_WINDOW_ACTION_SEARCH_SAVE(window) \ E_SHELL_WINDOW_ACTION ((window), "search-save") +#define E_SHELL_WINDOW_ACTION_SELECT_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "select-all") #define E_SHELL_WINDOW_ACTION_SEND_RECEIVE(window) \ E_SHELL_WINDOW_ACTION ((window), "send-receive") #define E_SHELL_WINDOW_ACTION_SHOW_SIDEBAR(window) \ diff --git a/shell/e-shell-window-private.c b/shell/e-shell-window-private.c index 0d9dda59cb..a2805f46bf 100644 --- a/shell/e-shell-window-private.c +++ b/shell/e-shell-window-private.c @@ -473,6 +473,7 @@ e_shell_window_private_dispose (EShellWindow *shell_window) priv->shell = NULL; } + DISPOSE (priv->focus_tracker); DISPOSE (priv->ui_manager); g_hash_table_remove_all (priv->loaded_views); diff --git a/shell/e-shell-window-private.h b/shell/e-shell-window-private.h index 635b6b6630..87e18646c4 100644 --- a/shell/e-shell-window-private.h +++ b/shell/e-shell-window-private.h @@ -34,6 +34,7 @@ #include <widgets/misc/e-import-assistant.h> #include <widgets/misc/e-menu-tool-button.h> #include <widgets/misc/e-online-button.h> +#include <widgets/misc/e-popup-action.h> #include <e-shell.h> #include <e-shell-content.h> @@ -70,6 +71,7 @@ struct _EShellWindowPrivate { /*** UI Management ***/ + EFocusTracker *focus_tracker; GtkUIManager *ui_manager; guint custom_rule_merge_id; guint gal_view_merge_id; diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c index 25b56caecb..d3d6107e24 100644 --- a/shell/e-shell-window.c +++ b/shell/e-shell-window.c @@ -29,6 +29,7 @@ enum { PROP_0, PROP_ACTIVE_VIEW, + PROP_FOCUS_TRACKER, PROP_GEOMETRY, PROP_SAFE_MODE, PROP_SHELL, @@ -234,6 +235,12 @@ shell_window_get_property (GObject *object, E_SHELL_WINDOW (object))); return; + case PROP_FOCUS_TRACKER: + g_value_set_object ( + value, e_shell_window_get_focus_tracker ( + E_SHELL_WINDOW (object))); + return; + case PROP_SAFE_MODE: g_value_set_boolean ( value, e_shell_window_get_safe_mode ( @@ -609,6 +616,21 @@ shell_window_class_init (EShellWindowClass *class) G_PARAM_READWRITE)); /** + * EShellWindow:focus-tracker + * + * The shell window's #EFocusTracker. + **/ + g_object_class_install_property ( + object_class, + PROP_FOCUS_TRACKER, + g_param_spec_object ( + "focus-tracker", + _("Focus Tracker"), + _("The shell window's EFocusTracker"), + E_TYPE_FOCUS_TRACKER, + G_PARAM_READABLE)); + + /** * EShellWindow:geometry * * User-specified initial window geometry string. @@ -886,6 +908,24 @@ e_shell_window_get_shell_view_action (EShellWindow *shell_window, } /** + * e_shell_window_get_focus_tracker: + * @shell_window: an #EShellWindow + * + * Returns @shell_window<!-- -->'s focus tracker, which directs + * Cut, Copy, Paste and Select All main menu activations to the + * appropriate editable or selectable widget. + * + * Returns: the #EFocusTracker for @shell_window + **/ +EFocusTracker * +e_shell_window_get_focus_tracker (EShellWindow *shell_window) +{ + g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); + + return shell_window->priv->focus_tracker; +} + +/** * e_shell_window_get_ui_manager: * @shell_window: an #EShellWindow * diff --git a/shell/e-shell-window.h b/shell/e-shell-window.h index bb88003955..4ac76ba5d4 100644 --- a/shell/e-shell-window.h +++ b/shell/e-shell-window.h @@ -29,6 +29,7 @@ #define E_SHELL_WINDOW_H #include <shell/e-shell.h> +#include <misc/e-focus-tracker.h> /* Standard GObject macros */ #define E_TYPE_SHELL_WINDOW \ @@ -94,6 +95,7 @@ struct _EShellView * GtkAction * e_shell_window_get_shell_view_action (EShellWindow *shell_window, const gchar *view_name); +EFocusTracker * e_shell_window_get_focus_tracker(EShellWindow *shell_window); GtkUIManager * e_shell_window_get_ui_manager (EShellWindow *shell_window); GtkAction * e_shell_window_get_action (EShellWindow *shell_window, const gchar *action_name); diff --git a/ui/evolution-calendars.ui b/ui/evolution-calendars.ui index 8bff0fc506..818ed176b3 100644 --- a/ui/evolution-calendars.ui +++ b/ui/evolution-calendars.ui @@ -11,10 +11,6 @@ </menu> <menu action='edit-menu'> <placeholder name='edit-actions'> - <menuitem action='event-clipboard-cut'/> - <menuitem action='event-clipboard-copy'/> - <menuitem action='event-clipboard-paste'/> - <separator/> <menuitem action='event-delete'/> <menuitem action='event-delete-occurrence'/> <menuitem action='event-delete-occurrence-all'/> @@ -66,7 +62,7 @@ <separator/> <menuitem action='event-popup-print'/> <separator/> - <menuitem action='event-popup-clipboard-paste'/> + <menuitem action='popup-paste-clipboard'/> <separator/> <menu action='gal-view-menu'> <menuitem action='calendar-view-day'/> @@ -85,9 +81,9 @@ <menuitem action='event-popup-save-as'/> <menuitem action='event-popup-print'/> <separator/> - <menuitem action='event-popup-clipboard-cut'/> - <menuitem action='event-popup-clipboard-copy'/> - <menuitem action='event-popup-clipboard-paste'/> + <menuitem action='popup-cut-clipboard'/> + <menuitem action='popup-copy-clipboard'/> + <menuitem action='popup-paste-clipboard'/> <separator/> <menuitem action='event-popup-copy'/> <menuitem action='event-popup-move'/> @@ -113,9 +109,9 @@ <menuitem action='calendar-memopad-save-as'/> <menuitem action='calendar-memopad-print'/> <separator/> - <menuitem action='calendar-memopad-clipboard-cut'/> - <menuitem action='calendar-memopad-clipboard-copy'/> - <menuitem action='calendar-memopad-clipboard-paste'/> + <menuitem action='popup-cut-clipboard'/> + <menuitem action='popup-copy-clipboard'/> + <menuitem action='popup-paste-clipboard'/> <separator/> <menuitem action='calendar-memopad-forward'/> <separator/> @@ -129,9 +125,9 @@ <menuitem action='calendar-taskpad-save-as'/> <menuitem action='calendar-taskpad-print'/> <separator/> - <menuitem action='calendar-taskpad-clipboard-cut'/> - <menuitem action='calendar-taskpad-clipboard-copy'/> - <menuitem action='calendar-taskpad-clipboard-paste'/> + <menuitem action='popup-cut-clipboard'/> + <menuitem action='popup-copy-clipboard'/> + <menuitem action='popup-paste-clipboard'/> <separator/> <menuitem action='calendar-taskpad-assign'/> <menuitem action='calendar-taskpad-forward'/> diff --git a/ui/evolution-contacts.ui b/ui/evolution-contacts.ui index 864a5aa887..c3ce87108a 100644 --- a/ui/evolution-contacts.ui +++ b/ui/evolution-contacts.ui @@ -13,12 +13,6 @@ </menu> <menu action='edit-menu'> <placeholder name='edit-actions'> - <menuitem action='contact-select-all'/> - <separator/> - <menuitem action='contact-clipboard-cut'/> - <menuitem action='contact-clipboard-copy'/> - <menuitem action='contact-clipboard-paste'/> - <separator/> <menuitem action='contact-delete'/> <menuitem action='address-book-delete'/> </placeholder> @@ -77,9 +71,9 @@ <menuitem action='contact-popup-copy'/> <menuitem action='contact-popup-move'/> <separator/> - <menuitem action='contact-popup-clipboard-cut'/> - <menuitem action='contact-popup-clipboard-copy'/> - <menuitem action='contact-popup-clipboard-paste'/> + <menuitem action='popup-cut-clipboard'/> + <menuitem action='popup-copy-clipboard'/> + <menuitem action='popup-paste-clipboard'/> <menuitem action='contact-popup-delete'/> </popup> <popup name='contact-search-options'> diff --git a/ui/evolution-mail-reader.ui b/ui/evolution-mail-reader.ui index 1209144486..b54f4b970e 100644 --- a/ui/evolution-mail-reader.ui +++ b/ui/evolution-mail-reader.ui @@ -11,10 +11,6 @@ </menu> <menu action='edit-menu'> <placeholder name='edit-actions'> - <menuitem action='mail-clipboard-copy'/> - <separator/> - <menuitem action='mail-select-all'/> - <separator/> <menuitem action='mail-delete'/> <menuitem action='mail-undelete'/> <separator/> @@ -145,8 +141,6 @@ </placeholder> </popup> <popup name='mail-preview-popup'> - <menuitem action='mail-popup-clipboard-copy'/> - <separator/> <menuitem action='mail-popup-reply-sender'/> <menuitem action='mail-popup-reply-all'/> <menuitem action='mail-popup-forward'/> diff --git a/ui/evolution-mail.ui b/ui/evolution-mail.ui index f2c162c387..ec971201d1 100644 --- a/ui/evolution-mail.ui +++ b/ui/evolution-mail.ui @@ -42,7 +42,6 @@ <menuitem action='mail-folder-copy'/> <menuitem action='mail-folder-move'/> <separator/> - <menuitem action='mail-folder-select-all'/> <menuitem action='mail-folder-select-thread'/> <menuitem action='mail-folder-select-subthread'/> <menuitem action='mail-folder-mark-all-as-read'/> diff --git a/ui/evolution-memos.ui b/ui/evolution-memos.ui index 0d842b1526..29c4263440 100644 --- a/ui/evolution-memos.ui +++ b/ui/evolution-memos.ui @@ -11,10 +11,6 @@ </menu> <menu action='edit-menu'> <placeholder name='edit-actions'> - <menuitem action='memo-clipboard-cut'/> - <menuitem action='memo-clipboard-copy'/> - <menuitem action='memo-clipboard-paste'/> - <separator/> <menuitem action='memo-delete'/> </placeholder> </menu> @@ -31,9 +27,9 @@ </menubar> <toolbar name='main-toolbar'> <placeholder name='toolbar-actions'> - <toolitem action='memo-clipboard-cut'/> - <toolitem action='memo-clipboard-copy'/> - <toolitem action='memo-clipboard-paste'/> + <toolitem action='cut-clipboard'/> + <toolitem action='copy-clipboard'/> + <toolitem action='paste-clipboard'/> <separator/> <toolitem action='memo-list-print'/> <toolitem action='memo-delete'/> @@ -47,9 +43,9 @@ <menuitem action='memo-popup-save-as'/> <menuitem action='memo-popup-print'/> <separator/> - <menuitem action='memo-popup-clipboard-cut'/> - <menuitem action='memo-popup-clipboard-copy'/> - <menuitem action='memo-popup-clipboard-paste'/> + <menuitem action='popup-cut-clipboard'/> + <menuitem action='popup-copy-clipboard'/> + <menuitem action='popup-paste-clipboard'/> <separator/> <menuitem action='memo-popup-forward'/> <separator/> diff --git a/ui/evolution-shell.ui b/ui/evolution-shell.ui index ccfeb865d2..654d322f60 100644 --- a/ui/evolution-shell.ui +++ b/ui/evolution-shell.ui @@ -20,6 +20,12 @@ <menuitem action='quit'/> </menu> <menu action='edit-menu'> + <menuitem action='cut-clipboard'/> + <menuitem action='copy-clipboard'/> + <menuitem action='paste-clipboard'/> + <separator/> + <menuitem action='select-all'/> + <separator/> <placeholder name='edit-actions'/> <separator/> <menuitem action='sync-options'/> diff --git a/ui/evolution-tasks.ui b/ui/evolution-tasks.ui index 70695883df..de4d97e067 100644 --- a/ui/evolution-tasks.ui +++ b/ui/evolution-tasks.ui @@ -11,10 +11,6 @@ </menu> <menu action='edit-menu'> <placeholder name='edit-actions'> - <menuitem action='task-clipboard-cut'/> - <menuitem action='task-clipboard-copy'/> - <menuitem action='task-clipboard-paste'/> - <separator/> <menuitem action='task-delete'/> <separator/> <menuitem action='task-mark-complete'/> @@ -40,9 +36,9 @@ </placeholder> </menubar> <toolbar name='main-toolbar'> - <toolitem action='task-clipboard-cut'/> - <toolitem action='task-clipboard-copy'/> - <toolitem action='task-clipboard-paste'/> + <toolitem action='cut-clipboard'/> + <toolitem action='copy-clipboard'/> + <toolitem action='paste-clipboard'/> <separator/> <toolitem action='task-print'/> <toolitem action='task-delete'/> @@ -55,9 +51,9 @@ <menuitem action='task-popup-save-as'/> <menuitem action='task-popup-print'/> <separator/> - <menuitem action='task-popup-clipboard-cut'/> - <menuitem action='task-popup-clipboard-copy'/> - <menuitem action='task-popup-clipboard-paste'/> + <menuitem action='popup-cut-clipboard'/> + <menuitem action='popup-copy-clipboard'/> + <menuitem action='popup-paste-clipboard'/> <separator/> <menuitem action='task-popup-assign'/> <menuitem action='task-popup-forward'/> diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am index 33b9311d90..aa29f406df 100644 --- a/widgets/misc/Makefile.am +++ b/widgets/misc/Makefile.am @@ -46,6 +46,7 @@ widgetsinclude_HEADERS = \ e-colors.h \ e-combo-cell-editable.h \ e-dateedit.h \ + e-focus-tracker.h \ e-gui-utils.h \ e-hinted-entry.h \ e-hsv-utils.h \ @@ -60,6 +61,7 @@ widgetsinclude_HEADERS = \ e-popup-menu.h \ e-preferences-window.h \ e-printable.h \ + e-selectable.h \ e-selection-model.h \ e-selection-model-array.h \ e-selection-model-simple.h \ @@ -121,6 +123,7 @@ libemiscwidgets_la_SOURCES = \ e-colors.c \ e-combo-cell-editable.c \ e-dateedit.c \ + e-focus-tracker.c \ e-gui-utils.c \ e-hinted-entry.c \ e-hsv-utils.c \ @@ -135,6 +138,7 @@ libemiscwidgets_la_SOURCES = \ e-popup-menu.c \ e-preferences-window.c \ e-printable.c \ + e-selectable.c \ e-selection-model.c \ e-selection-model-array.c \ e-selection-model-simple.c \ diff --git a/widgets/misc/e-focus-tracker.c b/widgets/misc/e-focus-tracker.c new file mode 100644 index 0000000000..d1cb32adde --- /dev/null +++ b/widgets/misc/e-focus-tracker.c @@ -0,0 +1,859 @@ +/* + * e-focus-tracker.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-focus-tracker.h" + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include <misc/e-selectable.h> + +#define E_FOCUS_TRACKER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_FOCUS_TRACKER, EFocusTrackerPrivate)) + +struct _EFocusTrackerPrivate { + GtkWidget *focus; /* not referenced */ + GtkWindow *window; + + GtkAction *cut_clipboard; + GtkAction *copy_clipboard; + GtkAction *paste_clipboard; + GtkAction *delete_selection; + GtkAction *select_all; +}; + +enum { + PROP_0, + PROP_FOCUS, + PROP_WINDOW, + PROP_CUT_CLIPBOARD_ACTION, + PROP_COPY_CLIPBOARD_ACTION, + PROP_PASTE_CLIPBOARD_ACTION, + PROP_DELETE_SELECTION_ACTION, + PROP_SELECT_ALL_ACTION +}; + +static gpointer parent_class; + +static void +focus_tracker_disable_actions (EFocusTracker *focus_tracker) +{ + GtkAction *action; + + action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); + if (action != NULL) + gtk_action_set_sensitive (action, FALSE); + + action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); + if (action != NULL) + gtk_action_set_sensitive (action, FALSE); + + action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); + if (action != NULL) + gtk_action_set_sensitive (action, FALSE); + + action = e_focus_tracker_get_delete_selection_action (focus_tracker); + if (action != NULL) + gtk_action_set_sensitive (action, FALSE); + + action = e_focus_tracker_get_select_all_action (focus_tracker); + if (action != NULL) + gtk_action_set_sensitive (action, FALSE); +} + +static void +focus_tracker_editable_update_actions (EFocusTracker *focus_tracker, + GtkEditable *editable, + GdkAtom *targets, + gint n_targets) +{ + GtkAction *action; + gboolean can_edit_text; + gboolean clipboard_has_text; + gboolean text_is_selected; + gboolean sensitive; + + can_edit_text = + gtk_editable_get_editable (editable); + + clipboard_has_text = (targets != NULL) && + gtk_targets_include_text (targets, n_targets); + + text_is_selected = + gtk_editable_get_selection_bounds (editable, NULL, NULL); + + action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); + if (action != NULL) { + sensitive = can_edit_text && text_is_selected; + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, _("Cut the selection")); + } + + action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); + if (action != NULL) { + sensitive = text_is_selected; + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, _("Copy the selection")); + } + + action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); + if (action != NULL) { + sensitive = can_edit_text && clipboard_has_text; + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, _("Paste the clipboard")); + } + + action = e_focus_tracker_get_delete_selection_action (focus_tracker); + if (action != NULL) { + sensitive = can_edit_text && text_is_selected; + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, _("Delete the selection")); + } + + action = e_focus_tracker_get_select_all_action (focus_tracker); + if (action != NULL) { + sensitive = TRUE; /* always enabled */ + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, _("Select all text")); + } +} + +static void +focus_tracker_selectable_update_actions (EFocusTracker *focus_tracker, + ESelectable *selectable, + GdkAtom *targets, + gint n_targets) +{ + ESelectableInterface *interface; + GtkAction *action; + + interface = E_SELECTABLE_GET_INTERFACE (selectable); + + e_selectable_update_actions ( + selectable, focus_tracker, targets, n_targets); + + /* Disable actions for which the corresponding method is not + * implemented. This allows update_actions() implementations + * to simply skip the actions they don't support, which in turn + * allows us to add new actions without disturbing the existing + * ESelectable implementations. */ + + action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); + if (action != NULL && interface->cut_clipboard == NULL) + gtk_action_set_sensitive (action, FALSE); + + action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); + if (action != NULL && interface->copy_clipboard == NULL) + gtk_action_set_sensitive (action, FALSE); + + action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); + if (action != NULL && interface->paste_clipboard == NULL) + gtk_action_set_sensitive (action, FALSE); + + action = e_focus_tracker_get_delete_selection_action (focus_tracker); + if (action != NULL && interface->delete_selection == NULL) + gtk_action_set_sensitive (action, FALSE); + + action = e_focus_tracker_get_select_all_action (focus_tracker); + if (action != NULL && interface->select_all == NULL) + gtk_action_set_sensitive (action, FALSE); +} + +static void +focus_tracker_targets_received_cb (GtkClipboard *clipboard, + GdkAtom *targets, + gint n_targets, + EFocusTracker *focus_tracker) +{ + GtkWidget *focus; + + focus = e_focus_tracker_get_focus (focus_tracker); + + if (focus == NULL) + focus_tracker_disable_actions (focus_tracker); + + else if (GTK_IS_EDITABLE (focus)) + focus_tracker_editable_update_actions ( + focus_tracker, GTK_EDITABLE (focus), + targets, n_targets); + + else if (E_IS_SELECTABLE (focus)) + focus_tracker_selectable_update_actions ( + focus_tracker, E_SELECTABLE (focus), + targets, n_targets); + + g_object_unref (focus_tracker); +} + +static void +focus_tracker_set_focus_cb (GtkWindow *window, + GtkWidget *focus, + EFocusTracker *focus_tracker) +{ + while (focus != NULL) { + if (GTK_IS_EDITABLE (focus)) + break; + + if (E_IS_SELECTABLE (focus)) + break; + + focus = gtk_widget_get_parent (focus); + } + + if (focus == focus_tracker->priv->focus) + return; + + focus_tracker->priv->focus = focus; + g_object_notify (G_OBJECT (focus_tracker), "focus"); + + e_focus_tracker_update_actions (focus_tracker); +} + +static void +focus_tracker_set_window (EFocusTracker *focus_tracker, + GtkWindow *window) +{ + g_return_if_fail (GTK_IS_WINDOW (window)); + g_return_if_fail (focus_tracker->priv->window == NULL); + + focus_tracker->priv->window = g_object_ref (window); + + g_signal_connect ( + window, "set-focus", + G_CALLBACK (focus_tracker_set_focus_cb), focus_tracker); +} + +static void +focus_tracker_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_WINDOW: + focus_tracker_set_window ( + E_FOCUS_TRACKER (object), + g_value_get_object (value)); + return; + + case PROP_CUT_CLIPBOARD_ACTION: + e_focus_tracker_set_cut_clipboard_action ( + E_FOCUS_TRACKER (object), + g_value_get_object (value)); + return; + + case PROP_COPY_CLIPBOARD_ACTION: + e_focus_tracker_set_copy_clipboard_action ( + E_FOCUS_TRACKER (object), + g_value_get_object (value)); + return; + + case PROP_PASTE_CLIPBOARD_ACTION: + e_focus_tracker_set_paste_clipboard_action ( + E_FOCUS_TRACKER (object), + g_value_get_object (value)); + return; + + case PROP_DELETE_SELECTION_ACTION: + e_focus_tracker_set_delete_selection_action ( + E_FOCUS_TRACKER (object), + g_value_get_object (value)); + return; + + case PROP_SELECT_ALL_ACTION: + e_focus_tracker_set_select_all_action ( + E_FOCUS_TRACKER (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +focus_tracker_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FOCUS: + g_value_set_object ( + value, + e_focus_tracker_get_focus ( + E_FOCUS_TRACKER (object))); + return; + + case PROP_WINDOW: + g_value_set_object ( + value, + e_focus_tracker_get_window ( + E_FOCUS_TRACKER (object))); + return; + + case PROP_CUT_CLIPBOARD_ACTION: + g_value_set_object ( + value, + e_focus_tracker_get_cut_clipboard_action ( + E_FOCUS_TRACKER (object))); + return; + + case PROP_COPY_CLIPBOARD_ACTION: + g_value_set_object ( + value, + e_focus_tracker_get_copy_clipboard_action ( + E_FOCUS_TRACKER (object))); + return; + + case PROP_PASTE_CLIPBOARD_ACTION: + g_value_set_object ( + value, + e_focus_tracker_get_paste_clipboard_action ( + E_FOCUS_TRACKER (object))); + return; + + case PROP_DELETE_SELECTION_ACTION: + g_value_set_object ( + value, + e_focus_tracker_get_delete_selection_action ( + E_FOCUS_TRACKER (object))); + return; + + case PROP_SELECT_ALL_ACTION: + g_value_set_object ( + value, + e_focus_tracker_get_select_all_action ( + E_FOCUS_TRACKER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +focus_tracker_dispose (GObject *object) +{ + EFocusTrackerPrivate *priv; + + priv = E_FOCUS_TRACKER_GET_PRIVATE (object); + + g_signal_handlers_disconnect_matched ( + gtk_clipboard_get (GDK_SELECTION_PRIMARY), + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object); + + if (priv->window != NULL) { + g_signal_handlers_disconnect_matched ( + priv->window, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->window); + priv->window = NULL; + } + + if (priv->cut_clipboard != NULL) { + g_signal_handlers_disconnect_matched ( + priv->cut_clipboard, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->cut_clipboard); + priv->cut_clipboard = NULL; + } + + if (priv->copy_clipboard != NULL) { + g_signal_handlers_disconnect_matched ( + priv->copy_clipboard, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->copy_clipboard); + priv->copy_clipboard = NULL; + } + + if (priv->paste_clipboard != NULL) { + g_signal_handlers_disconnect_matched ( + priv->paste_clipboard, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->paste_clipboard); + priv->paste_clipboard = NULL; + } + + if (priv->delete_selection != NULL) { + g_signal_handlers_disconnect_matched ( + priv->delete_selection, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->delete_selection); + priv->delete_selection = NULL; + } + + if (priv->select_all != NULL) { + g_signal_handlers_disconnect_matched ( + priv->select_all, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->select_all); + priv->select_all = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +focus_tracker_constructed (GObject *object) +{ + GtkClipboard *clipboard; + + /* Listen for "owner-change" signals from the primary selection + * clipboard to learn when text selections change in GtkEditable + * widgets. It's a bit of an overkill, but I don't know of any + * other notification mechanism. */ + + clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY); + + g_signal_connect_swapped ( + clipboard, "owner-change", + G_CALLBACK (e_focus_tracker_update_actions), object); +} + +static void +focus_tracker_class_init (EFocusTrackerClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EFocusTrackerPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = focus_tracker_set_property; + object_class->get_property = focus_tracker_get_property; + object_class->dispose = focus_tracker_dispose; + object_class->constructed = focus_tracker_constructed; + + g_object_class_install_property ( + object_class, + PROP_FOCUS, + g_param_spec_object ( + "focus", + "Focus", + NULL, + GTK_TYPE_WIDGET, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_WINDOW, + g_param_spec_object ( + "window", + "Window", + NULL, + GTK_TYPE_WINDOW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + object_class, + PROP_CUT_CLIPBOARD_ACTION, + g_param_spec_object ( + "cut-clipboard-action", + "Cut Clipboard Action", + NULL, + GTK_TYPE_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_COPY_CLIPBOARD_ACTION, + g_param_spec_object ( + "copy-clipboard-action", + "Copy Clipboard Action", + NULL, + GTK_TYPE_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_PASTE_CLIPBOARD_ACTION, + g_param_spec_object ( + "paste-clipboard-action", + "Paste Clipboard Action", + NULL, + GTK_TYPE_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_DELETE_SELECTION_ACTION, + g_param_spec_object ( + "delete-selection-action", + "Delete Selection Action", + NULL, + GTK_TYPE_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SELECT_ALL_ACTION, + g_param_spec_object ( + "select-all-action", + "Select All Action", + NULL, + GTK_TYPE_ACTION, + G_PARAM_READWRITE)); +} + +static void +focus_tracker_init (EFocusTracker *focus_tracker) +{ + focus_tracker->priv = E_FOCUS_TRACKER_GET_PRIVATE (focus_tracker); +} + +GType +e_focus_tracker_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EFocusTrackerClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) focus_tracker_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EFocusTracker), + 0, /* n_preallocs */ + (GInstanceInitFunc) focus_tracker_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_OBJECT, "EFocusTracker", &type_info, 0); + } + + return type; +} + +EFocusTracker * +e_focus_tracker_new (GtkWindow *window) +{ + g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); + + return g_object_new (E_TYPE_FOCUS_TRACKER, "window", window, NULL); +} + +GtkWidget * +e_focus_tracker_get_focus (EFocusTracker *focus_tracker) +{ + g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); + + return focus_tracker->priv->focus; +} + +GtkWindow * +e_focus_tracker_get_window (EFocusTracker *focus_tracker) +{ + g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); + + return focus_tracker->priv->window; +} + +GtkAction * +e_focus_tracker_get_cut_clipboard_action (EFocusTracker *focus_tracker) +{ + g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); + + return focus_tracker->priv->cut_clipboard; +} + +void +e_focus_tracker_set_cut_clipboard_action (EFocusTracker *focus_tracker, + GtkAction *cut_clipboard) +{ + g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); + + if (cut_clipboard != NULL) { + g_return_if_fail (GTK_IS_ACTION (cut_clipboard)); + g_object_ref (cut_clipboard); + } + + if (focus_tracker->priv->cut_clipboard != NULL) { + g_signal_handlers_disconnect_matched ( + focus_tracker->priv->cut_clipboard, + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, + focus_tracker); + g_object_unref (focus_tracker->priv->cut_clipboard); + } + + focus_tracker->priv->cut_clipboard = cut_clipboard; + + if (cut_clipboard != NULL) + g_signal_connect_swapped ( + cut_clipboard, "activate", + G_CALLBACK (e_focus_tracker_cut_clipboard), + focus_tracker); + + g_object_notify (G_OBJECT (focus_tracker), "cut-clipboard-action"); +} + +GtkAction * +e_focus_tracker_get_copy_clipboard_action (EFocusTracker *focus_tracker) +{ + g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); + + return focus_tracker->priv->copy_clipboard; +} + +void +e_focus_tracker_set_copy_clipboard_action (EFocusTracker *focus_tracker, + GtkAction *copy_clipboard) +{ + g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); + + if (copy_clipboard != NULL) { + g_return_if_fail (GTK_IS_ACTION (copy_clipboard)); + g_object_ref (copy_clipboard); + } + + if (focus_tracker->priv->copy_clipboard != NULL) { + g_signal_handlers_disconnect_matched ( + focus_tracker->priv->copy_clipboard, + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, + focus_tracker); + g_object_unref (focus_tracker->priv->copy_clipboard); + } + + focus_tracker->priv->copy_clipboard = copy_clipboard; + + if (copy_clipboard != NULL) + g_signal_connect_swapped ( + copy_clipboard, "activate", + G_CALLBACK (e_focus_tracker_copy_clipboard), + focus_tracker); + + g_object_notify (G_OBJECT (focus_tracker), "copy-clipboard-action"); +} + +GtkAction * +e_focus_tracker_get_paste_clipboard_action (EFocusTracker *focus_tracker) +{ + g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); + + return focus_tracker->priv->paste_clipboard; +} + +void +e_focus_tracker_set_paste_clipboard_action (EFocusTracker *focus_tracker, + GtkAction *paste_clipboard) +{ + g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); + + if (paste_clipboard != NULL) { + g_return_if_fail (GTK_IS_ACTION (paste_clipboard)); + g_object_ref (paste_clipboard); + } + + if (focus_tracker->priv->paste_clipboard != NULL) { + g_signal_handlers_disconnect_matched ( + focus_tracker->priv->paste_clipboard, + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, + focus_tracker); + g_object_unref (focus_tracker->priv->paste_clipboard); + } + + focus_tracker->priv->paste_clipboard = paste_clipboard; + + if (paste_clipboard != NULL) + g_signal_connect_swapped ( + paste_clipboard, "activate", + G_CALLBACK (e_focus_tracker_paste_clipboard), + focus_tracker); + + g_object_notify (G_OBJECT (focus_tracker), "paste-clipboard-action"); +} + +GtkAction * +e_focus_tracker_get_delete_selection_action (EFocusTracker *focus_tracker) +{ + g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); + + return focus_tracker->priv->delete_selection; +} + +void +e_focus_tracker_set_delete_selection_action (EFocusTracker *focus_tracker, + GtkAction *delete_selection) +{ + g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); + + if (delete_selection != NULL) { + g_return_if_fail (GTK_IS_ACTION (delete_selection)); + g_object_ref (delete_selection); + } + + if (focus_tracker->priv->delete_selection != NULL) { + g_signal_handlers_disconnect_matched ( + focus_tracker->priv->delete_selection, + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, + focus_tracker); + g_object_unref (focus_tracker->priv->delete_selection); + } + + focus_tracker->priv->delete_selection = delete_selection; + + if (delete_selection != NULL) + g_signal_connect_swapped ( + delete_selection, "activate", + G_CALLBACK (e_focus_tracker_delete_selection), + focus_tracker); + + g_object_notify (G_OBJECT (focus_tracker), "delete-selection-action"); +} + +GtkAction * +e_focus_tracker_get_select_all_action (EFocusTracker *focus_tracker) +{ + g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); + + return focus_tracker->priv->select_all; +} + +void +e_focus_tracker_set_select_all_action (EFocusTracker *focus_tracker, + GtkAction *select_all) +{ + g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); + + if (select_all != NULL) { + g_return_if_fail (GTK_IS_ACTION (select_all)); + g_object_ref (select_all); + } + + if (focus_tracker->priv->select_all != NULL) { + g_signal_handlers_disconnect_matched ( + focus_tracker->priv->select_all, + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, + focus_tracker); + g_object_unref (focus_tracker->priv->select_all); + } + + focus_tracker->priv->select_all = select_all; + + if (select_all != NULL) + g_signal_connect_swapped ( + select_all, "activate", + G_CALLBACK (e_focus_tracker_select_all), + focus_tracker); + + g_object_notify (G_OBJECT (focus_tracker), "select-all-action"); +} + +void +e_focus_tracker_update_actions (EFocusTracker *focus_tracker) +{ + GtkClipboard *clipboard; + + g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); + + /* Request clipboard targets asynchronously. */ + + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + + gtk_clipboard_request_targets ( + clipboard, (GtkClipboardTargetsReceivedFunc) + focus_tracker_targets_received_cb, + g_object_ref (focus_tracker)); +} + +void +e_focus_tracker_cut_clipboard (EFocusTracker *focus_tracker) +{ + GtkWidget *focus; + + g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); + + focus = e_focus_tracker_get_focus (focus_tracker); + + if (GTK_IS_EDITABLE (focus)) + gtk_editable_cut_clipboard (GTK_EDITABLE (focus)); + + else if (E_IS_SELECTABLE (focus)) + e_selectable_cut_clipboard (E_SELECTABLE (focus)); +} + +void +e_focus_tracker_copy_clipboard (EFocusTracker *focus_tracker) +{ + GtkWidget *focus; + + g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); + + focus = e_focus_tracker_get_focus (focus_tracker); + + if (GTK_IS_EDITABLE (focus)) + gtk_editable_copy_clipboard (GTK_EDITABLE (focus)); + + else if (E_IS_SELECTABLE (focus)) + e_selectable_copy_clipboard (E_SELECTABLE (focus)); +} + +void +e_focus_tracker_paste_clipboard (EFocusTracker *focus_tracker) +{ + GtkWidget *focus; + + g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); + + focus = e_focus_tracker_get_focus (focus_tracker); + + if (GTK_IS_EDITABLE (focus)) + gtk_editable_paste_clipboard (GTK_EDITABLE (focus)); + + else if (E_IS_SELECTABLE (focus)) + e_selectable_paste_clipboard (E_SELECTABLE (focus)); +} + +void +e_focus_tracker_delete_selection (EFocusTracker *focus_tracker) +{ + GtkWidget *focus; + + g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); + + focus = e_focus_tracker_get_focus (focus_tracker); + + if (GTK_IS_EDITABLE (focus)) + gtk_editable_delete_selection (GTK_EDITABLE (focus)); + + else if (E_IS_SELECTABLE (focus)) + e_selectable_delete_selection (E_SELECTABLE (focus)); +} + +void +e_focus_tracker_select_all (EFocusTracker *focus_tracker) +{ + GtkWidget *focus; + + g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); + + focus = e_focus_tracker_get_focus (focus_tracker); + + if (GTK_IS_EDITABLE (focus)) + gtk_editable_select_region (GTK_EDITABLE (focus), 0, -1); + + else if (E_IS_SELECTABLE (focus)) + e_selectable_select_all (E_SELECTABLE (focus)); +} diff --git a/widgets/misc/e-focus-tracker.h b/widgets/misc/e-focus-tracker.h new file mode 100644 index 0000000000..679cc4b655 --- /dev/null +++ b/widgets/misc/e-focus-tracker.h @@ -0,0 +1,99 @@ +/* + * e-focus-tracker.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_FOCUS_TRACKER_H +#define E_FOCUS_TRACKER_H + +#include <gtk/gtk.h> + +/* Standard GObject macros */ +#define E_TYPE_FOCUS_TRACKER \ + (e_focus_tracker_get_type ()) +#define E_FOCUS_TRACKER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_FOCUS_TRACKER, EFocusTracker)) +#define E_FOCUS_TRACKER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_FOCUS_TRACKER, EFocusTrackerClass)) +#define E_IS_FOCUS_TRACKER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_FOCUS_TRACKER)) +#define E_IS_FOCUS_TRACKER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_FOCUS_TRACKER)) +#define E_FOCUS_TRACKER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_FOCUS_TRACKER, EFocusTrackerClass)) + +G_BEGIN_DECLS + +typedef struct _EFocusTracker EFocusTracker; +typedef struct _EFocusTrackerClass EFocusTrackerClass; +typedef struct _EFocusTrackerPrivate EFocusTrackerPrivate; + +struct _EFocusTracker { + GObject parent; + EFocusTrackerPrivate *priv; +}; + +struct _EFocusTrackerClass { + GObjectClass parent_class; +}; + +GType e_focus_tracker_get_type (void); +EFocusTracker * e_focus_tracker_new (GtkWindow *window); +GtkWidget * e_focus_tracker_get_focus (EFocusTracker *focus_tracker); +GtkWindow * e_focus_tracker_get_window (EFocusTracker *focus_tracker); +GtkAction * e_focus_tracker_get_cut_clipboard_action + (EFocusTracker *focus_tracker); +void e_focus_tracker_set_cut_clipboard_action + (EFocusTracker *focus_tracker, + GtkAction *cut_clipboard); +GtkAction * e_focus_tracker_get_copy_clipboard_action + (EFocusTracker *focus_tracker); +void e_focus_tracker_set_copy_clipboard_action + (EFocusTracker *focus_tracker, + GtkAction *copy_clipboard); +GtkAction * e_focus_tracker_get_paste_clipboard_action + (EFocusTracker *focus_tracker); +void e_focus_tracker_set_paste_clipboard_action + (EFocusTracker *focus_tracker, + GtkAction *paste_clipboard); +GtkAction * e_focus_tracker_get_delete_selection_action + (EFocusTracker *focus_tracker); +void e_focus_tracker_set_delete_selection_action + (EFocusTracker *focus_tracker, + GtkAction *delete_selection); +GtkAction * e_focus_tracker_get_select_all_action + (EFocusTracker *focus_tracker); +void e_focus_tracker_set_select_all_action + (EFocusTracker *focus_tracker, + GtkAction *select_all); +void e_focus_tracker_update_actions (EFocusTracker *focus_tracker); +void e_focus_tracker_cut_clipboard (EFocusTracker *focus_tracker); +void e_focus_tracker_copy_clipboard (EFocusTracker *focus_tracker); +void e_focus_tracker_paste_clipboard (EFocusTracker *focus_tracker); +void e_focus_tracker_delete_selection(EFocusTracker *focus_tracker); +void e_focus_tracker_select_all (EFocusTracker *focus_tracker); + +G_END_DECLS + +#endif /* E_FOCUS_TRACKER_H */ diff --git a/widgets/misc/e-selectable.c b/widgets/misc/e-selectable.c new file mode 100644 index 0000000000..95cd2bb06f --- /dev/null +++ b/widgets/misc/e-selectable.c @@ -0,0 +1,133 @@ +/* + * e-selectable.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-selectable.h" + +GType +e_selectable_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (ESelectableInterface), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) NULL, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + 0, /* instance_size */ + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_INTERFACE, "ESelectable", &type_info, 0); + + g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); + } + + return type; +} + +void +e_selectable_update_actions (ESelectable *selectable, + EFocusTracker *focus_tracker, + GdkAtom *clipboard_targets, + gint n_clipboard_targets) +{ + ESelectableInterface *interface; + + g_return_if_fail (E_IS_SELECTABLE (selectable)); + + interface = E_SELECTABLE_GET_INTERFACE (selectable); + g_return_if_fail (interface->update_actions != NULL); + + return interface->update_actions ( + selectable, focus_tracker, + clipboard_targets, n_clipboard_targets); +} + +void +e_selectable_cut_clipboard (ESelectable *selectable) +{ + ESelectableInterface *interface; + + g_return_if_fail (E_IS_SELECTABLE (selectable)); + + interface = E_SELECTABLE_GET_INTERFACE (selectable); + + if (interface->cut_clipboard != NULL) + interface->cut_clipboard (selectable); +} + +void +e_selectable_copy_clipboard (ESelectable *selectable) +{ + ESelectableInterface *interface; + + g_return_if_fail (E_IS_SELECTABLE (selectable)); + + interface = E_SELECTABLE_GET_INTERFACE (selectable); + + if (interface->copy_clipboard != NULL) + interface->copy_clipboard (selectable); +} + +void +e_selectable_paste_clipboard (ESelectable *selectable) +{ + ESelectableInterface *interface; + + g_return_if_fail (E_IS_SELECTABLE (selectable)); + + interface = E_SELECTABLE_GET_INTERFACE (selectable); + + if (interface->paste_clipboard != NULL) + interface->paste_clipboard (selectable); +} + +void +e_selectable_delete_selection (ESelectable *selectable) +{ + ESelectableInterface *interface; + + g_return_if_fail (E_IS_SELECTABLE (selectable)); + + interface = E_SELECTABLE_GET_INTERFACE (selectable); + + if (interface->delete_selection != NULL) + interface->delete_selection (selectable); +} + +void +e_selectable_select_all (ESelectable *selectable) +{ + ESelectableInterface *interface; + + g_return_if_fail (E_IS_SELECTABLE (selectable)); + + interface = E_SELECTABLE_GET_INTERFACE (selectable); + + if (interface->select_all != NULL) + interface->select_all (selectable); +} diff --git a/widgets/misc/e-selectable.h b/widgets/misc/e-selectable.h new file mode 100644 index 0000000000..fca400ce65 --- /dev/null +++ b/widgets/misc/e-selectable.h @@ -0,0 +1,76 @@ +/* + * e-selectable.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_SELECTABLE_H +#define E_SELECTABLE_H + +#include <gtk/gtk.h> +#include <misc/e-focus-tracker.h> + +/* Standard GObject macros */ +#define E_TYPE_SELECTABLE \ + (e_selectable_get_type ()) +#define E_SELECTABLE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SELECTABLE, ESelectable)) +#define E_IS_SELECTABLE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SELECTABLE)) +#define E_SELECTABLE_GET_INTERFACE(obj) \ + (G_TYPE_INSTANCE_GET_INTERFACE \ + ((obj), E_TYPE_SELECTABLE, ESelectableInterface)) + +G_BEGIN_DECLS + +typedef struct _ESelectable ESelectable; +typedef struct _ESelectableInterface ESelectableInterface; + +struct _ESelectableInterface { + GTypeInterface parent_iface; + + /* Required Methods */ + void (*update_actions) (ESelectable *selectable, + EFocusTracker *focus_tracker, + GdkAtom *clipboard_targets, + gint n_clipboard_targets); + + /* Optional Methods */ + void (*cut_clipboard) (ESelectable *selectable); + void (*copy_clipboard) (ESelectable *selectable); + void (*paste_clipboard) (ESelectable *selectable); + void (*delete_selection) (ESelectable *selectable); + void (*select_all) (ESelectable *selectable); +}; + +GType e_selectable_get_type (void); +void e_selectable_update_actions (ESelectable *selectable, + EFocusTracker *focus_tracker, + GdkAtom *clipboard_targets, + gint n_clipboard_targets); +void e_selectable_cut_clipboard (ESelectable *selectable); +void e_selectable_copy_clipboard (ESelectable *selectable); +void e_selectable_paste_clipboard (ESelectable *selectable); +void e_selectable_delete_selection (ESelectable *selectable); +void e_selectable_select_all (ESelectable *selectable); + +G_END_DECLS + +#endif /* E_SELECTABLE_H */ diff --git a/widgets/misc/e-signature-editor.c b/widgets/misc/e-signature-editor.c index 9266425494..91a4d81c8d 100644 --- a/widgets/misc/e-signature-editor.c +++ b/widgets/misc/e-signature-editor.c @@ -26,6 +26,7 @@ #include <e-util/e-alert-dialog.h> #include <e-util/e-signature-utils.h> +#include <misc/e-web-view.h> #define E_SIGNATURE_EDITOR_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ @@ -33,11 +34,13 @@ enum { PROP_0, + PROP_FOCUS_TRACKER, PROP_SIGNATURE }; struct _ESignatureEditorPrivate { GtkActionGroup *action_group; + EFocusTracker *focus_tracker; ESignature *signature; GtkWidget *entry; gchar *original_name; @@ -255,6 +258,12 @@ signature_editor_get_property (GObject *object, GParamSpec *pspec) { switch (property_id) { + case PROP_FOCUS_TRACKER: + g_value_set_object ( + value, e_signature_editor_get_focus_tracker ( + E_SIGNATURE_EDITOR (object))); + return; + case PROP_SIGNATURE: g_value_set_object ( value, e_signature_editor_get_signature ( @@ -277,6 +286,11 @@ signature_editor_dispose (GObject *object) priv->action_group = NULL; } + if (priv->focus_tracker != NULL) { + g_object_unref (priv->focus_tracker); + priv->focus_tracker = NULL; + } + if (priv->signature != NULL) { g_object_unref (priv->signature); priv->signature = NULL; @@ -320,6 +334,16 @@ signature_editor_class_init (ESignatureEditorClass *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_SIGNATURE, g_param_spec_object ( "signature", @@ -333,7 +357,10 @@ static void signature_editor_init (ESignatureEditor *editor) { GtkActionGroup *action_group; + EFocusTracker *focus_tracker; + GtkhtmlEditor *gtkhtml_editor; GtkUIManager *ui_manager; + GtkAction *action; GtkWidget *container; GtkWidget *widget; GtkWidget *vbox; @@ -342,7 +369,8 @@ signature_editor_init (ESignatureEditor *editor) editor->priv = E_SIGNATURE_EDITOR_GET_PRIVATE (editor); vbox = GTKHTML_EDITOR (editor)->vbox; - ui_manager = gtkhtml_editor_get_ui_manager (GTKHTML_EDITOR (editor)); + gtkhtml_editor = GTKHTML_EDITOR (editor); + ui_manager = gtkhtml_editor_get_ui_manager (gtkhtml_editor); gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); handle_error (&error); @@ -383,6 +411,28 @@ signature_editor_init (ESignatureEditor *editor) G_CALLBACK (signature_editor_delete_event_cb), NULL); e_signature_editor_set_signature (editor, NULL); + + /* Configure an EFocusTracker to manage selection actions. + * + * XXX GtkhtmlEditor does not manage its own selection actions, + * which is technically a bug but works in our favor here + * because it won't cause any conflicts with EFocusTracker. */ + + focus_tracker = e_focus_tracker_new (GTK_WINDOW (editor)); + + action = gtkhtml_editor_get_action (gtkhtml_editor, "cut"); + e_focus_tracker_set_cut_clipboard_action (focus_tracker, action); + + action = gtkhtml_editor_get_action (gtkhtml_editor, "copy"); + e_focus_tracker_set_copy_clipboard_action (focus_tracker, action); + + action = gtkhtml_editor_get_action (gtkhtml_editor, "paste"); + e_focus_tracker_set_paste_clipboard_action (focus_tracker, action); + + action = gtkhtml_editor_get_action (gtkhtml_editor, "select-all"); + e_focus_tracker_set_select_all_action (focus_tracker, action); + + editor->priv->focus_tracker = focus_tracker; } GType @@ -415,7 +465,17 @@ e_signature_editor_get_type (void) GtkWidget * e_signature_editor_new (void) { - return g_object_new (E_TYPE_SIGNATURE_EDITOR, NULL); + return g_object_new ( + E_TYPE_SIGNATURE_EDITOR, + "html", e_web_view_new (), NULL); +} + +EFocusTracker * +e_signature_editor_get_focus_tracker (ESignatureEditor *editor) +{ + g_return_val_if_fail (E_IS_SIGNATURE_EDITOR (editor), NULL); + + return editor->priv->focus_tracker; } ESignature * diff --git a/widgets/misc/e-signature-editor.h b/widgets/misc/e-signature-editor.h index 1e8b88a909..6d9f4a9b61 100644 --- a/widgets/misc/e-signature-editor.h +++ b/widgets/misc/e-signature-editor.h @@ -24,6 +24,7 @@ #include <gtkhtml-editor.h> #include <e-util/e-signature.h> +#include <misc/e-focus-tracker.h> /* Standard GObject macros */ #define E_TYPE_SIGNATURE_EDITOR \ @@ -61,6 +62,8 @@ struct _ESignatureEditorClass { GType e_signature_editor_get_type (void); GtkWidget * e_signature_editor_new (void); +EFocusTracker * e_signature_editor_get_focus_tracker + (ESignatureEditor *editor); ESignature * e_signature_editor_get_signature (ESignatureEditor *editor); void e_signature_editor_set_signature (ESignatureEditor *editor, ESignature *signature); diff --git a/widgets/misc/e-web-view.c b/widgets/misc/e-web-view.c index f52d7399eb..a873731014 100644 --- a/widgets/misc/e-web-view.c +++ b/widgets/misc/e-web-view.c @@ -33,6 +33,7 @@ #include "e-util/e-plugin-ui.h" #include "e-popup-action.h" +#include "e-selectable.h" #define E_WEB_VIEW_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ @@ -89,7 +90,7 @@ static guint signals[LAST_SIGNAL]; static const gchar *ui = "<ui>" " <popup name='context'>" -" <menuitem action='clipboard-copy'/>" +" <menuitem action='copy-clipboard'/>" " <separator/>" " <placeholder name='custom-actions-1'>" " <menuitem action='open'/>" @@ -240,10 +241,10 @@ web_view_request_read_cb (GFile *file, } static void -action_clipboard_copy_cb (GtkAction *action, +action_copy_clipboard_cb (GtkAction *action, EWebView *web_view) { - e_web_view_clipboard_copy (web_view); + e_web_view_copy_clipboard (web_view); } static void @@ -372,12 +373,12 @@ static GtkActionEntry mailto_entries[] = { static GtkActionEntry selection_entries[] = { - { "clipboard-copy", + { "copy-clipboard", GTK_STOCK_COPY, NULL, NULL, - N_("Copy the selection to the clipboard"), - G_CALLBACK (action_clipboard_copy_cb) }, + N_("Copy the selection"), + G_CALLBACK (action_copy_clipboard_cb) }, }; static GtkActionEntry standard_entries[] = { @@ -859,6 +860,52 @@ web_view_update_actions (EWebView *web_view) } static void +web_view_selectable_update_actions (ESelectable *selectable, + EFocusTracker *focus_tracker, + GdkAtom *clipboard_targets, + gint n_clipboard_targets) +{ + EWebView *web_view; + GtkAction *action; + const gchar *tooltip; + gboolean sensitive; + + web_view = E_WEB_VIEW (selectable); + + /* Copy Clipboard */ + + action = e_web_view_get_action (web_view, "copy-clipboard"); + sensitive = gtk_action_get_sensitive (action); + tooltip = gtk_action_get_tooltip (action); + + action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, tooltip); + + /* Select All */ + + action = e_web_view_get_action (web_view, "select-all"); + sensitive = gtk_action_get_sensitive (action); + tooltip = gtk_action_get_tooltip (action); + + action = e_focus_tracker_get_select_all_action (focus_tracker); + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, tooltip); +} + +static void +web_view_selectable_copy_clipboard (ESelectable *selectable) +{ + e_web_view_copy_clipboard (E_WEB_VIEW (selectable)); +} + +static void +web_view_selectable_select_all (ESelectable *selectable) +{ + e_web_view_select_all (E_WEB_VIEW (selectable)); +} + +static void web_view_class_init (EWebViewClass *class) { GObjectClass *object_class; @@ -1010,6 +1057,14 @@ web_view_class_init (EWebViewClass *class) } static void +web_view_selectable_init (ESelectableInterface *interface) +{ + interface->update_actions = web_view_selectable_update_actions; + interface->copy_clipboard = web_view_selectable_copy_clipboard; + interface->select_all = web_view_selectable_select_all; +} + +static void web_view_init (EWebView *web_view) { GtkUIManager *ui_manager; @@ -1140,8 +1195,17 @@ e_web_view_get_type (void) NULL /* value_table */ }; + static const GInterfaceInfo selectable_info = { + (GInterfaceInitFunc) web_view_selectable_init, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + type = g_type_register_static ( GTK_TYPE_HTML, "EWebView", &type_info, 0); + + g_type_add_interface_static ( + type, E_TYPE_SELECTABLE, &selectable_info); } return type; @@ -1411,7 +1475,7 @@ e_web_view_extract_uri (EWebView *web_view, } void -e_web_view_clipboard_copy (EWebView *web_view) +e_web_view_copy_clipboard (EWebView *web_view) { g_return_if_fail (E_IS_WEB_VIEW (web_view)); diff --git a/widgets/misc/e-web-view.h b/widgets/misc/e-web-view.h index 4a30b4bd80..123965c7d0 100644 --- a/widgets/misc/e-web-view.h +++ b/widgets/misc/e-web-view.h @@ -118,7 +118,7 @@ GtkActionGroup *e_web_view_get_action_group (EWebView *web_view, gchar * e_web_view_extract_uri (EWebView *web_view, GdkEventButton *event, GtkHTML *frame); -void e_web_view_clipboard_copy (EWebView *web_view); +void e_web_view_copy_clipboard (EWebView *web_view); gboolean e_web_view_is_selection_active (EWebView *web_view); gboolean e_web_view_scroll_forward (EWebView *web_view); gboolean e_web_view_scroll_backward (EWebView *web_view); diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c index f5cd6c0d16..2656f7f949 100644 --- a/widgets/table/e-table.c +++ b/widgets/table/e-table.c @@ -55,8 +55,6 @@ #define COLUMN_HEADER_HEIGHT 16 -G_DEFINE_TYPE (ETable, e_table, GTK_TYPE_TABLE) - #define d(x) #if d(!)0 @@ -77,6 +75,11 @@ enum { STATE_CHANGE, WHITE_SPACE_EVENT, + CUT_CLIPBOARD, + COPY_CLIPBOARD, + PASTE_CLIPBOARD, + SELECT_ALL, + TABLE_DRAG_BEGIN, TABLE_DRAG_END, TABLE_DRAG_DATA_GET, @@ -159,6 +162,8 @@ static gint et_focus (GtkWidget *container, GtkDirectionType direction); static void scroll_off (ETable *et); static void scroll_on (ETable *et, guint scroll_direction); +G_DEFINE_TYPE (ETable, e_table, GTK_TYPE_TABLE) + static void et_disconnect_model (ETable *et) { @@ -3357,4 +3362,3 @@ e_table_class_init (ETableClass *class) gal_a11y_e_table_init (); } - diff --git a/widgets/table/e-tree.c b/widgets/table/e-tree.c index 38c7a5111b..ba50be0625 100644 --- a/widgets/table/e-tree.c +++ b/widgets/table/e-tree.c @@ -54,8 +54,6 @@ #define COLUMN_HEADER_HEIGHT 16 -G_DEFINE_TYPE (ETree, e_tree, GTK_TYPE_TABLE) - #define d(x) #if d(!)0 @@ -76,6 +74,11 @@ enum { STATE_CHANGE, WHITE_SPACE_EVENT, + CUT_CLIPBOARD, + COPY_CLIPBOARD, + PASTE_CLIPBOARD, + SELECT_ALL, + TREE_DRAG_BEGIN, TREE_DRAG_END, TREE_DRAG_DATA_GET, @@ -245,6 +248,8 @@ static void hover_off (ETree *et); static void hover_on (ETree *et, gint x, gint y); static void context_destroyed (gpointer data, GObject *ctx); +G_DEFINE_TYPE (ETree, e_tree, GTK_TYPE_TABLE) + static void et_disconnect_from_etta (ETree *et) { |