diff options
Diffstat (limited to 'addressbook/gui')
-rw-r--r-- | addressbook/gui/component/addressbook-view.c | 134 | ||||
-rw-r--r-- | addressbook/gui/widgets/Makefile.am | 2 | ||||
-rw-r--r-- | addressbook/gui/widgets/e-addressbook-view.c | 418 | ||||
-rw-r--r-- | addressbook/gui/widgets/eab-popup.c | 278 | ||||
-rw-r--r-- | addressbook/gui/widgets/eab-popup.h | 151 |
5 files changed, 627 insertions, 356 deletions
diff --git a/addressbook/gui/component/addressbook-view.c b/addressbook/gui/component/addressbook-view.c index 84888f3ff5..48d8499a32 100644 --- a/addressbook/gui/component/addressbook-view.c +++ b/addressbook/gui/component/addressbook-view.c @@ -60,6 +60,7 @@ #include "addressbook/gui/merging/eab-contact-merging.h" #include "addressbook/printing/e-contact-print.h" #include "addressbook/util/eab-book-util.h" +#include "addressbook/gui/widgets/eab-popup.h" #define PARENT_TYPE G_TYPE_OBJECT static GObjectClass *parent_class = NULL; @@ -614,45 +615,10 @@ load_primary_selection (AddressbookView *view) } /* Folder popup menu callbacks */ - -static void -add_popup_menu_item (GtkMenu *menu, const char *label, const char *pixmap, - GCallback callback, gpointer user_data, gboolean sensitive) -{ - GtkWidget *item, *image; - - if (pixmap) { - item = gtk_image_menu_item_new_with_label (label); - - /* load the image */ - if (g_file_test (pixmap, G_FILE_TEST_EXISTS)) - image = gtk_image_new_from_file (pixmap); - else - image = gtk_image_new_from_stock (pixmap, GTK_ICON_SIZE_MENU); - - if (image) { - gtk_widget_show (image); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - } - } else { - item = gtk_menu_item_new_with_label (label); - } - - if (callback) - g_signal_connect (G_OBJECT (item), "activate", callback, user_data); - - if (!sensitive) - gtk_widget_set_sensitive (item, FALSE); - - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_show (item); -} - typedef struct { AddressbookView *view; ESource *selected_source; GtkWidget *toplevel; - GtkWidget *dialog; } BookRemovedClosure; static void @@ -662,7 +628,6 @@ book_removed (EBook *book, EBookStatus status, gpointer data) AddressbookView *view = closure->view; AddressbookViewPrivate *priv = view->priv; ESource *source = closure->selected_source; - GtkWidget *dialog = closure->dialog; GtkWidget *toplevel = closure->toplevel; g_free (closure); @@ -685,73 +650,54 @@ book_removed (EBook *book, EBookStatus status, gpointer data) "addressbook:remove-addressbook", NULL); } - - gtk_widget_destroy (dialog); } static void -delete_addressbook_cb (GtkWidget *widget, AddressbookView *view) +delete_addressbook_cb(EPopup *ep, EPopupItem *pitem, void *data) { + AddressbookView *view = data; AddressbookViewPrivate *priv = view->priv; ESource *selected_source; - GtkWidget *dialog; EBook *book; GError *error = NULL; + GtkWindow *toplevel; selected_source = e_source_selector_peek_primary_selection (E_SOURCE_SELECTOR (priv->selector)); if (!selected_source) return; - /* Create the confirmation dialog */ - dialog = gtk_message_dialog_new ( - GTK_WINDOW (gtk_widget_get_toplevel (widget)), - GTK_DIALOG_MODAL, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_YES_NO, - _("Address book '%s' will be removed. Are you sure you want to continue?"), - e_source_peek_name (selected_source)); -#if !GTK_CHECK_VERSION (2,4,0) - gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); -#endif - - if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_YES) { - gtk_widget_destroy (dialog); + toplevel = (GtkWindow *)gtk_widget_get_toplevel(ep->target->widget); + + if (e_error_run(toplevel, "addressbook:ask-delete-addressbook", e_source_peek_name(selected_source)) != GTK_RESPONSE_YES) return; - } /* Remove local data */ book = e_book_new (selected_source, &error); if (book) { BookRemovedClosure *closure = g_new (BookRemovedClosure, 1); - closure->toplevel = gtk_widget_get_toplevel (widget); + closure->toplevel = (GtkWidget *)toplevel; closure->view = view; closure->selected_source = selected_source; - closure->dialog = dialog; if (e_book_async_remove (book, book_removed, closure)) { - e_error_run (GTK_WINDOW (gtk_widget_get_toplevel (widget)), - "addressbook:remove-addressbook", - NULL); - + e_error_run (toplevel, "addressbook:remove-addressbook", NULL); g_free (closure); - g_object_unref (book); } } - - gtk_widget_set_sensitive (dialog, FALSE); } static void -new_addressbook_cb (GtkWidget *widget, AddressbookView *view) +new_addressbook_cb(EPopup *ep, EPopupItem *pitem, void *data) { - addressbook_config_create_new_source (gtk_widget_get_toplevel (widget)); + addressbook_config_create_new_source (gtk_widget_get_toplevel(ep->target->widget)); } static void -edit_addressbook_cb (GtkWidget *widget, AddressbookView *view) +edit_addressbook_cb(EPopup *ep, EPopupItem *pitem, void *data) { + AddressbookView *view = data; AddressbookViewPrivate *priv = view->priv; ESource *selected_source; const char *uid; @@ -769,7 +715,7 @@ edit_addressbook_cb (GtkWidget *widget, AddressbookView *view) char *uid_copy = g_strdup (uid); closure = g_new (EditorUidClosure, 1); - closure->editor = addressbook_config_edit_source (gtk_widget_get_toplevel (widget), selected_source); + closure->editor = addressbook_config_edit_source (gtk_widget_get_toplevel(ep->target->widget), selected_source); closure->uid = uid_copy; closure->view = view; @@ -794,25 +740,41 @@ primary_source_selection_changed_callback (ESourceSelector *selector, save_primary_selection (view); } +static EPopupItem abv_source_popups[] = { + { E_POPUP_ITEM, "10.new", N_("New Address Book"), new_addressbook_cb, NULL, NULL, 0 }, + { E_POPUP_ITEM, "20.delete", N_("Delete"), delete_addressbook_cb, NULL, "stock_delete", EAB_POPUP_SOURCE_USER|EAB_POPUP_SOURCE_PRIMARY }, + { E_POPUP_ITEM, "30.properties", N_("Properties..."), edit_addressbook_cb, NULL, NULL, EAB_POPUP_SOURCE_PRIMARY }, +}; static void -fill_popup_menu_callback (ESourceSelector *selector, GtkMenu *menu, AddressbookView *view) +abv_source_popup_free(EPopup *ep, GSList *list, void *data) { - AddressbookViewPrivate *priv = view->priv; - gboolean sensitive; - gboolean local_addressbook; - ESource *selected_source; - char *uri; + g_slist_free(list); +} - selected_source = e_source_selector_peek_primary_selection (E_SOURCE_SELECTOR (priv->selector)); - sensitive = selected_source ? TRUE : FALSE; +static gboolean +popup_event_callback(ESourceSelector *selector, ESource *source, GdkEventButton *event, AddressbookView *view) +{ + EABPopup *ep; + EABPopupTargetSource *t; + GSList *menus = NULL; + int i; + GtkMenu *menu; - uri = e_source_peek_relative_uri (selected_source); - local_addressbook = (uri && !strcmp ("system", uri)); - - add_popup_menu_item (menu, _("New Address Book"), NULL, G_CALLBACK (new_addressbook_cb), view, TRUE); - add_popup_menu_item (menu, _("Delete"), GTK_STOCK_DELETE, G_CALLBACK (delete_addressbook_cb), view, sensitive && !local_addressbook); - add_popup_menu_item (menu, _("Properties..."), NULL, G_CALLBACK (edit_addressbook_cb), view, sensitive); + ep = eab_popup_new("com.novell.evolution.addressbook.source.popup"); + t = eab_popup_target_new_source(ep, selector); + t->target.widget = (GtkWidget *)view->priv->notebook; + + for (i=0;i<sizeof(abv_source_popups)/sizeof(abv_source_popups[0]);i++) + menus = g_slist_prepend(menus, &abv_source_popups[i]); + + e_popup_add_items((EPopup *)ep, menus, abv_source_popup_free, view); + + /* visibility is disabled, we only disable menu items */ + menu = e_popup_create_menu_once((EPopup *)ep, (EPopupTarget *)t, 0, t->target.mask); + gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event?event->button:0, event?event->time:gtk_get_current_event_time()); + + return TRUE; } static gboolean @@ -978,15 +940,13 @@ selector_tree_drag_data_received (GtkWidget *widget, { GtkTreePath *path = NULL; GtkTreeViewDropPosition pos; - gpointer source, target = NULL; + gpointer target = NULL; GtkTreeModel *model; GtkTreeIter iter; gboolean success = FALSE; - EBook *source_book, *target_book; MergeContext *merge_context; GList *contactlist; - GList *l; if (!gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (widget), x, y, &path, &pos)) @@ -1170,8 +1130,8 @@ addressbook_view_init (AddressbookView *view) g_signal_connect_object (priv->selector, "primary_selection_changed", G_CALLBACK (primary_source_selection_changed_callback), G_OBJECT (view), 0); - g_signal_connect_object (priv->selector, "fill_popup_menu", - G_CALLBACK (fill_popup_menu_callback), + g_signal_connect_object (priv->selector, "popup_event", + G_CALLBACK (popup_event_callback), G_OBJECT (view), 0); load_primary_selection (view); diff --git a/addressbook/gui/widgets/Makefile.am b/addressbook/gui/widgets/Makefile.am index 6842ce14d5..504702b277 100644 --- a/addressbook/gui/widgets/Makefile.am +++ b/addressbook/gui/widgets/Makefile.am @@ -44,6 +44,8 @@ libeabwidgets_la_SOURCES = \ eab-contact-display.h \ eab-gui-util.c \ eab-gui-util.h \ + eab-popup.c \ + eab-popup.h \ eab-popup-control.c \ eab-popup-control.h \ eab-vcard-control.c \ diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c index e4fe2e287a..f716ea8624 100644 --- a/addressbook/gui/widgets/e-addressbook-view.c +++ b/addressbook/gui/widgets/e-addressbook-view.c @@ -29,7 +29,6 @@ #include <gtk/gtkscrolledwindow.h> #include <gal/e-table/e-table-scrolled.h> #include <gal/e-table/e-table-model.h> -#include <gal/widgets/e-popup-menu.h> #include <gal/widgets/e-gui-utils.h> #include <gal/menus/gal-view-factory-etable.h> #include <gal/menus/gal-view-etable.h> @@ -44,6 +43,7 @@ #include "addressbook/printing/e-contact-print.h" #include "addressbook/printing/e-contact-print-envelope.h" #include "addressbook/gui/search/e-addressbook-search-dialog.h" +#include "addressbook/gui/widgets/eab-popup.h" #include "e-util/e-categories-master-list-wombat.h" #include "e-util/e-sexp.h" @@ -771,7 +771,6 @@ get_selection_model (EABView *view) /* Popup menu stuff */ typedef struct { EABView *view; - EPopupMenu *submenu; gpointer closure; } ContactAndBook; @@ -781,371 +780,221 @@ contact_and_book_get_selection_model (ContactAndBook *contact_and_book) return get_selection_model (contact_and_book->view); } -static void -contact_and_book_free (ContactAndBook *contact_and_book) -{ - EABView *view = contact_and_book->view; - ESelectionModel *selection; - - if (contact_and_book->submenu) - gal_view_instance_free_popup_menu (view->view_instance, - contact_and_book->submenu); - - selection = contact_and_book_get_selection_model (contact_and_book); - if (selection) - e_selection_model_right_click_up(selection); - - g_object_unref (view); -} - -static void -get_contact_list_1(gint model_row, - gpointer closure) -{ - ContactAndBook *contact_and_book; - GList **list; - EABView *view; - EContact *contact; - - contact_and_book = closure; - list = contact_and_book->closure; - view = contact_and_book->view; - - contact = eab_model_get_contact(view->model, model_row); - *list = g_list_prepend(*list, contact); -} - static GList * -get_contact_list (ContactAndBook *contact_and_book) +get_contact_list (EABPopupTargetSelect *t) { GList *list = NULL; - ESelectionModel *selection; + int i; - selection = contact_and_book_get_selection_model (contact_and_book); - - if (selection) { - contact_and_book->closure = &list; - e_selection_model_foreach (selection, get_contact_list_1, contact_and_book); - } + for (i=0;i<t->cards->len;i++) + list = g_list_prepend(list, t->cards->pdata[i]); return list; } static void -has_email_address_1(gint model_row, - gpointer closure) +save_as (EPopup *ep, EPopupItem *pitem, void *data) { - ContactAndBook *contact_and_book; - gboolean *has_email; - EABView *view; - const EContact *contact; - GList *email; - - contact_and_book = closure; - has_email = contact_and_book->closure; - view = contact_and_book->view; + /*ContactAndBook *contact_and_book = data;*/ + GList *contacts = get_contact_list ((EABPopupTargetSelect *)ep->target); - if (*has_email) - return; - - contact = eab_model_contact_at(view->model, model_row); - - email = e_contact_get (E_CONTACT (contact), E_CONTACT_EMAIL); - - if (g_list_length (email) > 0) - *has_email = TRUE; - - g_list_foreach (email, (GFunc)g_free, NULL); - g_list_free (email); -} - -static gboolean -get_has_email_address (ContactAndBook *contact_and_book) -{ - ESelectionModel *selection; - gboolean has_email = FALSE; - - selection = contact_and_book_get_selection_model (contact_and_book); - - if (selection) { - contact_and_book->closure = &has_email; - e_selection_model_foreach (selection, has_email_address_1, contact_and_book); - } - - return has_email; -} - -static void -save_as (GtkWidget *widget, ContactAndBook *contact_and_book) -{ - GList *contacts = get_contact_list (contact_and_book); if (contacts) { eab_contact_list_save(_("Save as VCard..."), contacts, NULL); - e_free_object_list(contacts); + g_list_free(contacts); } } static void -send_as (GtkWidget *widget, ContactAndBook *contact_and_book) +send_as (EPopup *ep, EPopupItem *pitem, void *data) { - GList *contacts = get_contact_list (contact_and_book); + /*ContactAndBook *contact_and_book = data;*/ + GList *contacts = get_contact_list ((EABPopupTargetSelect *)ep->target); + if (contacts) { eab_send_contact_list(contacts, EAB_DISPOSITION_AS_ATTACHMENT); - e_free_object_list(contacts); + g_list_free(contacts); } } static void -send_to (GtkWidget *widget, ContactAndBook *contact_and_book) - +send_to (EPopup *ep, EPopupItem *pitem, void *data) { - GList *contacts = get_contact_list (contact_and_book); + /*ContactAndBook *contact_and_book = data;*/ + GList *contacts = get_contact_list ((EABPopupTargetSelect *)ep->target); if (contacts) { eab_send_contact_list(contacts, EAB_DISPOSITION_AS_TO); - e_free_object_list(contacts); + g_list_free(contacts); } } static void -print (GtkWidget *widget, ContactAndBook *contact_and_book) +print (EPopup *ep, EPopupItem *pitem, void *data) { - GList *contacts = get_contact_list (contact_and_book); - if (contacts) { - if (contacts->next) - gtk_widget_show(e_contact_print_contact_list_dialog_new(contacts)); - else - gtk_widget_show(e_contact_print_contact_dialog_new(contacts->data)); - e_free_object_list(contacts); - } -} + /*ContactAndBook *contact_and_book = data;*/ + EABPopupTargetSelect *t = (EABPopupTargetSelect *)ep->target; -#if 0 /* Envelope printing is disabled for Evolution 1.0. */ -static void -print_envelope (GtkWidget *widget, ContactAndBook *contact_and_book) -{ - GList *cards = get_card_list (contact_and_book); - if (cards) { - gtk_widget_show(e_contact_list_print_envelope_dialog_new(contact_and_book->card)); - e_free_object_list(cards); + if (t->cards->len == 1) { + gtk_widget_show(e_contact_print_contact_dialog_new(t->cards->pdata[0])); + } else { + GList *contacts = get_contact_list(t); + + gtk_widget_show(e_contact_print_contact_list_dialog_new(contacts)); + g_list_free(contacts); } } -#endif static void -copy (GtkWidget *widget, ContactAndBook *contact_and_book) +copy (EPopup *ep, EPopupItem *pitem, void *data) { + ContactAndBook *contact_and_book = data; + eab_view_copy (contact_and_book->view); } static void -paste (GtkWidget *widget, ContactAndBook *contact_and_book) +paste (EPopup *ep, EPopupItem *pitem, void *data) { + ContactAndBook *contact_and_book = data; + eab_view_paste (contact_and_book->view); } static void -cut (GtkWidget *widget, ContactAndBook *contact_and_book) +cut (EPopup *ep, EPopupItem *pitem, void *data) { + ContactAndBook *contact_and_book = data; + eab_view_cut (contact_and_book->view); } static void -delete (GtkWidget *widget, ContactAndBook *contact_and_book) +delete (EPopup *ep, EPopupItem *pitem, void *data) { - if (eab_editor_confirm_delete(GTK_WINDOW(gtk_widget_get_toplevel(contact_and_book->view->widget)))) { - EBook *book; - GList *list = get_contact_list(contact_and_book); - GList *iterator; - gboolean bulk_remove = FALSE; + ContactAndBook *contact_and_book = data; - bulk_remove = e_book_check_static_capability (contact_and_book->view->model->book, - "bulk-remove"); - - g_object_get(contact_and_book->view->model, - "book", &book, - NULL); - - if (bulk_remove) { - GList *ids = NULL; - - for (iterator = list; iterator; iterator = iterator->next) { - EContact *contact = iterator->data; - ids = g_list_prepend (ids, (char*)e_contact_get_const (contact, E_CONTACT_UID)); - } - - /* Remove the cards all at once. */ - /* XXX no callback specified... ugh */ - e_book_async_remove_contacts (book, - ids, - NULL, - NULL); - - g_list_free (ids); - } - else { - for (iterator = list; iterator; iterator = iterator->next) { - EContact *contact = iterator->data; - /* Remove the card. */ - /* XXX no callback specified... ugh */ - e_book_async_remove_contact (book, - contact, - NULL, - NULL); - } - } - e_free_object_list(list); - g_object_unref(book); - } + eab_view_delete_selection(contact_and_book->view); } static void -copy_to_folder (GtkWidget *widget, ContactAndBook *contact_and_book) +copy_to_folder (EPopup *ep, EPopupItem *pitem, void *data) { + ContactAndBook *contact_and_book = data; + eab_view_copy_to_folder (contact_and_book->view); } static void -move_to_folder (GtkWidget *widget, ContactAndBook *contact_and_book) +move_to_folder (EPopup *ep, EPopupItem *pitem, void *data) { - eab_view_move_to_folder (contact_and_book->view); -} + ContactAndBook *contact_and_book = data; -static void -free_popup_info (GtkWidget *w, ContactAndBook *contact_and_book) -{ - contact_and_book_free (contact_and_book); + eab_view_move_to_folder (contact_and_book->view); } static void -new_card (GtkWidget *widget, ContactAndBook *contact_and_book) +new_card (EPopup *ep, EPopupItem *pitem, void *data) { - EBook *book; + /*ContactAndBook *contact_and_book = data;*/ EContact *contact = e_contact_new(); - g_object_get(contact_and_book->view->model, - "book", &book, - NULL); - - eab_show_contact_editor (book, contact, TRUE, TRUE); - g_object_unref (book); + eab_show_contact_editor (((EABPopupTargetSelect *)ep->target)->book, contact, TRUE, TRUE); g_object_unref (contact); } static void -new_list (GtkWidget *widget, ContactAndBook *contact_and_book) +new_list (EPopup *ep, EPopupItem *pitem, void *data) { - EBook *book; + /*ContactAndBook *contact_and_book = data;*/ EContact *contact = e_contact_new (); - g_object_get(contact_and_book->view->model, - "book", &book, - NULL); - eab_show_contact_list_editor (book, contact, TRUE, TRUE); - g_object_unref(book); + eab_show_contact_list_editor (((EABPopupTargetSelect *)ep->target)->book, contact, TRUE, TRUE); g_object_unref(contact); } -#if 0 +static EPopupItem eabv_popup_items[] = { + { E_POPUP_ITEM, "10.new", N_("New Contact..."), new_card, NULL, "stock_contact", EAB_POPUP_SELECT_EDITABLE}, + { E_POPUP_ITEM, "15.newlist", N_("New Contact List..."), new_list, NULL, "stock_contact-list", EAB_POPUP_SELECT_EDITABLE }, + + { E_POPUP_BAR, "20.bar" }, + { E_POPUP_ITEM, "30.saveas", N_("Save as VCard..."), save_as, NULL, "stock_save-as", EAB_POPUP_SELECT_MANY }, + { E_POPUP_ITEM, "40.forward", N_("Forward Contact"), send_as, NULL, "stock_mail-forward", EAB_POPUP_SELECT_MANY }, + { E_POPUP_ITEM, "50.mailto", N_("Send Message to Contact"), send_to, NULL, "stock_mail-send", EAB_POPUP_SELECT_MANY|EAB_POPUP_SELECT_EMAIL }, + { E_POPUP_ITEM, "60.print", N_("Print"), print, NULL, "stock_print", EAB_POPUP_SELECT_MANY }, + + { E_POPUP_BAR, "70.bar" }, + { E_POPUP_ITEM, "80.copyto", N_("Copy to Address Book..."), copy_to_folder, NULL, NULL, EAB_POPUP_SELECT_MANY }, + { E_POPUP_ITEM, "90.moveto", N_("Move to Address Book..."), move_to_folder, NULL, NULL, EAB_POPUP_SELECT_MANY|EAB_POPUP_SELECT_EDITABLE }, + + { E_POPUP_BAR, "a0.bar" }, + { E_POPUP_BAR, "b0.cut", N_("Cut"), cut, NULL, "stock_cut", EAB_POPUP_SELECT_MANY|EAB_POPUP_SELECT_EDITABLE }, + { E_POPUP_ITEM, "c0.copy", N_("Copy"), copy, NULL, "stock_copy", EAB_POPUP_SELECT_MANY }, + { E_POPUP_ITEM, "d0.paste", N_("Paste"), paste, NULL, "stock_paste", EAB_POPUP_SELECT_EDITABLE }, + { E_POPUP_ITEM, "e0.delete", N_("Delete"), delete, NULL, "stock_delete", EAB_POPUP_SELECT_EDITABLE|EAB_POPUP_SELECT_MANY }, +}; + static void -sources (GtkWidget *widget, ContactAndBook *contact_and_book) +get_card_1(gint model_row, void *data) { - BonoboControl *control; - GNOME_Evolution_ShellView shell_view; - CORBA_Environment ev; + ContactAndBook *contact_and_book = data; + EContact *contact; - control = g_object_get_data (G_OBJECT (gcal), "control"); - if (control == NULL) - return; + contact = eab_model_get_contact(contact_and_book->view->model, model_row); + if (contact) + g_ptr_array_add((GPtrArray *)contact_and_book->closure, contact); +} - shell_view = get_shell_view_interface (control); - if (shell_view == CORBA_OBJECT_NIL) - return; +static void +eabv_popup_free(EPopup *ep, GSList *list, void *data) +{ + ContactAndBook *cab = data; + ESelectionModel *selection; - CORBA_exception_init (&ev); - - GNOME_Evolution_ShellView_showSettings (shell_view, &ev); - - if (BONOBO_EX (&ev)) - g_message ("control_util_show_settings(): Could not show settings"); + /* NB: this looks strange to me */ + selection = contact_and_book_get_selection_model(cab); + if (selection) + e_selection_model_right_click_up(selection); - CORBA_exception_free (&ev); + g_slist_free(list); + g_object_unref(cab->view); + g_free(cab); } -#endif - -#define POPUP_READONLY_MASK 0x1 -#define POPUP_NOSELECTION_MASK 0x2 -#define POPUP_NOEMAIL_MASK 0x4 static void do_popup_menu(EABView *view, GdkEvent *event) { + EABPopup *ep; + EABPopupTargetSelect *t; + GSList *menus = NULL; + int i; + GtkMenu *menu; + GPtrArray *cards = g_ptr_array_new(); ContactAndBook *contact_and_book; - GtkMenu *popup; - EPopupMenu *submenu = NULL; ESelectionModel *selection_model; - gboolean selection = FALSE; - - EPopupMenu menu[] = { - E_POPUP_ITEM (N_("New Contact..."), G_CALLBACK(new_card), POPUP_READONLY_MASK), - E_POPUP_ITEM (N_("New Contact List..."), G_CALLBACK(new_list), POPUP_READONLY_MASK), - E_POPUP_SEPARATOR, -#if 0 - E_POPUP_ITEM (N_("Go to Folder..."), G_CALLBACK (goto_folder), 0), - E_POPUP_ITEM (N_("Import..."), G_CALLBACK (import), POPUP_READONLY_MASK), - E_POPUP_SEPARATOR, - E_POPUP_ITEM (N_("Search for Contacts..."), G_CALLBACK (search), 0), - E_POPUP_ITEM (N_("Address Book Sources..."), G_CALLBACK (sources), 0), - E_POPUP_SEPARATOR, - E_POPUP_ITEM (N_("Pilot Settings..."), G_CALLBACK (pilot_settings), 0), -#endif - E_POPUP_SEPARATOR, - E_POPUP_ITEM (N_("Save as VCard..."), G_CALLBACK(save_as), POPUP_NOSELECTION_MASK), - E_POPUP_ITEM (N_("Forward Contact"), G_CALLBACK(send_as), POPUP_NOSELECTION_MASK), - E_POPUP_ITEM (N_("Send Message to Contact"), G_CALLBACK(send_to), POPUP_NOSELECTION_MASK | POPUP_NOEMAIL_MASK), - E_POPUP_ITEM (N_("Print"), G_CALLBACK(print), POPUP_NOSELECTION_MASK), -#if 0 /* Envelope printing is disabled for Evolution 1.0. */ - E_POPUP_ITEM (N_("Print Envelope"), G_CALLBACK(print_envelope), POPUP_NOSELECTION_MASK), -#endif - E_POPUP_SEPARATOR, - - E_POPUP_ITEM (N_("Copy to Address Book..."), G_CALLBACK(copy_to_folder), POPUP_NOSELECTION_MASK), - E_POPUP_ITEM (N_("Move to Address Book..."), G_CALLBACK(move_to_folder), POPUP_READONLY_MASK | POPUP_NOSELECTION_MASK), - E_POPUP_SEPARATOR, - - E_POPUP_ITEM (N_("Cut"), G_CALLBACK (cut), POPUP_READONLY_MASK | POPUP_NOSELECTION_MASK), - E_POPUP_ITEM (N_("Copy"), G_CALLBACK (copy), POPUP_NOSELECTION_MASK), - E_POPUP_ITEM (N_("Paste"), G_CALLBACK (paste), POPUP_READONLY_MASK), - E_POPUP_ITEM (N_("Delete"), G_CALLBACK(delete), POPUP_READONLY_MASK | POPUP_NOSELECTION_MASK), - E_POPUP_SEPARATOR, - -#if 0 - E_POPUP_SUBMENU (N_("Current View"), submenu = gal_view_instance_get_popup_menu (view->view_instance), 0), -#endif - E_POPUP_TERMINATOR - }; contact_and_book = g_new(ContactAndBook, 1); contact_and_book->view = view; - contact_and_book->submenu = submenu; + g_object_ref(contact_and_book->view); - g_object_ref (contact_and_book->view); + selection_model = contact_and_book_get_selection_model(contact_and_book); + if (selection_model) { + contact_and_book->closure = cards; + e_selection_model_foreach(selection_model, get_card_1, contact_and_book); + } - selection_model = contact_and_book_get_selection_model (contact_and_book); - if (selection_model) - selection = e_selection_model_selected_count (selection_model) > 0; + ep = eab_popup_new("com.novell.evolution.addressbook.view.popup"); + t = eab_popup_target_new_select(ep, view->book, !eab_model_editable(view->model), cards); + t->target.widget = (GtkWidget *)view; - popup = e_popup_menu_create (menu, - 0, - (eab_model_editable (view->model) ? 0 : POPUP_READONLY_MASK) + - (selection ? 0 : POPUP_NOSELECTION_MASK) + - (get_has_email_address (contact_and_book) ? 0 : POPUP_NOEMAIL_MASK), - contact_and_book); + for (i=0;i<sizeof(eabv_popup_items)/sizeof(eabv_popup_items[0]);i++) + menus = g_slist_prepend(menus, &eabv_popup_items[i]); - g_signal_connect (popup, "selection-done", - G_CALLBACK (free_popup_info), contact_and_book); - e_popup_menu (popup, event); + e_popup_add_items((EPopup *)ep, menus, eabv_popup_free, contact_and_book); + /* visibility is disabled, we only disable menu items */ + /* FIXME: when enable is implemented in e-popup */ + menu = e_popup_create_menu_once((EPopup *)ep, (EPopupTarget *)t, 0, t->target.mask); + gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event?event->button.button:0, event?event->button.time:gtk_get_current_event_time()); } static void @@ -1985,12 +1834,43 @@ eab_view_print_preview(EABView *view) void eab_view_delete_selection(EABView *view) { - ContactAndBook contact_and_book; + GList *list, *l; + + if (!eab_editor_confirm_delete(GTK_WINDOW(gtk_widget_get_toplevel(view->widget)))) + return; + + list = get_selected_contacts(view); + if (e_book_check_static_capability (view->book, "bulk-remove")) { + GList *ids = NULL; + + for (l=list;l;l=g_list_next(l)) { + EContact *contact = l->data; + + ids = g_list_prepend (ids, (char*)e_contact_get_const (contact, E_CONTACT_UID)); + } - memset (&contact_and_book, 0, sizeof (contact_and_book)); - contact_and_book.view = view; + /* Remove the cards all at once. */ + /* XXX no callback specified... ugh */ + e_book_async_remove_contacts (view->book, + ids, + NULL, + NULL); + + g_list_free (ids); + } + else { + for (l=list;l;l=g_list_next(l)) { + EContact *contact = l->data; + /* Remove the card. */ + /* XXX no callback specified... ugh */ + e_book_async_remove_contact (view->book, + contact, + NULL, + NULL); + } + } - delete (GTK_WIDGET (view), &contact_and_book); + e_free_object_list(list); } static void diff --git a/addressbook/gui/widgets/eab-popup.c b/addressbook/gui/widgets/eab-popup.c new file mode 100644 index 0000000000..d2faa40fc5 --- /dev/null +++ b/addressbook/gui/widgets/eab-popup.c @@ -0,0 +1,278 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Michael Zucchi <notzed@ximian.com> + * + * Copyright 2004 Novell, Inc. (www.novell.com) + * + * This program 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; version 2 of the License. + * + * 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 program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <stdlib.h> + +#include <glib.h> + +#include "eab-popup.h" +#include "widgets/misc/e-source-selector.h" +#include <libebook/e-contact.h> + +static GObjectClass *eabp_parent; + +static void +eabp_init(GObject *o) +{ + /*EABPopup *eabp = (EABPopup *)o; */ +} + +static void +eabp_finalise(GObject *o) +{ + ((GObjectClass *)eabp_parent)->finalize(o); +} + +static void +eabp_target_free(EPopup *ep, EPopupTarget *t) +{ + switch (t->type) { + case EAB_POPUP_TARGET_SELECT: { + EABPopupTargetSelect *s = (EABPopupTargetSelect *)t; + int i; + + for (i=0;i<s->cards->len;i++) + g_object_unref(s->cards->pdata[i]); + g_ptr_array_free(s->cards, TRUE); + g_object_unref(s->book); + + break; } + case EAB_POPUP_TARGET_SOURCE: { + EABPopupTargetSource *s = (EABPopupTargetSource *)t; + + g_object_unref(s->selector); + break; } + } + + ((EPopupClass *)eabp_parent)->target_free(ep, t); +} + +static void +eabp_class_init(GObjectClass *klass) +{ + klass->finalize = eabp_finalise; + ((EPopupClass *)klass)->target_free = eabp_target_free; +} + +GType +eab_popup_get_type(void) +{ + static GType type = 0; + + if (type == 0) { + static const GTypeInfo info = { + sizeof(EABPopupClass), + NULL, NULL, + (GClassInitFunc)eabp_class_init, + NULL, NULL, + sizeof(EABPopup), 0, + (GInstanceInitFunc)eabp_init + }; + eabp_parent = g_type_class_ref(e_popup_get_type()); + type = g_type_register_static(e_popup_get_type(), "EABPopup", &info, 0); + } + + return type; +} + +EABPopup *eab_popup_new(const char *menuid) +{ + EABPopup *eabp = g_object_new(eab_popup_get_type(), 0); + + e_popup_construct(&eabp->popup, menuid); + + return eabp; +} + +/** + * eab_popup_target_new_select: + * @eabp: Address book popup. + * @book: Book the cards belong to. + * @readonly: Book is read-only mode. FIXME: Why can't we just get this off the book? + * @cards: Cards selected. This will be freed on completion. + * + * Create a new selection popup target. + * + * Return value: + **/ +EABPopupTargetSelect * +eab_popup_target_new_select(EABPopup *eabp, struct _EBook *book, int readonly, GPtrArray *cards) +{ + EABPopupTargetSelect *t = e_popup_target_new(&eabp->popup, EAB_POPUP_TARGET_SELECT, sizeof(*t)); + guint32 mask = ~0; + int has_email = FALSE, i; + + t->book = book; + g_object_ref(book); + t->cards = cards; + + for (i=0;i<cards->len && !has_email;i++) { + EContact *contact = cards->pdata[i]; + GList *email; + + email = e_contact_get(E_CONTACT(contact), E_CONTACT_EMAIL); + if (email) { + has_email = TRUE; + + g_list_foreach(email, (GFunc)g_free, NULL); + g_list_free(email); + } + } + + if (has_email) + mask &= ~EAB_POPUP_SELECT_EMAIL; + + if (!readonly) + mask &= ~EAB_POPUP_SELECT_EDITABLE; + + if (cards->len == 1) + mask &= ~EAB_POPUP_SELECT_ONE; + + if (cards->len >= 1) + mask &= ~EAB_POPUP_SELECT_MANY; + + t->target.mask = mask; + + return t; +} + +EABPopupTargetSource * +eab_popup_target_new_source(EABPopup *eabp, ESourceSelector *selector) +{ + EABPopupTargetSource *t = e_popup_target_new(&eabp->popup, EAB_POPUP_TARGET_SOURCE, sizeof(*t)); + guint32 mask = ~0; + const char *source_uri; + ESource *source; + + /* TODO: this is duplicated for calendar and tasks too */ + + t->selector = selector; + g_object_ref(selector); + + /* TODO: perhaps we need to copy this so it doesn't change during the lifecycle */ + source = e_source_selector_peek_primary_selection(selector); + if (source) + mask &= ~EAB_POPUP_SOURCE_PRIMARY; + + /* FIXME Gross hack, should have a property or something */ + source_uri = e_source_peek_relative_uri(source); + if (source_uri && !strcmp("system", source_uri)) + mask &= ~EAB_POPUP_SOURCE_SYSTEM; + else + mask &= ~EAB_POPUP_SOURCE_USER; + + t->target.mask = mask; + + return t; +} + +/* ********************************************************************** */ +/* Popup menu plugin handler */ + +/* +<e-plugin + class="com.ximian.mail.plugin.popup:1.0" + id="com.ximian.mail.plugin.popup.iteab:1.0" + type="shlib" + location="/opt/gnome2/lib/camel/1.0/libcamelimap.so" + name="imap" + description="IMAP4 and IMAP4v1 mail store"> + <hook class="com.ximian.mail.popupMenu:1.0" + handler="HandlePopup"> + <menu id="any" target="select"> + <iteab + type="iteab|toggle|radio|image|submenu|bar" + active + path="foo/bar" + label="label" + icon="foo" + mask="select_one" + activate="eabp_view_eabacs"/> + </menu> + </extension> + +*/ + +static void *eabph_parent_class; +#define eabph ((EABPopupHook *)eph) + +static const EPopupHookTargetMask eabph_select_masks[] = { + { "one", EAB_POPUP_SELECT_ONE }, + { "many", EAB_POPUP_SELECT_MANY }, + { 0 } +}; + +static const EPopupHookTargetMask eabph_source_masks[] = { + { "primary", EAB_POPUP_SOURCE_PRIMARY }, + { "system", EAB_POPUP_SOURCE_SYSTEM }, + { 0 } +}; + +static const EPopupHookTargetMap eabph_targets[] = { + { "select", EAB_POPUP_TARGET_SELECT, eabph_select_masks }, + { "source", EAB_POPUP_TARGET_SOURCE, eabph_source_masks }, + { 0 } +}; + +static void +eabph_finalise(GObject *o) +{ + /*EPluginHook *eph = (EPluginHook *)o;*/ + + ((GObjectClass *)eabph_parent_class)->finalize(o); +} + +static void +eabph_class_init(EPluginHookClass *klass) +{ + int i; + + ((GObjectClass *)klass)->finalize = eabph_finalise; + ((EPluginHookClass *)klass)->id = "com.ximian.evolution.addressbook.popup:1.0"; + + for (i=0;eabph_targets[i].type;i++) + e_popup_hook_class_add_target_map((EPopupHookClass *)klass, &eabph_targets[i]); + + ((EPopupHookClass *)klass)->popup_class = g_type_class_ref(eab_popup_get_type()); +} + +GType +eab_popup_hook_get_type(void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof(EABPopupHookClass), NULL, NULL, (GClassInitFunc) eabph_class_init, NULL, NULL, + sizeof(EABPopupHook), 0, (GInstanceInitFunc) NULL, + }; + + eabph_parent_class = g_type_class_ref(e_popup_hook_get_type()); + type = g_type_register_static(e_popup_hook_get_type(), "EABPopupHook", &info, 0); + } + + return type; +} diff --git a/addressbook/gui/widgets/eab-popup.h b/addressbook/gui/widgets/eab-popup.h new file mode 100644 index 0000000000..996cf78d6d --- /dev/null +++ b/addressbook/gui/widgets/eab-popup.h @@ -0,0 +1,151 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Michael Zucchi <notzed@ximian.com> + * + * Copyright 2004 Novell, Inc. (www.novell.com) + * + * This program 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; version 2 of the License. + * + * 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 program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __EAB_POPUP_H__ +#define __EAB_POPUP_H__ + +#include <glib-object.h> + +#include "e-util/e-popup.h" + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +typedef struct _EABPopup EABPopup; +typedef struct _EABPopupClass EABPopupClass; + +/** + * enum _eab_popup_target_t - A list of mail popup target types. + * + * @EAB_POPUP_TARGET_SELECT: A selection of cards + * @EAB_POPUP_TARGET_SOURCE: A source selection. + * + * Defines the value of the targetid for all EABPopup target types. + **/ +enum _eab_popup_target_t { + EAB_POPUP_TARGET_SELECT, + EAB_POPUP_TARGET_SOURCE, +}; + +/** + * enum _eab_popup_target_select_t - EABPopupTargetSelect qualifiers. + * + * @EAB_POPUP_SELECT_ONE: Only one item is selected. + * @EAB_POPUP_SELECT_MANY: One ore more items are selected. + * @EAB_POPUP_SELECT_EDITABLE: Read/writable source. + * @EAB_POPUP_SELECT_EMAIL: Has an email address. + **/ +enum _eab_popup_target_select_t { + EAB_POPUP_SELECT_ONE = 1<<0, + EAB_POPUP_SELECT_MANY = 1<<1, + EAB_POPUP_SELECT_EDITABLE = 1<<2, + EAB_POPUP_SELECT_EMAIL = 1<<3, +}; + +/** + * enum _eab_popup_target_source_t - EABPopupTargetSource qualifiers. + * + * @EAB_POPUP_SOURCE_PRIMARY: Has a primary selection. + * @EAB_POPUP_SOURCE_SYSTEM: Is a 'system' folder. + * + **/ +enum _eab_popup_target_source_t { + EAB_POPUP_SOURCE_PRIMARY = 1<<0, + EAB_POPUP_SOURCE_SYSTEM = 1<<1, /* system folder */ + EAB_POPUP_SOURCE_USER = 1<<2, /* user folder (!system) */ +}; + +typedef struct _EABPopupTargetSelect EABPopupTargetSelect; +typedef struct _EABPopupTargetSource EABPopupTargetSource; + +/** + * struct _EABPopupTargetSelect - A list of address cards. + * + * @target: Superclass. + * @book: Book the cards belong to. + * @cards: All selected cards. + * + * Used to represent a selection of cards as context for a popup + * menu. + **/ +struct _EABPopupTargetSelect { + EPopupTarget target; + + struct _EBook *book; + GPtrArray *cards; +}; + +/** + * struct _EABPopupTargetSource - A source target. + * + * @target: Superclass. + * @selector: Selector holding the source selection. + * + * This target is used to represent a source selection. + **/ +struct _EABPopupTargetSource { + EPopupTarget target; + + struct _ESourceSelector *selector; +}; + +typedef struct _EPopupItem EABPopupItem; + +/* The object */ +struct _EABPopup { + EPopup popup; + + struct _EABPopupPrivate *priv; +}; + +struct _EABPopupClass { + EPopupClass popup_class; +}; + +GType eab_popup_get_type(void); + +EABPopup *eab_popup_new(const char *menuid); + +EABPopupTargetSelect *eab_popup_target_new_select(EABPopup *eabp, struct _EBook *book, int readonly, GPtrArray *cards); +EABPopupTargetSource *eab_popup_target_new_source(EABPopup *eabp, struct _ESourceSelector *selector); + +/* ********************************************************************** */ + +typedef struct _EABPopupHook EABPopupHook; +typedef struct _EABPopupHookClass EABPopupHookClass; + +struct _EABPopupHook { + EPopupHook hook; +}; + +struct _EABPopupHookClass { + EPopupHookClass hook_class; +}; + +GType eab_popup_hook_get_type(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __EAB_POPUP_H__ */ |