From c12e485e47f5ac99f0ddd7f7e90b9ab28b077c3d Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 11 Nov 2009 23:52:08 -0500 Subject: Simplify clipboard handling in addressbook. --- addressbook/gui/widgets/e-addressbook-view.c | 152 ++------ calendar/gui/Makefile.am | 3 - calendar/gui/e-cal-selection.c | 323 ---------------- calendar/gui/e-cal-selection.h | 75 ---- calendar/gui/e-calendar-table.c | 2 +- calendar/gui/e-calendar-view.c | 2 +- calendar/gui/e-memo-table.c | 2 +- e-util/Makefile.am | 6 +- e-util/e-selection.c | 536 +++++++++++++++++++++++++++ e-util/e-selection.h | 96 +++++ modules/addressbook/e-book-shell-content.c | 6 + modules/addressbook/e-book-shell-content.h | 3 +- modules/addressbook/e-book-shell-view.c | 5 +- modules/calendar/e-cal-shell-view-private.h | 2 +- 14 files changed, 692 insertions(+), 521 deletions(-) delete mode 100644 calendar/gui/e-cal-selection.c delete mode 100644 calendar/gui/e-cal-selection.h create mode 100644 e-util/e-selection.c create mode 100644 e-util/e-selection.h diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c index 280c4d3820..cfff4313bb 100644 --- a/addressbook/gui/widgets/e-addressbook-view.c +++ b/addressbook/gui/widgets/e-addressbook-view.c @@ -37,6 +37,7 @@ #include "ea-addressbook.h" #include "e-util/e-print.h" +#include "e-util/e-selection.h" #include "e-util/e-util.h" #include "libedataserver/e-sexp.h" #include @@ -78,15 +79,12 @@ struct _EAddressbookViewPrivate { EAddressbookModel *model; EActivity *activity; - GList *clipboard_contacts; ESource *source; GObject *object; GtkWidget *widget; GalViewInstance *view_instance; - - GtkWidget *invisible; }; enum { @@ -116,7 +114,6 @@ static GtkTargetEntry drag_types[] = { static gpointer parent_class; static guint signals[LAST_SIGNAL]; -static GdkAtom clipboard_atom = GDK_NONE; static void addressbook_view_emit_open_contact (EAddressbookView *view, @@ -401,77 +398,6 @@ addressbook_view_display_view_cb (EAddressbookView *view, command_state_change (view); } -static void -addressbook_view_selection_get_cb (EAddressbookView *view, - GtkSelectionData *selection_data, - guint info, - guint time_stamp) -{ - gchar *string; - - string = eab_contact_list_to_string (view->priv->clipboard_contacts); - - gtk_selection_data_set ( - selection_data, GDK_SELECTION_TYPE_STRING, - 8, (guchar *) string, strlen (string)); - - g_free (string); -} - -static void -addressbook_view_selection_clear_event_cb (EAddressbookView *view, - GdkEventSelection *event) -{ - GList *list; - - list = view->priv->clipboard_contacts; - view->priv->clipboard_contacts = NULL; - - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); -} - -static void -addressbook_view_selection_received_cb (EAddressbookView *view, - GtkSelectionData *selection_data, - guint time) -{ - EAddressbookModel *model; - GList *list, *iter; - EBook *book; - - model = e_addressbook_view_get_model (view); - book = e_addressbook_model_get_book (model); - - if (selection_data->length <= 0) - return; - - if (selection_data->type != GDK_SELECTION_TYPE_STRING) - return; - - if (selection_data->data[selection_data->length - 1] != 0) { - gchar *string; - - string = g_malloc0 (selection_data->length + 1); - memcpy (string, selection_data->data, selection_data->length); - list = eab_contact_list_from_string (string); - g_free (string); - } else - list = eab_contact_list_from_string ( - (gchar *) selection_data->data); - - for (iter = list; iter != NULL; iter = iter->next) { - EContact *contact = iter->data; - - /* XXX NULL for a callback /sigh */ - eab_merging_book_add_contact ( - book, contact, NULL /* XXX */, NULL); - } - - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); -} - static void addressbook_view_set_shell_view (EAddressbookView *view, EShellView *shell_view) @@ -575,11 +501,6 @@ addressbook_view_dispose (GObject *object) priv->activity = NULL; } - if (priv->invisible != NULL) { - gtk_widget_destroy (priv->invisible); - priv->invisible = NULL; - } - if (priv->source != NULL) { g_object_unref (priv->source); priv->source = NULL; @@ -590,12 +511,6 @@ addressbook_view_dispose (GObject *object) priv->view_instance = NULL; } - g_list_foreach ( - priv->clipboard_contacts, - (GFunc) g_object_unref, NULL); - g_list_free (priv->clipboard_contacts); - priv->clipboard_contacts = NULL; - /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -708,9 +623,6 @@ addressbook_view_class_init (EAddressbookViewClass *class) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - if (clipboard_atom == NULL) - clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); - /* init the accessibility support for e_addressbook_view */ eab_view_a11y_init (); } @@ -721,22 +633,6 @@ addressbook_view_init (EAddressbookView *view) view->priv = E_ADDRESSBOOK_VIEW_GET_PRIVATE (view); view->priv->model = e_addressbook_model_new (); - - view->priv->invisible = gtk_invisible_new (); - - gtk_selection_add_target ( - view->priv->invisible, clipboard_atom, - GDK_SELECTION_TYPE_STRING, 0); - - g_signal_connect_swapped ( - view->priv->invisible, "selection-get", - G_CALLBACK (addressbook_view_selection_get_cb), view); - g_signal_connect_swapped ( - view->priv->invisible, "selection-clear-event", - G_CALLBACK (addressbook_view_selection_clear_event_cb), view); - g_signal_connect_swapped ( - view->priv->invisible, "selection-received", - G_CALLBACK (addressbook_view_selection_received_cb), view); } GType @@ -1348,23 +1244,55 @@ e_addressbook_view_cut (EAddressbookView *view) void e_addressbook_view_copy (EAddressbookView *view) { + GtkClipboard *clipboard; + GList *contact_list; + gchar *string; + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - view->priv->clipboard_contacts = e_addressbook_view_get_selected (view); + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - gtk_selection_owner_set ( - view->priv->invisible, - clipboard_atom, GDK_CURRENT_TIME); + 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)); - gtk_selection_convert ( - view->priv->invisible, clipboard_atom, - GDK_SELECTION_TYPE_STRING, GDK_CURRENT_TIME); + 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 diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am index fc9c91047a..dd1357c6c5 100644 --- a/calendar/gui/Makefile.am +++ b/calendar/gui/Makefile.am @@ -18,7 +18,6 @@ ecalendarinclude_HEADERS = \ e-cal-event.h \ e-cal-model-calendar.h \ e-cal-model.h \ - e-cal-selection.h \ e-calendar-view.h \ e-cell-date-edit-text.h \ e-date-time-list.h \ @@ -113,8 +112,6 @@ libevolution_calendar_la_SOURCES = \ e-cal-model-memos.h \ e-cal-model-tasks.c \ e-cal-model-tasks.h \ - e-cal-selection.c \ - e-cal-selection.h \ e-calendar-selector.c \ e-calendar-selector.h \ e-calendar-table.c \ diff --git a/calendar/gui/e-cal-selection.c b/calendar/gui/e-cal-selection.c deleted file mode 100644 index 27da752c98..0000000000 --- a/calendar/gui/e-cal-selection.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * e-cal-selection.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 - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "e-cal-selection.h" - -#include - -typedef struct _RequestCalendarInfo RequestCalendarInfo; -typedef struct _WaitForDataResults WaitForDataResults; - -struct _RequestCalendarInfo { - GtkClipboardTextReceivedFunc callback; - gpointer user_data; -}; - -struct _WaitForDataResults { - GMainLoop *loop; - gpointer data; -}; - -enum { - ATOM_CALENDAR, - ATOM_X_CALENDAR, - ATOM_X_VCALENDAR, - NUM_CALENDAR_ATOMS -}; - -static GdkAtom calendar_atoms[NUM_CALENDAR_ATOMS]; - -static void -init_atoms (void) -{ - static gboolean initialized = FALSE; - - if (initialized) - return; - - calendar_atoms[ATOM_CALENDAR] = - gdk_atom_intern_static_string ("text/calendar"); - - calendar_atoms[ATOM_X_CALENDAR] = - gdk_atom_intern_static_string ("text/x-calendar"); - - calendar_atoms[ATOM_X_VCALENDAR] = - gdk_atom_intern_static_string ("text/x-vcalendar"); - - initialized = TRUE; -} - -void -e_target_list_add_calendar_targets (GtkTargetList *list, - guint info) -{ - gint ii; - - g_return_if_fail (list != NULL); - - init_atoms (); - - for (ii = 0; ii < NUM_CALENDAR_ATOMS; ii++) - gtk_target_list_add (list, calendar_atoms[ii], 0, info); -} - -gboolean -e_selection_data_set_calendar (GtkSelectionData *selection_data, - const gchar *source, - gint length) -{ - GdkAtom atom; - gint ii; - - g_return_val_if_fail (selection_data != NULL, FALSE); - - if (length < 0) - length = strlen (source); - - init_atoms (); - - atom = gtk_selection_data_get_target (selection_data); - - /* All calendar atoms are treated the same. */ - for (ii = 0; ii < NUM_CALENDAR_ATOMS; ii++) { - if (atom == calendar_atoms[ii]) { - gtk_selection_data_set ( - selection_data, atom, 8, - (guchar *) source, length); - return TRUE; - } - } - - return FALSE; -} - -gchar * -e_selection_data_get_calendar (GtkSelectionData *selection_data) -{ - GdkAtom data_type; - const guchar *data = NULL; - gint ii; - - /* XXX May need to do encoding and line ending conversions - * here. Not worrying about it for now. */ - - g_return_val_if_fail (selection_data != NULL, NULL); - - data = gtk_selection_data_get_data (selection_data); - data_type = gtk_selection_data_get_data_type (selection_data); - - /* All calendar atoms are treated the same. */ - for (ii = 0; ii < NUM_CALENDAR_ATOMS; ii++) - if (data_type == calendar_atoms[ii]) - return g_strdup ((gchar *) data); - - return NULL; -} - -gboolean -e_selection_data_targets_include_calendar (GtkSelectionData *selection_data) -{ - GdkAtom *targets; - gint n_targets; - gboolean result = FALSE; - - g_return_val_if_fail (selection_data != NULL, FALSE); - - if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) { - result = e_targets_include_calendar (targets, n_targets); - g_free (targets); - } - - return result; -} - -gboolean -e_targets_include_calendar (GdkAtom *targets, - gint n_targets) -{ - gint ii, jj; - - g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE); - - init_atoms (); - - for (ii = 0; ii < n_targets; ii++) - for (jj = 0; jj < NUM_CALENDAR_ATOMS; jj++) - if (targets[ii] == calendar_atoms[jj]) - return TRUE; - - return FALSE; -} - -static void -clipboard_get_calendar (GtkClipboard *clipboard, - GtkSelectionData *selection_data, - guint info, - gchar *source) -{ - e_selection_data_set_calendar (selection_data, source, -1); -} - -static void -clipboard_clear_calendar (GtkClipboard *clipboard, - gchar *source) -{ - g_free (source); -} - -void -e_clipboard_set_calendar (GtkClipboard *clipboard, - const gchar *source, - gint length) -{ - GtkTargetList *list; - GtkTargetEntry *targets; - gint n_targets; - - g_return_if_fail (clipboard != NULL); - g_return_if_fail (source != NULL); - - list = gtk_target_list_new (NULL, 0); - e_target_list_add_calendar_targets (list, 0); - - targets = gtk_target_table_new_from_list (list, &n_targets); - - if (length < 0) - length = strlen (source); - - gtk_clipboard_set_with_data ( - clipboard, targets, n_targets, - (GtkClipboardGetFunc) clipboard_get_calendar, - (GtkClipboardClearFunc) clipboard_clear_calendar, - g_strndup (source, length)); - - gtk_clipboard_set_can_store (clipboard, NULL, 0); - - gtk_target_table_free (targets, n_targets); - gtk_target_list_unref (list); -} - -static void -clipboard_request_calendar_cb (GtkClipboard *clipboard, - GtkSelectionData *selection_data, - RequestCalendarInfo *info) -{ - gchar *source; - - source = e_selection_data_get_calendar (selection_data); - info->callback (clipboard, source, info->user_data); - g_free (source); - - g_slice_free (RequestCalendarInfo, info); -} - -void -e_clipboard_request_calendar (GtkClipboard *clipboard, - GtkClipboardTextReceivedFunc callback, - gpointer user_data) -{ - RequestCalendarInfo *info; - - g_return_if_fail (clipboard != NULL); - g_return_if_fail (callback != NULL); - - info = g_slice_new (RequestCalendarInfo); - info->callback = callback; - info->user_data = user_data; - - gtk_clipboard_request_contents ( - clipboard, calendar_atoms[ATOM_CALENDAR], - (GtkClipboardReceivedFunc) - clipboard_request_calendar_cb, info); -} - -static void -clipboard_wait_for_calendar_cb (GtkClipboard *clipboard, - const gchar *source, - WaitForDataResults *results) -{ - results->data = g_strdup (source); - g_main_loop_quit (results->loop); -} - -gchar * -e_clipboard_wait_for_calendar (GtkClipboard *clipboard) -{ - WaitForDataResults results; - - g_return_val_if_fail (clipboard != NULL, NULL); - - results.data = NULL; - results.loop = g_main_loop_new (NULL, TRUE); - - e_clipboard_request_calendar ( - clipboard, (GtkClipboardTextReceivedFunc) - clipboard_wait_for_calendar_cb, &results); - - if (g_main_loop_is_running (results.loop)) { - GDK_THREADS_LEAVE (); - g_main_loop_run (results.loop); - GDK_THREADS_ENTER (); - } - - g_main_loop_unref (results.loop); - - return results.data; -} - -gboolean -e_clipboard_wait_is_calendar_available (GtkClipboard *clipboard) -{ - GdkAtom *targets; - gint n_targets; - gboolean result = FALSE; - - if (gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets)) { - result = e_targets_include_calendar (targets, n_targets); - g_free (targets); - } - - return result; -} - -void -e_clipboard_print_targets (GtkClipboard *clipboard) -{ - GdkAtom *targets; - gchar *target_name; - gint n_targets, ii; - - g_return_if_fail (clipboard != NULL); - - gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets); - - g_print ("Clipboard Targets:\n"); - - if (n_targets == 0) - g_print (" (none)\n"); - else for (ii = 0; ii < n_targets; ii++) { - target_name = gdk_atom_name (targets[ii]); - g_print (" %s\n", target_name); - g_free (target_name); - } - - g_free (targets); -} diff --git a/calendar/gui/e-cal-selection.h b/calendar/gui/e-cal-selection.h deleted file mode 100644 index c79f1d608d..0000000000 --- a/calendar/gui/e-cal-selection.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * e-cal-selection.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 - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/** - * SECTION: e-cal-selection - * @short_description: calendar selection utilities - * @include: calendar/gui/e-cal-selection.h - **/ - -#ifndef E_CAL_SELECTION_H -#define E_CAL_SELECTION_H - -#include - -/* This API mimics GTK's API for dealing with text, image and URI data. */ - -G_BEGIN_DECLS - -/* Selection Functions */ - -void e_target_list_add_calendar_targets - (GtkTargetList *list, - guint info); -gboolean e_selection_data_set_calendar - (GtkSelectionData *selection_data, - const gchar *source, - gint length); -gchar * e_selection_data_get_calendar - (GtkSelectionData *selection_data); -gboolean e_selection_data_targets_include_calendar - (GtkSelectionData *selection_data); -gboolean e_targets_include_calendar - (GdkAtom *targets, - gint n_targets); - -/* Clipboard Functions */ - -void e_clipboard_set_calendar(GtkClipboard *clipboard, - const gchar *source, - gint length); -void e_clipboard_request_calendar - (GtkClipboard *clipboard, - GtkClipboardTextReceivedFunc callback, - gpointer user_data); -gchar * e_clipboard_wait_for_calendar - (GtkClipboard *clipboard); -gboolean e_clipboard_wait_is_calendar_available - (GtkClipboard *clipboard); - -/* Debugging Functions */ - -void e_clipboard_print_targets - (GtkClipboard *clipboard); - -G_END_DECLS - -#endif /* E_CAL_SELECTION_H */ diff --git a/calendar/gui/e-calendar-table.c b/calendar/gui/e-calendar-table.c index 3903c58888..4ea57c2abb 100644 --- a/calendar/gui/e-calendar-table.c +++ b/calendar/gui/e-calendar-table.c @@ -43,6 +43,7 @@ #include #include
#include +#include #include #include #include
@@ -55,7 +56,6 @@ #include "dialogs/delete-error.h" #include "dialogs/task-editor.h" #include "e-cal-model-tasks.h" -#include "e-cal-selection.h" #include "e-calendar-table.h" #include "e-calendar-view.h" #include "e-cell-date-edit-text.h" diff --git a/calendar/gui/e-calendar-view.c b/calendar/gui/e-calendar-view.c index 0ea84e1268..84812d60c5 100644 --- a/calendar/gui/e-calendar-view.c +++ b/calendar/gui/e-calendar-view.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -45,7 +46,6 @@ #include "comp-util.h" #include "ea-calendar.h" #include "e-cal-model-calendar.h" -#include "e-cal-selection.h" #include "e-calendar-view.h" #include "itip-utils.h" #include "dialogs/comp-editor-util.h" diff --git a/calendar/gui/e-memo-table.c b/calendar/gui/e-memo-table.c index c111bd668d..fc4b2c82ce 100644 --- a/calendar/gui/e-memo-table.c +++ b/calendar/gui/e-memo-table.c @@ -42,6 +42,7 @@ #include
#include
#include
+#include #include #include #include
@@ -53,7 +54,6 @@ #include "dialogs/delete-error.h" #include "dialogs/memo-editor.h" #include "e-cal-model-memos.h" -#include "e-cal-selection.h" #include "e-memo-table.h" #include "e-calendar-view.h" #include "e-cell-date-edit-text.h" diff --git a/e-util/Makefile.am b/e-util/Makefile.am index 688c7e73ec..3014458f28 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -15,6 +15,7 @@ eutilinclude_HEADERS = \ e-alert-activity.h \ e-bconf-map.h \ e-binding.h \ + e-bit-array.h \ e-categories-config.h \ e-charset.h \ e-config.h \ @@ -38,10 +39,10 @@ eutilinclude_HEADERS = \ e-plugin.h \ e-plugin-ui.h \ e-profile-event.h \ + e-selection.h \ e-signature.h \ e-signature-list.h \ e-signature-utils.h \ - e-bit-array.h \ e-sorter.h \ e-sorter-array.h \ e-text-event-processor-emacs-like.h \ @@ -88,6 +89,7 @@ libeutil_la_SOURCES = \ e-alert-activity.c \ e-bconf-map.c \ e-binding.c \ + e-bit-array.c \ e-categories-config.c \ e-charset.c \ e-config.c \ @@ -111,10 +113,10 @@ libeutil_la_SOURCES = \ e-plugin.c \ e-print.c \ e-profile-event.c \ + e-selection.c \ e-signature.c \ e-signature-list.c \ e-signature-utils.c \ - e-bit-array.c \ e-sorter.c \ e-sorter-array.c \ e-text-event-processor-emacs-like.c \ diff --git a/e-util/e-selection.c b/e-util/e-selection.c new file mode 100644 index 0000000000..8d2efff764 --- /dev/null +++ b/e-util/e-selection.c @@ -0,0 +1,536 @@ +/* + * e-selection.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 + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-selection.h" + +#include + +typedef struct _RequestTextInfo RequestTextInfo; +typedef struct _WaitForDataResults WaitForDataResults; + +struct _RequestTextInfo { + GtkClipboardTextReceivedFunc callback; + gpointer user_data; +}; + +struct _WaitForDataResults { + GMainLoop *loop; + gpointer data; +}; + +enum { + ATOM_CALENDAR, + ATOM_X_VCALENDAR, + NUM_CALENDAR_ATOMS +}; + +enum { + ATOM_DIRECTORY, + ATOM_X_VCARD, + NUM_DIRECTORY_ATOMS +}; + +static GdkAtom calendar_atoms[NUM_CALENDAR_ATOMS]; +static GdkAtom directory_atoms[NUM_DIRECTORY_ATOMS]; + +static void +init_atoms (void) +{ + static gboolean initialized = FALSE; + + if (initialized) + return; + + /* Calendar Atoms */ + + calendar_atoms[ATOM_CALENDAR] = + gdk_atom_intern_static_string ("text/calendar"); + + calendar_atoms[ATOM_X_VCALENDAR] = + gdk_atom_intern_static_string ("text/x-vcalendar"); + + /* Directory Atoms */ + + directory_atoms[ATOM_DIRECTORY] = + gdk_atom_intern_static_string ("text/directory"); + + directory_atoms[ATOM_X_VCARD] = + gdk_atom_intern_static_string ("text/x-vcard"); + + initialized = TRUE; +} + +static void +clipboard_wait_for_text_cb (GtkClipboard *clipboard, + const gchar *source, + WaitForDataResults *results) +{ + results->data = g_strdup (source); + g_main_loop_quit (results->loop); +} + +void +e_target_list_add_calendar_targets (GtkTargetList *list, + guint info) +{ + gint ii; + + g_return_if_fail (list != NULL); + + init_atoms (); + + for (ii = 0; ii < NUM_CALENDAR_ATOMS; ii++) + gtk_target_list_add (list, calendar_atoms[ii], 0, info); +} + +void +e_target_list_add_directory_targets (GtkTargetList *list, + guint info) +{ + gint ii; + + g_return_if_fail (list != NULL); + + init_atoms (); + + for (ii = 0; ii < NUM_DIRECTORY_ATOMS; ii++) + gtk_target_list_add (list, directory_atoms[ii], 0, info); +} + +gboolean +e_selection_data_set_calendar (GtkSelectionData *selection_data, + const gchar *source, + gint length) +{ + GdkAtom atom; + gint ii; + + g_return_val_if_fail (selection_data != NULL, FALSE); + + if (length < 0) + length = strlen (source); + + init_atoms (); + + atom = gtk_selection_data_get_target (selection_data); + + /* All calendar atoms are treated the same. */ + for (ii = 0; ii < NUM_CALENDAR_ATOMS; ii++) { + if (atom == calendar_atoms[ii]) { + gtk_selection_data_set ( + selection_data, atom, 8, + (guchar *) source, length); + return TRUE; + } + } + + return FALSE; +} + +gboolean +e_selection_data_set_directory (GtkSelectionData *selection_data, + const gchar *source, + gint length) +{ + GdkAtom atom; + gint ii; + + g_return_val_if_fail (selection_data != NULL, FALSE); + + if (length < 0) + length = strlen (source); + + init_atoms (); + + atom = gtk_selection_data_get_target (selection_data); + + /* All directory atoms are treated the same. */ + for (ii = 0; ii < NUM_DIRECTORY_ATOMS; ii++) { + if (atom == directory_atoms[ii]) { + gtk_selection_data_set ( + selection_data, atom, 8, + (guchar *) source, length); + return TRUE; + } + } + + return FALSE; +} + +gchar * +e_selection_data_get_calendar (GtkSelectionData *selection_data) +{ + GdkAtom data_type; + const guchar *data = NULL; + gint ii; + + /* XXX May need to do encoding and line ending conversions + * here. Not worrying about it for now. */ + + g_return_val_if_fail (selection_data != NULL, NULL); + + data = gtk_selection_data_get_data (selection_data); + data_type = gtk_selection_data_get_data_type (selection_data); + + /* All calendar atoms are treated the same. */ + for (ii = 0; ii < NUM_CALENDAR_ATOMS; ii++) + if (data_type == calendar_atoms[ii]) + return g_strdup ((gchar *) data); + + return NULL; +} + +gchar * +e_selection_data_get_directory (GtkSelectionData *selection_data) +{ + GdkAtom data_type; + const guchar *data = NULL; + gint ii; + + /* XXX May need to do encoding and line ending conversions + * here. Not worrying about it for now. */ + + g_return_val_if_fail (selection_data != NULL, NULL); + + data = gtk_selection_data_get_data (selection_data); + data_type = gtk_selection_data_get_data_type (selection_data); + + /* All directory atoms are treated the same. */ + for (ii = 0; ii < NUM_DIRECTORY_ATOMS; ii++) + if (data_type == directory_atoms[ii]) + return g_strdup ((gchar *) data); + + return NULL; +} + +gboolean +e_selection_data_targets_include_calendar (GtkSelectionData *selection_data) +{ + GdkAtom *targets; + gint n_targets; + gboolean result = FALSE; + + g_return_val_if_fail (selection_data != NULL, FALSE); + + if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) { + result = e_targets_include_calendar (targets, n_targets); + g_free (targets); + } + + return result; +} + +gboolean +e_selection_data_targets_include_directory (GtkSelectionData *selection_data) +{ + GdkAtom *targets; + gint n_targets; + gboolean result = FALSE; + + g_return_val_if_fail (selection_data != NULL, FALSE); + + if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) { + result = e_targets_include_directory (targets, n_targets); + g_free (targets); + } + + return result; +} + +gboolean +e_targets_include_calendar (GdkAtom *targets, + gint n_targets) +{ + gint ii, jj; + + g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE); + + init_atoms (); + + for (ii = 0; ii < n_targets; ii++) + for (jj = 0; jj < NUM_CALENDAR_ATOMS; jj++) + if (targets[ii] == calendar_atoms[jj]) + return TRUE; + + return FALSE; +} + +gboolean +e_targets_include_directory (GdkAtom *targets, + gint n_targets) +{ + gint ii, jj; + + g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE); + + init_atoms (); + + for (ii = 0; ii < n_targets; ii++) + for (jj = 0; jj < NUM_DIRECTORY_ATOMS; jj++) + if (targets[ii] == directory_atoms[jj]) + return TRUE; + + return FALSE; +} + +static void +clipboard_get_calendar (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + guint info, + gchar *source) +{ + e_selection_data_set_calendar (selection_data, source, -1); +} + +static void +clipboard_clear_calendar (GtkClipboard *clipboard, + gchar *source) +{ + g_free (source); +} + +void +e_clipboard_set_calendar (GtkClipboard *clipboard, + const gchar *source, + gint length) +{ + GtkTargetList *list; + GtkTargetEntry *targets; + gint n_targets; + + g_return_if_fail (clipboard != NULL); + g_return_if_fail (source != NULL); + + list = gtk_target_list_new (NULL, 0); + e_target_list_add_calendar_targets (list, 0); + + targets = gtk_target_table_new_from_list (list, &n_targets); + + if (length < 0) + length = strlen (source); + + gtk_clipboard_set_with_data ( + clipboard, targets, n_targets, + (GtkClipboardGetFunc) clipboard_get_calendar, + (GtkClipboardClearFunc) clipboard_clear_calendar, + g_strndup (source, length)); + + gtk_clipboard_set_can_store (clipboard, NULL, 0); + + gtk_target_table_free (targets, n_targets); + gtk_target_list_unref (list); +} + +static void +clipboard_get_directory (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + guint info, + gchar *source) +{ + e_selection_data_set_directory (selection_data, source, -1); +} + +static void +clipboard_clear_directory (GtkClipboard *clipboard, + gchar *source) +{ + g_free (source); +} + +void +e_clipboard_set_directory (GtkClipboard *clipboard, + const gchar *source, + gint length) +{ + GtkTargetList *list; + GtkTargetEntry *targets; + gint n_targets; + + g_return_if_fail (clipboard != NULL); + g_return_if_fail (source != NULL); + + list = gtk_target_list_new (NULL, 0); + e_target_list_add_directory_targets (list, 0); + + targets = gtk_target_table_new_from_list (list, &n_targets); + + if (length < 0) + length = strlen (source); + + gtk_clipboard_set_with_data ( + clipboard, targets, n_targets, + (GtkClipboardGetFunc) clipboard_get_directory, + (GtkClipboardClearFunc) clipboard_clear_directory, + g_strndup (source, length)); + + gtk_clipboard_set_can_store (clipboard, NULL, 0); + + gtk_target_table_free (targets, n_targets); + gtk_target_list_unref (list); +} + +static void +clipboard_request_calendar_cb (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + RequestTextInfo *info) +{ + gchar *source; + + source = e_selection_data_get_calendar (selection_data); + info->callback (clipboard, source, info->user_data); + g_free (source); + + g_slice_free (RequestTextInfo, info); +} + +void +e_clipboard_request_calendar (GtkClipboard *clipboard, + GtkClipboardTextReceivedFunc callback, + gpointer user_data) +{ + RequestTextInfo *info; + + g_return_if_fail (clipboard != NULL); + g_return_if_fail (callback != NULL); + + info = g_slice_new (RequestTextInfo); + info->callback = callback; + info->user_data = user_data; + + gtk_clipboard_request_contents ( + clipboard, calendar_atoms[ATOM_CALENDAR], + (GtkClipboardReceivedFunc) + clipboard_request_calendar_cb, info); +} + +static void +clipboard_request_directory_cb (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + RequestTextInfo *info) +{ + gchar *source; + + source = e_selection_data_get_directory (selection_data); + info->callback (clipboard, source, info->user_data); + g_free (source); + + g_slice_free (RequestTextInfo, info); +} + +void +e_clipboard_request_directory (GtkClipboard *clipboard, + GtkClipboardTextReceivedFunc callback, + gpointer user_data) +{ + RequestTextInfo *info; + + g_return_if_fail (clipboard != NULL); + g_return_if_fail (callback != NULL); + + info = g_slice_new (RequestTextInfo); + info->callback = callback; + info->user_data = user_data; + + gtk_clipboard_request_contents ( + clipboard, directory_atoms[ATOM_DIRECTORY], + (GtkClipboardReceivedFunc) + clipboard_request_directory_cb, info); +} + +gchar * +e_clipboard_wait_for_calendar (GtkClipboard *clipboard) +{ + WaitForDataResults results; + + g_return_val_if_fail (clipboard != NULL, NULL); + + results.data = NULL; + results.loop = g_main_loop_new (NULL, TRUE); + + e_clipboard_request_calendar ( + clipboard, (GtkClipboardTextReceivedFunc) + clipboard_wait_for_text_cb, &results); + + if (g_main_loop_is_running (results.loop)) { + GDK_THREADS_LEAVE (); + g_main_loop_run (results.loop); + GDK_THREADS_ENTER (); + } + + g_main_loop_unref (results.loop); + + return results.data; +} + +gchar * +e_clipboard_wait_for_directory (GtkClipboard *clipboard) +{ + WaitForDataResults results; + + g_return_val_if_fail (clipboard != NULL, NULL); + + results.data = NULL; + results.loop = g_main_loop_new (NULL, TRUE); + + e_clipboard_request_directory ( + clipboard, (GtkClipboardTextReceivedFunc) + clipboard_wait_for_text_cb, &results); + + if (g_main_loop_is_running (results.loop)) { + GDK_THREADS_LEAVE (); + g_main_loop_run (results.loop); + GDK_THREADS_ENTER (); + } + + g_main_loop_unref (results.loop); + + return results.data; +} + +gboolean +e_clipboard_wait_is_calendar_available (GtkClipboard *clipboard) +{ + GdkAtom *targets; + gint n_targets; + gboolean result = FALSE; + + if (gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets)) { + result = e_targets_include_calendar (targets, n_targets); + g_free (targets); + } + + return result; +} + +gboolean +e_clipboard_wait_is_directory_available (GtkClipboard *clipboard) +{ + GdkAtom *targets; + gint n_targets; + gboolean result = FALSE; + + if (gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets)) { + result = e_targets_include_directory (targets, n_targets); + g_free (targets); + } + + return result; +} diff --git a/e-util/e-selection.h b/e-util/e-selection.h new file mode 100644 index 0000000000..b0b2d1f3b6 --- /dev/null +++ b/e-util/e-selection.h @@ -0,0 +1,96 @@ +/* + * e-cal-selection.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 + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/** + * SECTION: e-selection + * @short_description: selection and clipboard utilities + * @include: e-util/e-selection.h + **/ + +#ifndef E_SELECTION_H +#define E_SELECTION_H + +#include + +/* This API mimics GTK's API for dealing with text, image and URI data. */ + +G_BEGIN_DECLS + +/* Selection Functions */ + +void e_target_list_add_calendar_targets + (GtkTargetList *list, + guint info); +void e_target_list_add_directory_targets + (GtkTargetList *list, + guint info); +gboolean e_selection_data_set_calendar + (GtkSelectionData *selection_data, + const gchar *source, + gint length); +gboolean e_selection_data_set_directory + (GtkSelectionData *selection_data, + const gchar *source, + gint length); +gchar * e_selection_data_get_calendar + (GtkSelectionData *selection_data); +gchar * e_selection_data_get_directory + (GtkSelectionData *selection_data); +gboolean e_selection_data_targets_include_calendar + (GtkSelectionData *selection_data); +gboolean e_selection_data_targets_include_directory + (GtkSelectionData *selection_data); +gboolean e_targets_include_calendar + (GdkAtom *targets, + gint n_targets); +gboolean e_targets_include_directory + (GdkAtom *targets, + gint n_targets); + +/* Clipboard Functions */ + +void e_clipboard_set_calendar(GtkClipboard *clipboard, + const gchar *source, + gint length); +void e_clipboard_set_directory + (GtkClipboard *clipboard, + const gchar *source, + gint length); +void e_clipboard_request_calendar + (GtkClipboard *clipboard, + GtkClipboardTextReceivedFunc callback, + gpointer user_data); +void e_clipboard_request_directory + (GtkClipboard *clipboard, + GtkClipboardTextReceivedFunc callback, + gpointer user_data); +gchar * e_clipboard_wait_for_calendar + (GtkClipboard *clipboard); +gchar * e_clipboard_wait_for_directory + (GtkClipboard *clipboard); +gboolean e_clipboard_wait_is_calendar_available + (GtkClipboard *clipboard); +gboolean e_clipboard_wait_is_directory_available + (GtkClipboard *clipboard); + +G_END_DECLS + +#endif /* E_SELECTION_H */ diff --git a/modules/addressbook/e-book-shell-content.c b/modules/addressbook/e-book-shell-content.c index 898bd2df39..4eccc971df 100644 --- a/modules/addressbook/e-book-shell-content.c +++ b/modules/addressbook/e-book-shell-content.c @@ -24,6 +24,7 @@ #include #include "e-util/e-binding.h" +#include "e-util/e-selection.h" #include "e-util/gconf-bridge.h" #include "widgets/misc/e-paned.h" @@ -258,6 +259,7 @@ book_shell_content_check_state (EShellContent *shell_content) ESelectionModel *selection_model; EAddressbookModel *model; EAddressbookView *view; + GtkClipboard *clipboard; guint32 state = 0; gint n_contacts; gint n_selected; @@ -272,6 +274,8 @@ book_shell_content_check_state (EShellContent *shell_content) n_selected = (selection_model != NULL) ? e_selection_model_selected_count (selection_model) : 0; + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + /* FIXME Finish the rest of the flags. */ if (n_selected == 1) state |= E_BOOK_SHELL_CONTENT_SELECTION_SINGLE; @@ -283,6 +287,8 @@ book_shell_content_check_state (EShellContent *shell_content) 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; } diff --git a/modules/addressbook/e-book-shell-content.h b/modules/addressbook/e-book-shell-content.h index da78c01274..31f8c35838 100644 --- a/modules/addressbook/e-book-shell-content.h +++ b/modules/addressbook/e-book-shell-content.h @@ -64,7 +64,8 @@ enum { E_BOOK_SHELL_CONTENT_SELECTION_HAS_MAILTO_URI = 1 << 5, E_BOOK_SHELL_CONTENT_SOURCE_IS_BUSY = 1 << 6, E_BOOK_SHELL_CONTENT_SOURCE_IS_EDITABLE = 1 << 7, - E_BOOK_SHELL_CONTENT_SOURCE_IS_EMPTY = 1 << 8 + E_BOOK_SHELL_CONTENT_SOURCE_IS_EMPTY = 1 << 8, + E_BOOK_SHELL_CONTENT_CLIPBOARD_HAS_DIRECTORY = 1 << 9 }; struct _EBookShellContent { diff --git a/modules/addressbook/e-book-shell-view.c b/modules/addressbook/e-book-shell-view.c index 8ea97caddc..88a503b024 100644 --- a/modules/addressbook/e-book-shell-view.c +++ b/modules/addressbook/e-book-shell-view.c @@ -246,6 +246,7 @@ book_shell_view_update_actions (EShellView *shell_view) gboolean source_is_busy; gboolean source_is_editable; gboolean source_is_empty; + gboolean clipboard_has_directory; priv = E_BOOK_SHELL_VIEW_GET_PRIVATE (shell_view); @@ -268,6 +269,8 @@ book_shell_view_update_actions (EShellView *shell_view) (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); @@ -301,7 +304,7 @@ book_shell_view_update_actions (EShellView *shell_view) gtk_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_CLIPBOARD_PASTE); - sensitive = source_is_editable; + sensitive = source_is_editable && clipboard_has_directory; gtk_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_COPY); diff --git a/modules/calendar/e-cal-shell-view-private.h b/modules/calendar/e-cal-shell-view-private.h index 7f6413c747..1f447bc162 100644 --- a/modules/calendar/e-cal-shell-view-private.h +++ b/modules/calendar/e-cal-shell-view-private.h @@ -32,6 +32,7 @@ #include #include "e-util/e-binding.h" +#include "e-util/e-selection.h" #include "e-util/e-dialog-utils.h" #include "e-util/e-file-utils.h" #include "e-util/e-error.h" @@ -44,7 +45,6 @@ #include "calendar/gui/comp-util.h" #include "calendar/gui/e-cal-list-view.h" #include "calendar/gui/e-cal-model-tasks.h" -#include "calendar/gui/e-cal-selection.h" #include "calendar/gui/e-calendar-view.h" #include "calendar/gui/e-day-view.h" #include "calendar/gui/e-week-view.h" -- cgit v1.2.3