aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--addressbook/gui/widgets/e-addressbook-view.c230
-rw-r--r--addressbook/gui/widgets/e-addressbook-view.h4
-rw-r--r--calendar/gui/dialogs/comp-editor.c153
-rw-r--r--calendar/gui/dialogs/comp-editor.h2
-rw-r--r--calendar/gui/e-cal-list-view.h3
-rw-r--r--calendar/gui/e-calendar-table.c540
-rw-r--r--calendar/gui/e-calendar-table.h5
-rw-r--r--calendar/gui/e-calendar-view.c682
-rw-r--r--calendar/gui/e-calendar-view.h3
-rw-r--r--calendar/gui/e-day-view-main-item.c1
-rw-r--r--calendar/gui/e-memo-table.c544
-rw-r--r--calendar/gui/e-memo-table.h5
-rw-r--r--calendar/gui/gnome-cal.h2
-rw-r--r--calendar/gui/goto.c1
-rw-r--r--calendar/gui/print.h1
-rw-r--r--composer/e-composer-private.c28
-rw-r--r--composer/e-composer-private.h3
-rw-r--r--composer/e-msg-composer.c295
-rw-r--r--composer/e-msg-composer.h2
-rw-r--r--configure.ac2
-rw-r--r--doc/reference/shell/tmpl/e-shell-window.sgml5
-rw-r--r--mail/e-mail-reader.c83
-rw-r--r--mail/message-list.c106
-rw-r--r--mail/message-list.h111
-rw-r--r--modules/addressbook/e-book-shell-content.c31
-rw-r--r--modules/addressbook/e-book-shell-content.h6
-rw-r--r--modules/addressbook/e-book-shell-view-actions.c92
-rw-r--r--modules/addressbook/e-book-shell-view-actions.h8
-rw-r--r--modules/addressbook/e-book-shell-view.c25
-rw-r--r--modules/calendar/e-cal-shell-content.c108
-rw-r--r--modules/calendar/e-cal-shell-content.h7
-rw-r--r--modules/calendar/e-cal-shell-view-actions.c63
-rw-r--r--modules/calendar/e-cal-shell-view-actions.h18
-rw-r--r--modules/calendar/e-cal-shell-view-memopad.c72
-rw-r--r--modules/calendar/e-cal-shell-view-taskpad.c72
-rw-r--r--modules/calendar/e-cal-shell-view.c20
-rw-r--r--modules/calendar/e-memo-shell-content.c5
-rw-r--r--modules/calendar/e-memo-shell-content.h3
-rw-r--r--modules/calendar/e-memo-shell-view-actions.c72
-rw-r--r--modules/calendar/e-memo-shell-view-actions.h6
-rw-r--r--modules/calendar/e-memo-shell-view.c18
-rw-r--r--modules/calendar/e-task-shell-content.c5
-rw-r--r--modules/calendar/e-task-shell-content.h3
-rw-r--r--modules/calendar/e-task-shell-view-actions.c72
-rw-r--r--modules/calendar/e-task-shell-view-actions.h6
-rw-r--r--modules/calendar/e-task-shell-view.c18
-rw-r--r--modules/mail/e-mail-shell-view-actions.c49
-rw-r--r--modules/mail/e-mail-shell-view-private.c1
-rw-r--r--modules/mail/e-mail-shell-view.c7
-rw-r--r--shell/e-shell-view.c45
-rw-r--r--shell/e-shell-window-actions.c73
-rw-r--r--shell/e-shell-window-actions.h10
-rw-r--r--shell/e-shell-window-private.c1
-rw-r--r--shell/e-shell-window-private.h2
-rw-r--r--shell/e-shell-window.c40
-rw-r--r--shell/e-shell-window.h2
-rw-r--r--ui/evolution-calendars.ui24
-rw-r--r--ui/evolution-contacts.ui12
-rw-r--r--ui/evolution-mail-reader.ui6
-rw-r--r--ui/evolution-mail.ui1
-rw-r--r--ui/evolution-memos.ui16
-rw-r--r--ui/evolution-shell.ui6
-rw-r--r--ui/evolution-tasks.ui16
-rw-r--r--widgets/misc/Makefile.am4
-rw-r--r--widgets/misc/e-focus-tracker.c859
-rw-r--r--widgets/misc/e-focus-tracker.h99
-rw-r--r--widgets/misc/e-selectable.c133
-rw-r--r--widgets/misc/e-selectable.h76
-rw-r--r--widgets/misc/e-signature-editor.c64
-rw-r--r--widgets/misc/e-signature-editor.h3
-rw-r--r--widgets/misc/e-web-view.c78
-rw-r--r--widgets/misc/e-web-view.h2
-rw-r--r--widgets/table/e-table.c10
-rw-r--r--widgets/table/e-tree.c9
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)
{