/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * e-table-field-chooser.c * Copyright (C) 2000 Ximian, Inc. * Author: Chris Lahey * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * 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 * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "addressbook/printing/e-contact-print.h" #include "addressbook/printing/e-contact-print-envelope.h" #include "gal-view-factory-minicard.h" #include "gal-view-minicard.h" #include "e-addressbook-view.h" #include "e-addressbook-model.h" #include "e-addressbook-util.h" #include "e-addressbook-table-adapter.h" #include "e-addressbook-reflow-adapter.h" #include "e-minicard-view-widget.h" #include "e-contact-save-as.h" #include "e-card-merging.h" #include "e-contact-editor.h" static void e_addressbook_view_init (EAddressbookView *card); static void e_addressbook_view_class_init (EAddressbookViewClass *klass); static void e_addressbook_view_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); static void e_addressbook_view_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); static void e_addressbook_view_destroy (GtkObject *object); static void change_view_type (EAddressbookView *view, EAddressbookViewType view_type); static void status_message (GtkObject *object, const gchar *status, EAddressbookView *eav); 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 */ enum { ARG_0, ARG_BOOK, ARG_QUERY, ARG_TYPE, }; enum { STATUS_MESSAGE, COMMAND_STATE_CHANGE, LAST_SIGNAL }; enum DndTargetType { DND_TARGET_TYPE_VCARD, }; #define VCARD_TYPE "text/x-vcard" static GtkTargetEntry drag_types[] = { { VCARD_TYPE, 0, DND_TARGET_TYPE_VCARD }, }; 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) { static GtkType type = 0; if (!type) { static const GtkTypeInfo info = { "EAddressbookView", sizeof (EAddressbookView), sizeof (EAddressbookViewClass), (GtkClassInitFunc) e_addressbook_view_class_init, (GtkObjectInitFunc) e_addressbook_view_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; type = gtk_type_unique (gtk_table_get_type (), &info); } return type; } static void e_addressbook_view_class_init (EAddressbookViewClass *klass) { GtkObjectClass *object_class; object_class = GTK_OBJECT_CLASS(klass); parent_class = gtk_type_class (gtk_table_get_type ()); object_class->set_arg = e_addressbook_view_set_arg; object_class->get_arg = e_addressbook_view_get_arg; object_class->destroy = e_addressbook_view_destroy; gtk_object_add_arg_type ("EAddressbookView::book", GTK_TYPE_OBJECT, GTK_ARG_READWRITE, ARG_BOOK); gtk_object_add_arg_type ("EAddressbookView::query", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_QUERY); gtk_object_add_arg_type ("EAddressbookView::type", GTK_TYPE_ENUM, GTK_ARG_READWRITE, ARG_TYPE); e_addressbook_view_signals [STATUS_MESSAGE] = gtk_signal_new ("status_message", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EAddressbookViewClass, status_message), gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); e_addressbook_view_signals [COMMAND_STATE_CHANGE] = gtk_signal_new ("command_state_change", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EAddressbookViewClass, command_state_change), gtk_marshal_NONE__NONE, 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 e_addressbook_view_init (EAddressbookView *eav) { eav->view_type = E_ADDRESSBOOK_VIEW_NONE; eav->model = e_addressbook_model_new (); gtk_signal_connect (GTK_OBJECT(eav->model), "status_message", GTK_SIGNAL_FUNC (status_message), eav); gtk_signal_connect (GTK_OBJECT(eav->model), "stop_state_changed", GTK_SIGNAL_FUNC (stop_state_changed), eav); gtk_signal_connect (GTK_OBJECT(eav->model), "writable_status", GTK_SIGNAL_FUNC (writable_status), eav); eav->editable = FALSE; eav->book = NULL; eav->query = g_strdup("(contains \"x-evolution-any-field\" \"\")"); eav->object = NULL; eav->widget = NULL; eav->view_collection = NULL; eav->view_menus = 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), "destroy", GTK_SIGNAL_FUNC (invisible_destroyed), eav); } static void e_addressbook_view_destroy (GtkObject *object) { EAddressbookView *eav = E_ADDRESSBOOK_VIEW(object); if (eav->model) gtk_object_unref(GTK_OBJECT(eav->model)); if (eav->book) gtk_object_unref(GTK_OBJECT(eav->book)); g_free(eav->query); if (eav->view_collection) { gtk_object_unref (GTK_OBJECT (eav->view_collection)); eav->view_collection = NULL; } if (eav->view_menus) { gtk_object_unref (GTK_OBJECT (eav->view_menus)); eav->view_menus = NULL; } 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); } GtkWidget* e_addressbook_view_new (void) { GtkWidget *widget = GTK_WIDGET (gtk_type_new (e_addressbook_view_get_type ())); return widget; } static void book_writable_cb (EBook *book, gboolean writable, EAddressbookView *eav) { eav->editable = writable; gtk_object_set (GTK_OBJECT (eav->model), "editable", eav->editable, NULL); } static void e_addressbook_view_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) { EAddressbookView *eav = E_ADDRESSBOOK_VIEW(object); switch (arg_id){ case ARG_BOOK: if (eav->book) { gtk_object_unref(GTK_OBJECT(eav->book)); } if (GTK_VALUE_OBJECT(*arg)) { eav->book = E_BOOK(GTK_VALUE_OBJECT(*arg)); gtk_object_ref(GTK_OBJECT(eav->book)); gtk_signal_connect (GTK_OBJECT (eav->book), "writable_status", book_writable_cb, eav); } else eav->book = NULL; gtk_object_set(GTK_OBJECT(eav->model), "book", eav->book, "editable", eav->editable, NULL); break; case ARG_QUERY: g_free(eav->query); eav->query = g_strdup(GTK_VALUE_STRING(*arg)); if (!eav->query) eav->query = g_strdup("(contains \"x-evolution-any-field\" \"\")"); gtk_object_set(GTK_OBJECT(eav->model), "query", eav->query, NULL); break; case ARG_TYPE: change_view_type(eav, GTK_VALUE_ENUM(*arg)); break; default: break; } } static void e_addressbook_view_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) { EAddressbookView *eav = E_ADDRESSBOOK_VIEW(object); switch (arg_id) { case ARG_BOOK: if (eav->book) GTK_VALUE_OBJECT (*arg) = GTK_OBJECT(eav->book); else GTK_VALUE_OBJECT (*arg) = NULL; break; case ARG_QUERY: GTK_VALUE_STRING (*arg) = eav->query; break; case ARG_TYPE: GTK_VALUE_ENUM (*arg) = eav->view_type; break; default: arg->type = GTK_TYPE_INVALID; break; } } typedef struct { EAddressbookView *view; char letter; } LetterClosure; static void jump_to_letter(GtkWidget *button, LetterClosure *closure) { if (closure->view->widget && E_IS_MINICARD_VIEW_WIDGET(closure->view->widget)) e_minicard_view_widget_jump_to_letter(E_MINICARD_VIEW_WIDGET(closure->view->widget), closure->letter); } static void free_closure(GtkWidget *button, LetterClosure *closure) { g_free(closure); } static void connect_button (EAddressbookView *view, GladeXML *gui, char letter) { char *name; GtkWidget *button; LetterClosure *closure; name = g_strdup_printf("button-%c", letter); button = glade_xml_get_widget(gui, name); g_free(name); if (!button) return; closure = g_new(LetterClosure, 1); closure->view = view; closure->letter = letter; gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(jump_to_letter), closure); gtk_signal_connect(GTK_OBJECT(button), "destroy", GTK_SIGNAL_FUNC(free_closure), closure); } static GtkWidget * create_alphabet (EAddressbookView *view) { GtkWidget *widget; char letter; GladeXML *gui = glade_xml_new (EVOLUTION_GLADEDIR "/alphabet.glade", NULL); widget = glade_xml_get_widget(gui, "scrolledwindow-top"); if (!widget) { return NULL; } connect_button(view, gui, '1'); for (letter = 'a'; letter <= 'z'; letter ++) { connect_button(view, gui, letter); } gtk_object_unref(GTK_OBJECT(gui)); return widget; } static void minicard_selection_change (EMinicardViewWidget *widget, EAddressbookView *view) { command_state_change (view); } static void create_minicard_view (EAddressbookView *view) { GtkWidget *scrollframe; GtkWidget *alphabet; GtkWidget *minicard_view; GtkWidget *minicard_hbox; EAddressbookReflowAdapter *adapter; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); minicard_hbox = gtk_hbox_new(FALSE, 0); adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(e_addressbook_reflow_adapter_new (view->model)); minicard_view = e_minicard_view_widget_new(adapter); gtk_signal_connect(GTK_OBJECT(minicard_view), "selection_change", GTK_SIGNAL_FUNC(minicard_selection_change), view); view->object = GTK_OBJECT(minicard_view); view->widget = minicard_hbox; scrollframe = e_scroll_frame_new (NULL, NULL); e_scroll_frame_set_policy (E_SCROLL_FRAME (scrollframe), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add (GTK_CONTAINER (scrollframe), minicard_view); gtk_box_pack_start(GTK_BOX(minicard_hbox), scrollframe, TRUE, TRUE, 0); alphabet = create_alphabet(view); if (alphabet) { gtk_object_ref(GTK_OBJECT(alphabet)); gtk_widget_unparent(alphabet); gtk_box_pack_start(GTK_BOX(minicard_hbox), alphabet, FALSE, FALSE, 0); gtk_object_unref(GTK_OBJECT(alphabet)); } gtk_table_attach(GTK_TABLE(view), minicard_hbox, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); gtk_widget_show_all( GTK_WIDGET(minicard_hbox) ); gtk_widget_pop_visual (); gtk_widget_pop_colormap (); e_reflow_model_changed (E_REFLOW_MODEL (adapter)); gtk_object_unref (GTK_OBJECT (adapter)); } static void table_double_click(ETableScrolled *table, gint row, gint col, GdkEvent *event, EAddressbookView *view) { if (E_IS_ADDRESSBOOK_TABLE_ADAPTER(view->object)) { EAddressbookModel *model = view->model; ECard *card = e_addressbook_model_get_card(model, row); EBook *book; gtk_object_get(GTK_OBJECT(model), "book", &book, NULL); g_assert (E_IS_BOOK (book)); if (e_card_evolution_list (card)) e_addressbook_show_contact_list_editor (book, card, FALSE, view->editable); else e_addressbook_show_contact_editor (book, card, FALSE, view->editable); } } typedef struct { EBook *book; ECard *card; EAddressbookView *view; GtkWidget *widget; gpointer closure; } CardAndBook; static void card_and_book_free (CardAndBook *card_and_book) { gtk_object_unref(GTK_OBJECT(card_and_book->card)); gtk_object_unref(GTK_OBJECT(card_and_book->book)); gtk_object_unref(GTK_OBJECT(card_and_book->view)); } static void get_card_list_1(gint model_row, gpointer closure) { CardAndBook *card_and_book; GList **list; EAddressbookView *view; ECard *card; card_and_book = closure; list = card_and_book->closure; view = card_and_book->view; card = e_addressbook_model_get_card(view->model, model_row); *list = g_list_prepend(*list, card); } static GList * get_card_list (CardAndBook *card_and_book) { GList *list = NULL; ETable *table; table = E_TABLE(card_and_book->widget); card_and_book->closure = &list; e_table_selected_row_foreach(table, get_card_list_1, card_and_book); return list; } static void save_as (GtkWidget *widget, CardAndBook *card_and_book) { e_contact_save_as(_("Save as VCard"), card_and_book->card); card_and_book_free(card_and_book); } static void send_as (GtkWidget *widget, CardAndBook *card_and_book) { e_card_send(card_and_book->card, E_CARD_DISPOSITION_AS_ATTACHMENT); card_and_book_free(card_and_book); } static void send_to (GtkWidget *widget, CardAndBook *card_and_book) { e_card_send(card_and_book->card, E_CARD_DISPOSITION_AS_TO); card_and_book_free(card_and_book); } static void print (GtkWidget *widget, CardAndBook *card_and_book) { gtk_widget_show(e_contact_print_card_dialog_new(card_and_book->card)); card_and_book_free(card_and_book); } static void print_envelope (GtkWidget *widget, CardAndBook *card_and_book) { gtk_widget_show(e_contact_print_envelope_dialog_new(card_and_book->card)); card_and_book_free(card_and_book); } static void delete (GtkWidget *widget, CardAndBook *card_and_book) { if (e_contact_editor_confirm_delete(GTK_WINDOW(gtk_widget_get_toplevel(card_and_book->widget)))) { GList *list = get_card_list(card_and_book); GList *iterator; for (iterator = list; iterator; iterator = iterator->next) { ECard *card = iterator->data; /* Add the card in the contact editor to our ebook */ e_book_remove_card (card_and_book->book, card, NULL, NULL); } e_free_object_list(list); } card_and_book_free(card_and_book); } static gint table_right_click(ETableScrolled *table, gint row, gint col, GdkEvent *event, EAddressbookView *view) { if (E_IS_ADDRESSBOOK_TABLE_ADAPTER(view->object)) { EAddressbookModel *model = view->model; CardAndBook *card_and_book; EPopupMenu menu[] = { {N_("Save as VCard"), NULL, GTK_SIGNAL_FUNC(save_as), NULL, 0}, {N_("Send contact to other"), NULL, GTK_SIGNAL_FUNC(send_as), NULL, 0}, {N_("Send message to contact"), NULL, GTK_SIGNAL_FUNC(send_to), NULL, 0}, {N_("Print"), NULL, GTK_SIGNAL_FUNC(print), NULL, 0}, {N_("Print Envelope"), NULL, GTK_SIGNAL_FUNC(print_envelope), NULL, 0}, {N_("Delete"), NULL, GTK_SIGNAL_FUNC(delete), NULL, 0}, {NULL, NULL, NULL, NULL, 0} }; card_and_book = g_new(CardAndBook, 1); card_and_book->card = e_addressbook_model_get_card(model, row); card_and_book->widget = GTK_WIDGET(table); card_and_book->view = view; gtk_object_get(GTK_OBJECT(model), "book", &(card_and_book->book), NULL); gtk_object_ref(GTK_OBJECT(card_and_book->book)); gtk_object_ref(GTK_OBJECT(card_and_book->view)); e_popup_menu_run (menu, event, 0, 0, card_and_book); return TRUE; } else return FALSE; } static void table_selection_change(ETableScrolled *table, EAddressbookView *view) { command_state_change (view); } static void table_drag_data_get (ETable *table, int row, int col, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint time, gpointer user_data) { EAddressbookView *view = user_data; printf ("table_drag_data_get (row %d, col %d)\n", row, col); if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER(view->object)) return; switch (info) { case DND_TARGET_TYPE_VCARD: { char *value; row = e_table_view_to_model_row (table, row); value = e_card_get_vcard(view->model->data[row]); gtk_selection_data_set (selection_data, selection_data->target, 8, value, strlen (value)); break; } } } static void emit_status_message (EAddressbookView *eav, const gchar *status) { gtk_signal_emit (GTK_OBJECT (eav), e_addressbook_view_signals [STATUS_MESSAGE], status); } static void status_message (GtkObject *object, const gchar *status, EAddressbookView *eav) { emit_status_message (eav, status); } static void stop_state_changed (GtkObject *object, EAddressbookView *eav) { command_state_change (eav); } static void writable_status (GtkObject *object, gboolean writable, EAddressbookView *eav) { command_state_change (eav); } static void command_state_change (EAddressbookView *eav) { gtk_signal_emit (GTK_OBJECT (eav), e_addressbook_view_signals [COMMAND_STATE_CHANGE]); } #ifdef JUST_FOR_TRANSLATORS static char *list [] = { N_("* Click here to add a contact *"), N_("File As"), N_("Full Name"), N_("Email"), N_("Primary Phone"), N_("Assistant Phone"), N_("Business Phone"), N_("Callback Phone"), N_("Company Phone"), N_("Home Phone"), N_("Organization"), N_("Business Address"), N_("Home Address"), N_("Mobile Phone"), N_("Car Phone"), N_("Business Fax"), N_("Home Fax"), N_("Business Phone 2"), N_("Home Phone 2"), N_("ISDN"), N_("Other Phone"), N_("Other Fax"), N_("Pager"), N_("Radio"), N_("Telex"), N_("TTY"), N_("Other Address"), N_("Email 2"), N_("Email 3"), N_("Web Site"), N_("Department"), N_("Office"), N_("Title"), N_("Profession"), N_("Manager"), N_("Assistant"), N_("Nickname"), N_("Spouse"), N_("Note"), N_("Free-busy URL"), }; #endif #define SPEC " \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ " static void create_table_view (EAddressbookView *view) { ETableModel *adapter; ECardSimple *simple; GtkWidget *table; simple = e_card_simple_new(NULL); adapter = e_addressbook_table_adapter_new(view->model); /* Here we create the table. We give it the three pieces of the table we've created, the header, the model, and the initial layout. It does the rest. */ table = e_table_scrolled_new (adapter, NULL, SPEC, NULL); view->object = GTK_OBJECT(adapter); view->widget = table; gtk_signal_connect(GTK_OBJECT(e_table_scrolled_get_table(E_TABLE_SCROLLED(table))), "double_click", GTK_SIGNAL_FUNC(table_double_click), view); gtk_signal_connect(GTK_OBJECT(e_table_scrolled_get_table(E_TABLE_SCROLLED(table))), "right_click", GTK_SIGNAL_FUNC(table_right_click), view); gtk_signal_connect(GTK_OBJECT(e_table_scrolled_get_table(E_TABLE_SCROLLED(table))), "selection_change", GTK_SIGNAL_FUNC(table_selection_change), view); /* drag & drop signals */ e_table_drag_source_set (E_TABLE(E_TABLE_SCROLLED(table)->table), GDK_BUTTON1_MASK, drag_types, num_drag_types, GDK_ACTION_MOVE); gtk_signal_connect (GTK_OBJECT (E_TABLE_SCROLLED(table)->table), "table_drag_data_get", GTK_SIGNAL_FUNC (table_drag_data_get), view); gtk_table_attach(GTK_TABLE(view), table, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); gtk_widget_show( GTK_WIDGET(table) ); gtk_object_unref(GTK_OBJECT(simple)); } static void change_view_type (EAddressbookView *view, EAddressbookViewType view_type) { if (view_type == view->view_type) return; if (view->widget) { gtk_widget_destroy (view->widget); view->widget = NULL; } view->object = NULL; switch (view_type) { case E_ADDRESSBOOK_VIEW_MINICARD: create_minicard_view (view); break; case E_ADDRESSBOOK_VIEW_TABLE: create_table_view (view); break; default: g_warning ("view_type must be either TABLE or MINICARD\n"); return; } view->view_type = view_type; command_state_change (view); } static void e_contact_print_destroy(GnomeDialog *dialog, gpointer data) { ETableScrolled *table = gtk_object_get_data(GTK_OBJECT(dialog), "table"); EPrintable *printable = gtk_object_get_data(GTK_OBJECT(dialog), "printable"); gtk_object_unref(GTK_OBJECT(printable)); gtk_object_unref(GTK_OBJECT(table)); } static void e_contact_print_button(GnomeDialog *dialog, gint button, gpointer data) { GnomePrintMaster *master; GnomePrintContext *pc; EPrintable *printable = gtk_object_get_data(GTK_OBJECT(dialog), "printable"); GtkWidget *preview; switch( button ) { case GNOME_PRINT_PRINT: master = gnome_print_master_new_from_dialog( GNOME_PRINT_DIALOG(dialog) ); pc = gnome_print_master_get_context( master ); e_printable_reset(printable); while (e_printable_data_left(printable)) { if (gnome_print_gsave(pc) == -1) /* FIXME */; if (gnome_print_translate(pc, 72, 72) == -1) /* FIXME */; e_printable_print_page(printable, pc, 6.5 * 72, 5 * 72, TRUE); if (gnome_print_grestore(pc) == -1) /* FIXME */; if (gnome_print_showpage(pc) == -1) /* FIXME */; } gnome_print_master_close(master); gnome_print_master_print(master); gtk_object_unref(GTK_OBJECT(master)); gnome_dialog_close(dialog); break; case GNOME_PRINT_PREVIEW: master = gnome_print_master_new_from_dialog( GNOME_PRINT_DIALOG(dialog) ); pc = gnome_print_master_get_context( master ); e_printable_reset(printable); while (e_printable_data_left(printable)) { if (gnome_print_gsave(pc) == -1) /* FIXME */; if (gnome_print_translate(pc, 72, 72) == -1) /* FIXME */; e_printable_print_page(printable, pc, 6.5 * 72, 9 * 72, TRUE); if (gnome_print_grestore(pc) == -1) /* FIXME */; if (gnome_print_showpage(pc) == -1) /* FIXME */; } gnome_print_master_close(master); preview = GTK_WIDGET(gnome_print_master_preview_new(master, "Print Preview")); gtk_widget_show_all(preview); gtk_object_unref(GTK_OBJECT(master)); break; case GNOME_PRINT_CANCEL: gnome_dialog_close(dialog); break; } } static void display_view(GalViewCollection *collection, GalView *view, gpointer data) { EAddressbookView *address_view = data; if (GAL_IS_VIEW_ETABLE(view)) { change_view_type (address_view, E_ADDRESSBOOK_VIEW_TABLE); e_table_set_state_object(e_table_scrolled_get_table(E_TABLE_SCROLLED(address_view->widget)), GAL_VIEW_ETABLE(view)->state); } else if (GAL_IS_VIEW_MINICARD(view)) { change_view_type (address_view, E_ADDRESSBOOK_VIEW_MINICARD); } } void e_addressbook_view_setup_menus (EAddressbookView *view, BonoboUIComponent *uic) { GalViewFactory *factory; ETableSpecification *spec; char *galview; g_return_if_fail (view != NULL); g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); g_return_if_fail (uic != NULL); g_return_if_fail (BONOBO_IS_UI_COMPONENT (uic)); g_return_if_fail (view->view_collection == NULL); g_assert (view->view_collection == NULL); g_assert (view->view_menus == NULL); view->view_collection = gal_view_collection_new(); galview = gnome_util_prepend_user_home("/evolution/views/addressbook/"); gal_view_collection_set_storage_directories(view->view_collection, EVOLUTION_DATADIR "/evolution/views/addressbook/", galview); g_free(galview); spec = e_table_specification_new(); e_table_specification_load_from_string(spec, SPEC); factory = gal_view_factory_etable_new (spec); gtk_object_unref (GTK_OBJECT (spec)); gal_view_collection_add_factory (view->view_collection, factory); gtk_object_unref (GTK_OBJECT (factory)); factory = gal_view_factory_minicard_new (); gal_view_collection_add_factory (view->view_collection, factory); gtk_object_unref (GTK_OBJECT (factory)); gal_view_collection_load(view->view_collection); view->view_menus = gal_view_menus_new(view->view_collection); gal_view_menus_apply(view->view_menus, uic, NULL); gtk_signal_connect(GTK_OBJECT(view->view_collection), "display_view", display_view, view); } /** * e_addressbook_view_discard_menus: * @view: An addressbook view. * * Makes an addressbook view discard its GAL view menus and its views collection * objects. This should be called when the corresponding Bonobo component is * deactivated. **/ void e_addressbook_view_discard_menus (EAddressbookView *view) { g_return_if_fail (view != NULL); g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); g_return_if_fail (view->view_collection); g_assert (view->view_collection != NULL); g_assert (view->view_menus != NULL); gtk_object_unref (GTK_OBJECT (view->view_collection)); view->view_collection = NULL; gtk_object_unref (GTK_OBJECT (view->view_menus)); view->view_menus = NULL; } 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) { if (view->view_type == E_ADDRESSBOOK_VIEW_MINICARD) { char *query; EBook *book; GtkWidget *print; gtk_object_get (GTK_OBJECT(view->model), "query", &query, "book", &book, NULL); print = e_contact_print_dialog_new(book, query); g_free(query); gtk_widget_show_all(print); } else if (view->view_type == E_ADDRESSBOOK_VIEW_TABLE) { GtkWidget *dialog; EPrintable *printable; ETable *etable; dialog = gnome_print_dialog_new("Print cards", GNOME_PRINT_DIALOG_RANGE | GNOME_PRINT_DIALOG_COPIES); gnome_print_dialog_construct_range_any(GNOME_PRINT_DIALOG(dialog), GNOME_PRINT_RANGE_ALL | GNOME_PRINT_RANGE_SELECTION, NULL, NULL, NULL); gtk_object_get(GTK_OBJECT(view->widget), "table", &etable, NULL); printable = e_table_get_printable(etable); gtk_object_ref(GTK_OBJECT(view->widget)); gtk_object_set_data(GTK_OBJECT(dialog), "table", view->widget); gtk_object_set_data(GTK_OBJECT(dialog), "printable", printable); gtk_signal_connect(GTK_OBJECT(dialog), "clicked", GTK_SIGNAL_FUNC(e_contact_print_button), NULL); gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(e_contact_print_destroy), NULL); gtk_widget_show(dialog); } } static void card_deleted_cb (EBook* book, EBookStatus status, gpointer user_data) { EAddressbookView *view = user_data; emit_status_message (view, _("Done.")); if (status != E_BOOK_STATUS_SUCCESS) { e_addressbook_error_dialog (_("Error removing card"), status); } } static void do_remove (int i, gpointer user_data) { EBook *book; ECard *card; EAddressbookView *view = user_data; gtk_object_get (GTK_OBJECT(view->model), "book", &book, NULL); card = e_addressbook_model_get_card (view->model, i); e_book_remove_card(book, card, card_deleted_cb, view); gtk_object_unref (GTK_OBJECT (card)); } void e_addressbook_view_delete_selection(EAddressbookView *view) { ESelectionModel *model = get_selection_model (view); g_return_if_fail (model); emit_status_message (view, _("Removing cards...")); e_selection_model_foreach (model, do_remove, view); } 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_card_merging_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) { gtk_object_set(GTK_OBJECT(view), "query", NULL, NULL); } void e_addressbook_view_stop(EAddressbookView *view) { e_addressbook_model_stop (view->model); } gboolean e_addressbook_view_can_create (EAddressbookView *view) { return e_addressbook_model_editable (view->model); } gboolean e_addressbook_view_can_print (EAddressbookView *view) { ESelectionModel *selection_model; if (!e_addressbook_model_editable (view->model)) return FALSE; selection_model = get_selection_model (view); if (selection_model == NULL) return 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; selection_model = get_selection_model (view); if (selection_model == NULL) return 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); if (selection_model == NULL) return 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 e_addressbook_view_can_stop (EAddressbookView *view) { return e_addressbook_model_can_stop (view->model); }