diff options
-rw-r--r-- | addressbook/ChangeLog | 52 | ||||
-rw-r--r-- | addressbook/gui/component/addressbook.c | 50 | ||||
-rw-r--r-- | addressbook/gui/widgets/e-addressbook-view.c | 236 | ||||
-rw-r--r-- | addressbook/gui/widgets/e-addressbook-view.h | 11 | ||||
-rw-r--r-- | addressbook/gui/widgets/e-minicard-view-widget.c | 7 | ||||
-rw-r--r-- | addressbook/gui/widgets/e-minicard-view-widget.h | 2 |
6 files changed, 344 insertions, 14 deletions
diff --git a/addressbook/ChangeLog b/addressbook/ChangeLog index d42d9547c6..1541c6de75 100644 --- a/addressbook/ChangeLog +++ b/addressbook/ChangeLog @@ -1,3 +1,55 @@ +2001-05-30 Chris Toshok <toshok@ximian.com> + + * gui/component/addressbook.c (cut_contacts_cb): new function, for + the Cut verb. + (copy_contacts_cb): new function, for the Copy verb. + (paste_contacts_cb): new function, for the Paste verb. + (select_all_contacts_cb): new function, for the Select All verb. + (update_command_state): add handling for sensitivity of + Cut/Copy/Paste/Select All. + + * gui/widgets/e-addressbook-view.c (e_addressbook_view_init): init + the invisible and set up selection/destroy signals. + (get_selection_model): new function, so we can get the + ETableSelectionModel from either view type. makes lots of the + other functions easier, since we can get the list of selected + cards using the same code regardless of view type. + (invisible_destroyed): new function. + (selection_get): new function. convert the clipboard list to + string. + (selection_clear_event): new function - free up the list of + ECards. + (selection_received): if the selection data is valid and + well-formed, add the corresponding cards to the ebook. + (add_to_list): new function. + (get_selected_cards): new function. + (e_addressbook_view_cut): new function, implement in terms of + _copy and _delete_selection. + (e_addressbook_view_copy): claim ownership of the CLIPBOARD + selection after saving the list of selected ECards. + (e_addressbook_view_paste): call gtk_selection_convert. + (e_addressbook_view_select_all): new function, using + e_selection_model_select_all. + (e_addressbook_view_can_print): re-implement in terms of + get_selection_model. + (e_addressbook_view_can_delete): same. + (e_addressbook_view_can_cut): new function. + (e_addressbook_view_can_copy): new function. + (e_addressbook_view_can_paste): new function. hmm, always return + TRUE here. + (e_addressbook_view_can_select_all): new function. + + * gui/widgets/e-addressbook-view.h (struct _EAddressbookView): add + selection stuff - the list of selected cards, and the GtkInvisible + selection owner, and add prototypes for + e_addressbook_view_[can]_{cut,copy,paste,select_all}. + + * gui/widgets/e-minicard-view-widget.h: add a prototype for + e_minicard_view_widget_get_selection_model. + + * gui/widgets/e-minicard-view-widget.c + (e_minicard_view_widget_get_selection_model): new function. + 2001-05-27 Dan Winship <danw@ximian.com> * gui/component/addressbook.c: #include diff --git a/addressbook/gui/component/addressbook.c b/addressbook/gui/component/addressbook.c index 5db16cf42b..d489b89f60 100644 --- a/addressbook/gui/component/addressbook.c +++ b/addressbook/gui/component/addressbook.c @@ -188,6 +188,34 @@ stop_loading_cb (BonoboUIComponent *uih, void *user_data, const char *path) } static void +cut_contacts_cb (BonoboUIComponent *uih, void *user_data, const char *path) +{ + AddressbookView *view = (AddressbookView *) user_data; + e_addressbook_view_cut(view->view); +} + +static void +copy_contacts_cb (BonoboUIComponent *uih, void *user_data, const char *path) +{ + AddressbookView *view = (AddressbookView *) user_data; + e_addressbook_view_copy(view->view); +} + +static void +paste_contacts_cb (BonoboUIComponent *uih, void *user_data, const char *path) +{ + AddressbookView *view = (AddressbookView *) user_data; + e_addressbook_view_paste(view->view); +} + +static void +select_all_contacts_cb (BonoboUIComponent *uih, void *user_data, const char *path) +{ + AddressbookView *view = (AddressbookView *) user_data; + e_addressbook_view_select_all (view->view); +} + +static void update_command_state (EAddressbookView *eav, AddressbookView *view) { BonoboUIComponent *uic = bonobo_control_get_ui_component (view->control); @@ -210,7 +238,24 @@ update_command_state (EAddressbookView *eav, AddressbookView *view) "sensitive", e_addressbook_view_can_delete (view->view) ? "1" : "0", NULL); + bonobo_ui_component_set_prop (uic, + "/commands/ContactsCut", + "sensitive", + e_addressbook_view_can_cut (view->view) ? "1" : "0", NULL); + bonobo_ui_component_set_prop (uic, + "/commands/ContactsCopy", + "sensitive", + e_addressbook_view_can_copy (view->view) ? "1" : "0", NULL); + bonobo_ui_component_set_prop (uic, + "/commands/ContactsPaste", + "sensitive", + e_addressbook_view_can_paste (view->view) ? "1" : "0", NULL); + bonobo_ui_component_set_prop (uic, + "/commands/ContactsSelectAll", + "sensitive", + e_addressbook_view_can_select_all (view->view) ? "1" : "0", NULL); + /* View All Contacts */ #if 0 /* this is always enabled */ @@ -242,6 +287,11 @@ BonoboUIVerb verbs [] = { BONOBO_UI_UNSAFE_VERB ("ContactDelete", delete_contact_cb), BONOBO_UI_UNSAFE_VERB ("ContactViewAll", show_all_contacts_cb), BONOBO_UI_UNSAFE_VERB ("ContactStop", stop_loading_cb), + + BONOBO_UI_UNSAFE_VERB ("ContactsCut", cut_contacts_cb), + BONOBO_UI_UNSAFE_VERB ("ContactsCopy", copy_contacts_cb), + BONOBO_UI_UNSAFE_VERB ("ContactsPaste", paste_contacts_cb), + BONOBO_UI_UNSAFE_VERB ("ContactsSelectAll", select_all_contacts_cb), BONOBO_UI_VERB_END }; diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c index 55443000a0..3491b8e662 100644 --- a/addressbook/gui/widgets/e-addressbook-view.c +++ b/addressbook/gui/widgets/e-addressbook-view.c @@ -22,6 +22,8 @@ #include <config.h> +#include <gtk/gtkinvisible.h> + #include <libgnome/gnome-paper.h> #include <libgnome/gnome-i18n.h> #include <libgnome/gnome-util.h> @@ -66,6 +68,14 @@ static void stop_state_changed (GtkObject *object, EAddressbookView *eav); static void writable_status (GtkObject *object, gboolean writable, EAddressbookView *eav); static void command_state_change (EAddressbookView *eav); +static void selection_clear_event (GtkWidget *invisible, GdkEventSelection *event, + EAddressbookView *view); +static void selection_received (GtkWidget *invisible, GtkSelectionData *selection_data, + guint time, EAddressbookView *view); +static void selection_get (GtkWidget *invisible, GtkSelectionData *selection_data, + guint info, guint time_stamp, EAddressbookView *view); +static void invisible_destroyed (GtkWidget *invisible, EAddressbookView *view); + static GtkTableClass *parent_class = NULL; /* The arguments we take */ @@ -93,6 +103,8 @@ static const int num_drag_types = sizeof (drag_types) / sizeof (drag_types[0]); static guint e_addressbook_view_signals [LAST_SIGNAL] = {0, }; +static GdkAtom clipboard_atom = GDK_NONE; + GtkType e_addressbook_view_get_type (void) { @@ -154,6 +166,9 @@ e_addressbook_view_class_init (EAddressbookViewClass *klass) GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, e_addressbook_view_signals, LAST_SIGNAL); + + if (!clipboard_atom) + clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); } static void @@ -184,6 +199,26 @@ e_addressbook_view_init (EAddressbookView *eav) eav->object = NULL; eav->widget = NULL; + + eav->invisible = gtk_invisible_new (); + + gtk_selection_add_target (eav->invisible, + clipboard_atom, + GDK_SELECTION_TYPE_STRING, + 0); + + gtk_signal_connect (GTK_OBJECT(eav->invisible), "selection_get", + GTK_SIGNAL_FUNC (selection_get), + eav); + gtk_signal_connect (GTK_OBJECT(eav->invisible), "selection_clear_event", + GTK_SIGNAL_FUNC (selection_clear_event), + eav); + gtk_signal_connect (GTK_OBJECT(eav->invisible), "selection_received", + GTK_SIGNAL_FUNC (selection_received), + eav); + gtk_signal_connect (GTK_OBJECT(eav->invisible), "destroyed", + GTK_SIGNAL_FUNC (invisible_destroyed), + eav); } static void @@ -195,6 +230,15 @@ e_addressbook_view_destroy (GtkObject *object) gtk_object_unref(GTK_OBJECT(eav->book)); g_free(eav->query); + if (eav->clipboard_cards) { + g_list_foreach (eav->clipboard_cards, (GFunc)gtk_object_unref, NULL); + g_list_free (eav->clipboard_cards); + eav->clipboard_cards = NULL; + } + + if (eav->invisible) + gtk_widget_destroy (eav->invisible); + if (GTK_OBJECT_CLASS(parent_class)->destroy) GTK_OBJECT_CLASS(parent_class)->destroy(object); } @@ -1004,6 +1048,16 @@ e_addressbook_view_setup_menus (EAddressbookView *view, gtk_object_sink(GTK_OBJECT(collection)); } +static ESelectionModel* +get_selection_model (EAddressbookView *view) +{ + if (view->view_type == E_ADDRESSBOOK_VIEW_MINICARD) + return e_minicard_view_widget_get_selection_model (E_MINICARD_VIEW_WIDGET(view->object)); + else + return E_SELECTION_MODEL(E_TABLE_SCROLLED(view->widget)->table->selection); +} + + void e_addressbook_view_print(EAddressbookView *view) { @@ -1053,10 +1107,133 @@ card_deleted_cb (EBook* book, EBookStatus status, gpointer user_data) void e_addressbook_view_delete_selection(EAddressbookView *view) { + ESelectionModel *model = get_selection_model (view); + + g_return_if_fail (model); + if (view->view_type == E_ADDRESSBOOK_VIEW_MINICARD) e_minicard_view_widget_remove_selection (E_MINICARD_VIEW_WIDGET(view->object), card_deleted_cb, NULL); } +static void +invisible_destroyed (GtkWidget *invisible, EAddressbookView *view) +{ + view->invisible = NULL; +} + +static void +selection_get (GtkWidget *invisible, + GtkSelectionData *selection_data, + guint info, + guint time_stamp, + EAddressbookView *view) +{ + char *value; + + value = e_card_list_get_vcard(view->clipboard_cards); + + gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING, + 8, value, strlen (value)); + +} + +static void +selection_clear_event (GtkWidget *invisible, + GdkEventSelection *event, + EAddressbookView *view) +{ + if (view->clipboard_cards) { + g_list_foreach (view->clipboard_cards, (GFunc)gtk_object_unref, NULL); + g_list_free (view->clipboard_cards); + view->clipboard_cards = NULL; + } +} + +static void +selection_received (GtkWidget *invisible, + GtkSelectionData *selection_data, + guint time, + EAddressbookView *view) +{ + if (selection_data->length < 0 || selection_data->type != GDK_SELECTION_TYPE_STRING) { + return; + } + else { + /* XXX make sure selection_data->data = \0 terminated */ + GList *card_list = e_card_load_cards_from_string (selection_data->data); + GList *l; + + if (!card_list /* it wasn't a vcard list */) + return; + + for (l = card_list; l; l = l->next) { + ECard *card = l->data; + + e_book_add_card (view->book, card, NULL /* XXX */, NULL); + } + + g_list_foreach (card_list, (GFunc)gtk_object_unref, NULL); + g_list_free (card_list); + } +} + +static void +add_to_list (int model_row, gpointer closure) +{ + GList **list = closure; + *list = g_list_prepend (*list, GINT_TO_POINTER (model_row)); +} + +static GList * +get_selected_cards (EAddressbookView *view) +{ + GList *list; + GList *iterator; + ESelectionModel *selection = get_selection_model (view); + + list = NULL; + e_selection_model_foreach (selection, add_to_list, &list); + + for (iterator = list; iterator; iterator = iterator->next) { + iterator->data = e_addressbook_model_card_at (view->model, GPOINTER_TO_INT (iterator->data)); + } + list = g_list_reverse (list); + return list; +} + +void +e_addressbook_view_cut (EAddressbookView *view) +{ + e_addressbook_view_copy (view); + e_addressbook_view_delete_selection (view); +} + +void +e_addressbook_view_copy (EAddressbookView *view) +{ + view->clipboard_cards = get_selected_cards (view); + + gtk_selection_owner_set (view->invisible, clipboard_atom, GDK_CURRENT_TIME); +} + +void +e_addressbook_view_paste (EAddressbookView *view) +{ + gtk_selection_convert (view->invisible, clipboard_atom, + GDK_SELECTION_TYPE_STRING, + GDK_CURRENT_TIME); +} + +void +e_addressbook_view_select_all (EAddressbookView *view) +{ + ESelectionModel *model = get_selection_model (view); + + g_return_if_fail (model); + + e_selection_model_select_all (model); +} + void e_addressbook_view_show_all(EAddressbookView *view) { @@ -1080,30 +1257,61 @@ e_addressbook_view_can_create (EAddressbookView *view) gboolean e_addressbook_view_can_print (EAddressbookView *view) { - switch (view->view_type) { - case E_ADDRESSBOOK_VIEW_TABLE: - return e_table_selected_count (E_TABLE_SCROLLED(view->widget)->table) != 0; - case E_ADDRESSBOOK_VIEW_MINICARD: - return e_minicard_view_widget_selected_count (E_MINICARD_VIEW_WIDGET (view->object)) != 0; - default: + ESelectionModel *selection_model; + + if (!e_addressbook_model_editable (view->model)) return FALSE; - } + + selection_model = get_selection_model (view); + g_return_val_if_fail (selection_model != NULL, FALSE); + + return e_selection_model_selected_count (selection_model) != 0; } gboolean e_addressbook_view_can_delete (EAddressbookView *view) { + ESelectionModel *selection_model; + if (!e_addressbook_model_editable (view->model)) return FALSE; - switch (view->view_type) { - case E_ADDRESSBOOK_VIEW_TABLE: - return e_table_selected_count (E_TABLE_SCROLLED(view->widget)->table) != 0; - case E_ADDRESSBOOK_VIEW_MINICARD: - return e_minicard_view_widget_selected_count (E_MINICARD_VIEW_WIDGET (view->object)) != 0; - default: + selection_model = get_selection_model (view); + g_return_val_if_fail (selection_model != NULL, FALSE); + + return e_selection_model_selected_count (selection_model) != 0; +} + +gboolean +e_addressbook_view_can_cut (EAddressbookView *view) +{ + return (e_addressbook_view_can_copy (view) && e_addressbook_model_editable (view->model)); +} + +gboolean +e_addressbook_view_can_copy (EAddressbookView *view) +{ + ESelectionModel *selection_model; + + if (!e_addressbook_model_editable (view->model)) return FALSE; - } + + selection_model = get_selection_model (view); + g_return_val_if_fail (selection_model != NULL, FALSE); + + return e_selection_model_selected_count (selection_model) != 0; +} + +gboolean +e_addressbook_view_can_paste (EAddressbookView *view) +{ + return TRUE; +} + +gboolean +e_addressbook_view_can_select_all (EAddressbookView *view) +{ + return e_addressbook_model_card_count (view->model) != 0; } gboolean diff --git a/addressbook/gui/widgets/e-addressbook-view.h b/addressbook/gui/widgets/e-addressbook-view.h index 19c83474fe..049376c96f 100644 --- a/addressbook/gui/widgets/e-addressbook-view.h +++ b/addressbook/gui/widgets/e-addressbook-view.h @@ -64,6 +64,9 @@ struct _EAddressbookView EAddressbookModel *model; + GtkWidget *invisible; + GList *clipboard_cards; + EBook *book; char *query; guint editable : 1; @@ -93,12 +96,20 @@ void e_addressbook_view_setup_menus (EAddressbookView *view, void e_addressbook_view_print (EAddressbookView *view); void e_addressbook_view_delete_selection (EAddressbookView *view); +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); gboolean e_addressbook_view_can_create (EAddressbookView *view); gboolean e_addressbook_view_can_print (EAddressbookView *view); gboolean e_addressbook_view_can_delete (EAddressbookView *view); +gboolean e_addressbook_view_can_cut (EAddressbookView *view); +gboolean e_addressbook_view_can_copy (EAddressbookView *view); +gboolean e_addressbook_view_can_paste (EAddressbookView *view); +gboolean e_addressbook_view_can_select_all (EAddressbookView *view); gboolean e_addressbook_view_can_stop (EAddressbookView *view); #ifdef __cplusplus diff --git a/addressbook/gui/widgets/e-minicard-view-widget.c b/addressbook/gui/widgets/e-minicard-view-widget.c index 576f8b3aab..8e9f3c2761 100644 --- a/addressbook/gui/widgets/e-minicard-view-widget.c +++ b/addressbook/gui/widgets/e-minicard-view-widget.c @@ -329,3 +329,10 @@ void e_minicard_view_widget_jump_to_letter (EMinicardViewWidget *view, if (view->emv) e_minicard_view_jump_to_letter(E_MINICARD_VIEW(view->emv), letter); } + +ESelectionModel * +e_minicard_view_widget_get_selection_model (EMinicardViewWidget *view) +{ + if (view->emv) + return E_SELECTION_MODEL (E_REFLOW (view->emv)->selection); +} diff --git a/addressbook/gui/widgets/e-minicard-view-widget.h b/addressbook/gui/widgets/e-minicard-view-widget.h index 22156e2588..edfe5135a4 100644 --- a/addressbook/gui/widgets/e-minicard-view-widget.h +++ b/addressbook/gui/widgets/e-minicard-view-widget.h @@ -69,6 +69,8 @@ void e_minicard_view_widget_jump_to_letter (EMinicardViewWidget *view, char letter); GtkWidget *e_minicard_view_widget_new (EAddressbookReflowAdapter *adapter); +ESelectionModel *e_minicard_view_widget_get_selection_model (EMinicardViewWidget *view); + #ifdef __cplusplus } #endif /* __cplusplus */ |