2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2002 Hiroyuki Yamamoto
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include <gdk/gdkkeysyms.h>
28 #include <gtk/gtkwindow.h>
29 #include <gtk/gtksignal.h>
30 #include <gtk/gtkvbox.h>
31 #include <gtk/gtkscrolledwindow.h>
32 #include <gtk/gtkhpaned.h>
33 #include <gtk/gtkhbox.h>
34 #include <gtk/gtklabel.h>
35 #include <gtk/gtkentry.h>
36 #include <gtk/gtkctree.h>
37 #include <gtk/gtkclist.h>
38 #include <gtk/gtktable.h>
39 #include <gtk/gtkhbbox.h>
40 #include <gtk/gtkbutton.h>
41 #include <gtk/gtkmenu.h>
42 #include <gtk/gtkmenuitem.h>
43 #include <gtk/gtkitemfactory.h>
49 #include "addressbook.h"
50 #include "manage_window.h"
51 #include "prefs_common.h"
52 #include "alertpanel.h"
53 #include "inputdialog.h"
55 #include "stock_pixmap.h"
63 #include "addr_compl.h"
66 #include "addressitem.h"
68 #include "addrcache.h"
70 #include "addrindex.h"
71 #include "addressadd.h"
73 #include "editvcard.h"
74 #include "editgroup.h"
75 #include "editaddress.h"
77 #include "importldif.h"
78 #include "importmutt.h"
79 #include "importpine.h"
83 #include "editjpilot.h"
91 #define ADDRESSBOOK_LDAP_BUSYMSG "Busy"
94 #include "addrselect.h"
96 #include "addrgather.h"
97 #include "adbookbase.h"
98 #include "exphtmldlg.h"
105 } AddressBookColumnPos;
108 #define COL_NAME_WIDTH 164
109 #define COL_ADDRESS_WIDTH 156
111 #define COL_FOLDER_WIDTH 170
112 #define ADDRESSBOOK_WIDTH 640
113 #define ADDRESSBOOK_HEIGHT 360
115 #define ADDRESSBOOK_MSGBUF_SIZE 2048
117 static GdkPixmap *folderxpm;
118 static GdkBitmap *folderxpmmask;
119 static GdkPixmap *folderopenxpm;
120 static GdkBitmap *folderopenxpmmask;
121 static GdkPixmap *groupxpm;
122 static GdkBitmap *groupxpmmask;
123 static GdkPixmap *interfacexpm;
124 static GdkBitmap *interfacexpmmask;
125 static GdkPixmap *bookxpm;
126 static GdkBitmap *bookxpmmask;
127 static GdkPixmap *addressxpm;
128 static GdkBitmap *addressxpmmask;
129 static GdkPixmap *vcardxpm;
130 static GdkBitmap *vcardxpmmask;
131 static GdkPixmap *jpilotxpm;
132 static GdkBitmap *jpilotxpmmask;
133 static GdkPixmap *categoryxpm;
134 static GdkBitmap *categoryxpmmask;
135 static GdkPixmap *ldapxpm;
136 static GdkBitmap *ldapxpmmask;
139 static gchar addressbook_msgbuf[ ADDRESSBOOK_MSGBUF_SIZE ];
141 /* Address list selection */
142 static AddrSelectList *_addressSelect_ = NULL;
143 static AddressClipboard *_clipBoard_ = NULL;
145 /* Address index file and interfaces */
146 static AddressIndex *_addressIndex_ = NULL;
147 static GList *_addressInterfaceList_ = NULL;
148 static GList *_addressIFaceSelection_ = NULL;
149 #define ADDRESSBOOK_IFACE_SELECTION "1/y,3/y,4/y,2/n"
151 static AddressBook_win addrbook;
153 static GHashTable *_addressBookTypeHash_ = NULL;
154 static GList *_addressBookTypeList_ = NULL;
156 static void addressbook_create (void);
157 static gint addressbook_close (void);
158 static void addressbook_button_set_sensitive (void);
160 /* callback functions */
161 static void addressbook_del_clicked (GtkButton *button,
163 static void addressbook_reg_clicked (GtkButton *button,
165 static void addressbook_to_clicked (GtkButton *button,
167 static void addressbook_lup_clicked (GtkButton *button,
170 static void addressbook_tree_selected (GtkCTree *ctree,
174 static void addressbook_list_selected (GtkCList *clist,
179 static void addressbook_list_row_selected (GtkCTree *clist,
183 static void addressbook_list_row_unselected (GtkCTree *clist,
187 static void addressbook_person_expand_node (GtkCTree *ctree,
190 static void addressbook_person_collapse_node (GtkCTree *ctree,
193 static void addressbook_entry_gotfocus (GtkWidget *widget);
196 static void addressbook_entry_changed (GtkWidget *widget);
199 static void addressbook_list_button_pressed (GtkWidget *widget,
200 GdkEventButton *event,
202 static void addressbook_list_button_released (GtkWidget *widget,
203 GdkEventButton *event,
205 static void addressbook_tree_button_pressed (GtkWidget *ctree,
206 GdkEventButton *event,
208 static void addressbook_tree_button_released (GtkWidget *ctree,
209 GdkEventButton *event,
211 static void addressbook_popup_close (GtkMenuShell *menu_shell,
214 static void addressbook_new_folder_cb (gpointer data,
217 static void addressbook_new_group_cb (gpointer data,
220 static void addressbook_treenode_edit_cb (gpointer data,
223 static void addressbook_treenode_delete_cb (gpointer data,
227 static void addressbook_change_node_name (GtkCTreeNode *node,
230 static void addressbook_new_address_cb (gpointer data,
233 static void addressbook_edit_address_cb (gpointer data,
236 static void addressbook_delete_address_cb (gpointer data,
240 static void close_cb (gpointer data,
243 static void addressbook_file_save_cb (gpointer data,
247 /* Data source edit stuff */
248 static void addressbook_new_book_cb (gpointer data,
251 static void addressbook_new_vcard_cb (gpointer data,
256 static void addressbook_new_jpilot_cb (gpointer data,
262 static void addressbook_new_ldap_cb (gpointer data,
267 static void addressbook_set_clist (AddressObject *obj);
269 static void addressbook_load_tree (void);
270 void addressbook_read_file (void);
272 static GtkCTreeNode *addressbook_add_object (GtkCTreeNode *node,
274 static void addressbook_treenode_remove_item ( void );
276 static AddressDataSource *addressbook_find_datasource
277 (GtkCTreeNode *node );
279 static AddressBookFile *addressbook_get_book_file(void);
281 static GtkCTreeNode *addressbook_node_add_folder
283 AddressDataSource *ds,
284 ItemFolder *itemFolder,
285 AddressObjectType otype);
286 static GtkCTreeNode *addressbook_node_add_group (GtkCTreeNode *node,
287 AddressDataSource *ds,
288 ItemGroup *itemGroup);
289 static void addressbook_tree_remove_children (GtkCTree *ctree,
290 GtkCTreeNode *parent);
291 static void addressbook_move_nodes_up (GtkCTree *ctree,
293 static GtkCTreeNode *addressbook_find_group_node (GtkCTreeNode *parent,
295 static GtkCTreeNode *addressbook_find_folder_node( GtkCTreeNode *parent,
296 ItemFolder *folder );
298 static void addressbook_delete_object (AddressObject *obj);
300 static void key_pressed (GtkWidget *widget,
303 static gint addressbook_treenode_compare_func (GtkCList *clist,
306 static gint addressbook_list_compare_func (GtkCList *clist,
311 static void addressbook_ldap_show_message (SyldapServer *server);
314 /* LUT's and IF stuff */
315 static void addressbook_free_treenode ( gpointer data );
316 AddressTypeControlItem *addrbookctl_lookup (gint ot);
317 AddressTypeControlItem *addrbookctl_lookup_iface(AddressIfType ifType);
319 void addrbookctl_build_map (GtkWidget *window);
320 void addrbookctl_build_iflist (void);
321 AdapterInterface *addrbookctl_find_interface (AddressIfType ifType);
322 void addrbookctl_build_ifselect (void);
324 static void addrbookctl_free_interface (AdapterInterface *adapter);
325 static void addrbookctl_free_datasource (AdapterDSource *adapter);
326 static void addrbookctl_free_folder (AdapterFolder *adapter);
327 static void addrbookctl_free_group (AdapterGroup *adapter);
329 static void addressbook_list_select_clear ( void );
330 static void addressbook_list_select_add ( AddrItemObject *aio,
331 AddressDataSource *ds );
332 static void addressbook_list_select_remove ( AddrItemObject *aio );
334 static void addressbook_import_ldif_cb ( void );
335 static void addressbook_import_mutt_cb ( void );
336 static void addressbook_import_pine_cb ( void );
337 static void addressbook_export_html_cb ( void );
338 static void addressbook_clip_cut_cb ( void );
339 static void addressbook_clip_copy_cb ( void );
340 static void addressbook_clip_paste_cb ( void );
341 static void addressbook_clip_paste_address_cb ( void );
342 static void addressbook_treenode_cut_cb ( void );
343 static void addressbook_treenode_copy_cb ( void );
344 static void addressbook_treenode_paste_cb ( void );
346 static GtkItemFactoryEntry addressbook_entries[] =
348 {N_("/_File"), NULL, NULL, 0, "<Branch>"},
349 {N_("/_File/New _Book"), "<alt>B", addressbook_new_book_cb, 0, NULL},
350 {N_("/_File/New _vCard"), "<alt>D", addressbook_new_vcard_cb, 0, NULL},
352 {N_("/_File/New _JPilot"), "<alt>J", addressbook_new_jpilot_cb, 0, NULL},
355 {N_("/_File/New _Server"), "<alt>S", addressbook_new_ldap_cb, 0, NULL},
357 {N_("/_File/---"), NULL, NULL, 0, "<Separator>"},
358 {N_("/_File/_Edit"), NULL, addressbook_treenode_edit_cb, 0, NULL},
359 {N_("/_File/_Delete"), NULL, addressbook_treenode_delete_cb, 0, NULL},
360 {N_("/_File/---"), NULL, NULL, 0, "<Separator>"},
361 {N_("/_File/_Save"), "<alt>S", addressbook_file_save_cb, 0, NULL},
362 {N_("/_File/_Close"), "<alt>W", close_cb, 0, NULL},
363 {N_("/_Edit"), NULL, NULL, 0, "<Branch>"},
364 {N_("/_Edit/C_ut"), "<ctl>X", addressbook_clip_cut_cb, 0, NULL},
365 {N_("/_Edit/_Copy"), "<ctl>C", addressbook_clip_copy_cb, 0, NULL},
366 {N_("/_Edit/_Paste"), "<ctl>V", addressbook_clip_paste_cb, 0, NULL},
367 {N_("/_Edit/---"), NULL, NULL, 0, "<Separator>"},
368 {N_("/_Edit/Pa_ste Address"), NULL, addressbook_clip_paste_address_cb, 0, NULL},
369 {N_("/_Address"), NULL, NULL, 0, "<Branch>"},
370 {N_("/_Address/New _Address"), "<alt>N", addressbook_new_address_cb, 0, NULL},
371 {N_("/_Address/New _Group"), "<alt>G", addressbook_new_group_cb, 0, NULL},
372 {N_("/_Address/New _Folder"), "<alt>R", addressbook_new_folder_cb, 0, NULL},
373 {N_("/_Address/---"), NULL, NULL, 0, "<Separator>"},
374 {N_("/_Address/_Edit"), "<alt>Return", addressbook_edit_address_cb, 0, NULL},
375 {N_("/_Address/_Delete"), NULL, addressbook_delete_address_cb, 0, NULL},
376 {N_("/_Tools/---"), NULL, NULL, 0, "<Separator>"},
377 {N_("/_Tools/Import _LDIF file..."), NULL, addressbook_import_ldif_cb, 0, NULL},
378 {N_("/_Tools/Import M_utt file..."), NULL, addressbook_import_mutt_cb, 0, NULL},
379 {N_("/_Tools/Import _Pine file..."), NULL, addressbook_import_pine_cb, 0, NULL},
380 {N_("/_Tools/---"), NULL, NULL, 0, "<Separator>"},
381 {N_("/_Tools/Export _HTML..."), NULL, addressbook_export_html_cb, 0, NULL},
382 {N_("/_Help"), NULL, NULL, 0, "<LastBranch>"},
383 {N_("/_Help/_About"), NULL, about_show, 0, NULL}
386 static GtkItemFactoryEntry addressbook_tree_popup_entries[] =
388 {N_("/New _Address"), NULL, addressbook_new_address_cb, 0, NULL},
389 {N_("/New _Group"), NULL, addressbook_new_group_cb, 0, NULL},
390 {N_("/New _Folder"), NULL, addressbook_new_folder_cb, 0, NULL},
391 {N_("/---"), NULL, NULL, 0, "<Separator>"},
392 {N_("/_Edit"), NULL, addressbook_treenode_edit_cb, 0, NULL},
393 {N_("/_Delete"), NULL, addressbook_treenode_delete_cb, 0, NULL},
394 {N_("/---"), NULL, NULL, 0, "<Separator>"},
395 {N_("/C_ut"), NULL, addressbook_treenode_cut_cb, 0, NULL},
396 {N_("/_Copy"), NULL, addressbook_treenode_copy_cb, 0, NULL},
397 {N_("/_Paste"), NULL, addressbook_treenode_paste_cb, 0, NULL}
400 static GtkItemFactoryEntry addressbook_list_popup_entries[] =
402 {N_("/New _Address"), NULL, addressbook_new_address_cb, 0, NULL},
403 {N_("/New _Group"), NULL, addressbook_new_group_cb, 0, NULL},
404 {N_("/New _Folder"), NULL, addressbook_new_folder_cb, 0, NULL},
405 {N_("/---"), NULL, NULL, 0, "<Separator>"},
406 {N_("/_Edit"), NULL, addressbook_edit_address_cb, 0, NULL},
407 {N_("/_Delete"), NULL, addressbook_delete_address_cb, 0, NULL},
408 {N_("/---"), NULL, NULL, 0, "<Separator>"},
409 {N_("/C_ut"), NULL, addressbook_clip_cut_cb, 0, NULL},
410 {N_("/_Copy"), NULL, addressbook_clip_copy_cb, 0, NULL},
411 {N_("/_Paste"), NULL, addressbook_clip_paste_cb, 0, NULL},
412 {N_("/---"), NULL, NULL, 0, "<Separator>"},
413 {N_("/Pa_ste Address"), NULL, addressbook_clip_paste_address_cb, 0, NULL}
416 void addressbook_open(Compose *target)
418 /* Initialize all static members */
419 if( _clipBoard_ == NULL ) {
420 _clipBoard_ = addrclip_create();
422 if( _addressIndex_ != NULL ) {
423 addrclip_set_index( _clipBoard_, _addressIndex_ );
425 if( _addressSelect_ == NULL ) {
426 _addressSelect_ = addrselect_list_create();
428 if (!addrbook.window) {
429 addressbook_read_file();
430 addressbook_create();
431 addressbook_load_tree();
432 gtk_ctree_select(GTK_CTREE(addrbook.ctree),
433 GTK_CTREE_NODE(GTK_CLIST(addrbook.ctree)->row_list));
436 gtk_widget_hide(addrbook.window);
439 gtk_widget_show_all(addrbook.window);
440 addressbook_set_target_compose(target);
443 void addressbook_destroy() {
444 /* Free up address stuff */
445 if( _addressSelect_ != NULL ) {
446 addrselect_list_free( _addressSelect_ );
448 if( _clipBoard_ != NULL ) {
449 addrclip_free( _clipBoard_ );
451 if( _addressIndex_ != NULL ) {
452 addrindex_free_index( _addressIndex_ );
454 _addressSelect_ = NULL;
456 _addressIndex_ = NULL;
459 void addressbook_set_target_compose(Compose *target)
461 addrbook.target_compose = target;
462 addressbook_button_set_sensitive();
465 Compose *addressbook_get_target_compose(void)
467 return addrbook.target_compose;
470 void addressbook_refresh(void)
472 if (addrbook.window) {
473 if (addrbook.treeSelected) {
474 gtk_ctree_select(GTK_CTREE(addrbook.ctree),
475 addrbook.treeSelected);
478 addressbook_export_to_file();
482 * Create the address book widgets. The address book contains two CTree widgets: the
483 * address index tree on the left and the address list on the right.
485 * The address index tree displays a hierarchy of interfaces and groups. Each node in
486 * this tree is linked to an address Adapter. Adapters have been created for interfaces,
487 * data sources and folder objects.
489 * The address list displays group, person and email objects. These items are linked
490 * directly to ItemGroup, ItemPerson and ItemEMail objects inside the address book data
493 * In the tradition of MVC architecture, the data stores have been separated from the
494 * GUI components. The addrindex.c file provides the interface to all data stores.
496 static void addressbook_create(void)
502 GtkWidget *ctree_swin;
504 GtkWidget *clist_vbox;
505 GtkWidget *clist_swin;
511 GtkWidget *statusbar;
520 GtkWidget *tree_popup;
521 GtkWidget *list_popup;
522 GtkItemFactory *tree_factory;
523 GtkItemFactory *list_factory;
524 GtkItemFactory *menu_factory;
528 gchar *titles[N_COLS];
532 debug_print("Creating addressbook window...\n");
534 titles[COL_NAME] = _("Name");
535 titles[COL_ADDRESS] = _("E-Mail address");
536 titles[COL_REMARKS] = _("Remarks");
538 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
539 gtk_window_set_title(GTK_WINDOW(window), _("Address book"));
540 gtk_widget_set_usize(window, ADDRESSBOOK_WIDTH, ADDRESSBOOK_HEIGHT);
541 gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, TRUE);
542 gtk_window_set_wmclass(GTK_WINDOW(window), "addressbook", "Sylpheed");
543 gtk_widget_realize(window);
545 gtk_signal_connect(GTK_OBJECT(window), "delete_event",
546 GTK_SIGNAL_FUNC(addressbook_close), NULL);
547 gtk_signal_connect(GTK_OBJECT(window), "key_press_event",
548 GTK_SIGNAL_FUNC(key_pressed), NULL);
549 MANAGE_WINDOW_SIGNALS_CONNECT(window);
551 vbox = gtk_vbox_new(FALSE, 0);
552 gtk_container_add(GTK_CONTAINER(window), vbox);
554 n_entries = sizeof(addressbook_entries) /
555 sizeof(addressbook_entries[0]);
556 menubar = menubar_create(window, addressbook_entries, n_entries,
557 "<AddressBook>", NULL);
558 gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0);
559 menu_factory = gtk_item_factory_from_widget(menubar);
561 vbox2 = gtk_vbox_new(FALSE, 4);
562 gtk_container_set_border_width(GTK_CONTAINER(vbox2), BORDER_WIDTH);
563 gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
565 ctree_swin = gtk_scrolled_window_new(NULL, NULL);
566 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ctree_swin),
567 GTK_POLICY_AUTOMATIC,
569 gtk_widget_set_usize(ctree_swin, COL_FOLDER_WIDTH + 40, -1);
572 ctree = gtk_ctree_new(1, 0);
573 gtk_container_add(GTK_CONTAINER(ctree_swin), ctree);
574 gtk_clist_set_selection_mode(GTK_CLIST(ctree), GTK_SELECTION_BROWSE);
575 gtk_clist_set_column_width(GTK_CLIST(ctree), 0, COL_FOLDER_WIDTH);
576 gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_DOTTED);
577 gtk_ctree_set_expander_style(GTK_CTREE(ctree),
578 GTK_CTREE_EXPANDER_SQUARE);
579 gtk_ctree_set_indent(GTK_CTREE(ctree), CTREE_INDENT);
580 gtk_clist_set_compare_func(GTK_CLIST(ctree),
581 addressbook_treenode_compare_func);
583 gtk_signal_connect(GTK_OBJECT(ctree), "tree_select_row",
584 GTK_SIGNAL_FUNC(addressbook_tree_selected), NULL);
585 gtk_signal_connect(GTK_OBJECT(ctree), "button_press_event",
586 GTK_SIGNAL_FUNC(addressbook_tree_button_pressed),
588 gtk_signal_connect(GTK_OBJECT(ctree), "button_release_event",
589 GTK_SIGNAL_FUNC(addressbook_tree_button_released),
592 clist_vbox = gtk_vbox_new(FALSE, 4);
594 clist_swin = gtk_scrolled_window_new(NULL, NULL);
595 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
596 GTK_POLICY_AUTOMATIC,
598 gtk_box_pack_start(GTK_BOX(clist_vbox), clist_swin, TRUE, TRUE, 0);
601 clist = gtk_ctree_new_with_titles(N_COLS, 0, titles);
602 gtk_container_add(GTK_CONTAINER(clist_swin), clist);
603 gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_EXTENDED);
604 gtk_ctree_set_line_style(GTK_CTREE(clist), GTK_CTREE_LINES_NONE);
605 gtk_ctree_set_expander_style(GTK_CTREE(clist), GTK_CTREE_EXPANDER_SQUARE);
606 gtk_ctree_set_indent(GTK_CTREE(clist), CTREE_INDENT);
607 gtk_clist_set_column_width(GTK_CLIST(clist), COL_NAME,
609 gtk_clist_set_column_width(GTK_CLIST(clist), COL_ADDRESS,
611 gtk_clist_set_compare_func(GTK_CLIST(clist),
612 addressbook_list_compare_func);
614 for (i = 0; i < N_COLS; i++)
615 GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button,
618 gtk_signal_connect(GTK_OBJECT(clist), "tree_select_row",
619 GTK_SIGNAL_FUNC(addressbook_list_row_selected), NULL);
620 gtk_signal_connect(GTK_OBJECT(clist), "tree_unselect_row",
621 GTK_SIGNAL_FUNC(addressbook_list_row_unselected), NULL);
622 gtk_signal_connect(GTK_OBJECT(clist), "button_press_event",
623 GTK_SIGNAL_FUNC(addressbook_list_button_pressed),
625 gtk_signal_connect(GTK_OBJECT(clist), "button_release_event",
626 GTK_SIGNAL_FUNC(addressbook_list_button_released),
628 gtk_signal_connect(GTK_OBJECT(clist), "select_row",
629 GTK_SIGNAL_FUNC(addressbook_list_selected), NULL);
630 gtk_signal_connect(GTK_OBJECT(clist), "tree_expand",
631 GTK_SIGNAL_FUNC(addressbook_person_expand_node), NULL );
632 gtk_signal_connect(GTK_OBJECT(clist), "tree_collapse",
633 GTK_SIGNAL_FUNC(addressbook_person_collapse_node), NULL );
635 hbox = gtk_hbox_new(FALSE, 4);
636 gtk_box_pack_start(GTK_BOX(clist_vbox), hbox, FALSE, FALSE, 0);
638 label = gtk_label_new(_("Name:"));
639 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
641 entry = gtk_entry_new();
642 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
644 address_completion_register_entry(GTK_ENTRY(entry));
645 gtk_signal_connect(GTK_OBJECT(entry), "focus_in_event",
646 GTK_SIGNAL_FUNC(addressbook_entry_gotfocus), NULL);
649 gtk_signal_connect(GTK_OBJECT(entry), "changed",
650 GTK_SIGNAL_FUNC(addressbook_entry_changed), NULL);
653 paned = gtk_hpaned_new();
654 gtk_box_pack_start(GTK_BOX(vbox2), paned, TRUE, TRUE, 0);
655 gtk_paned_add1(GTK_PANED(paned), ctree_swin);
656 gtk_paned_add2(GTK_PANED(paned), clist_vbox);
659 hsbox = gtk_hbox_new(FALSE, 0);
660 gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, BORDER_WIDTH);
661 statusbar = gtk_statusbar_new();
662 gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, BORDER_WIDTH);
665 hbbox = gtk_hbutton_box_new();
666 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox), GTK_BUTTONBOX_END);
667 gtk_button_box_set_spacing(GTK_BUTTON_BOX(hbbox), 2);
668 gtk_box_pack_end(GTK_BOX(vbox), hbbox, FALSE, FALSE, 0);
670 del_btn = gtk_button_new_with_label(_("Delete"));
671 GTK_WIDGET_SET_FLAGS(del_btn, GTK_CAN_DEFAULT);
672 gtk_box_pack_start(GTK_BOX(hbbox), del_btn, TRUE, TRUE, 0);
673 reg_btn = gtk_button_new_with_label(_("Add"));
674 GTK_WIDGET_SET_FLAGS(reg_btn, GTK_CAN_DEFAULT);
675 gtk_box_pack_start(GTK_BOX(hbbox), reg_btn, TRUE, TRUE, 0);
676 lup_btn = gtk_button_new_with_label(_("Lookup"));
677 GTK_WIDGET_SET_FLAGS(lup_btn, GTK_CAN_DEFAULT);
678 gtk_box_pack_start(GTK_BOX(hbbox), lup_btn, TRUE, TRUE, 0);
680 gtk_signal_connect(GTK_OBJECT(del_btn), "clicked",
681 GTK_SIGNAL_FUNC(addressbook_del_clicked), NULL);
682 gtk_signal_connect(GTK_OBJECT(reg_btn), "clicked",
683 GTK_SIGNAL_FUNC(addressbook_reg_clicked), NULL);
684 gtk_signal_connect(GTK_OBJECT(lup_btn), "clicked",
685 GTK_SIGNAL_FUNC(addressbook_lup_clicked), NULL);
687 to_btn = gtk_button_new_with_label
688 (prefs_common.trans_hdr ? _("To:") : "To:");
689 GTK_WIDGET_SET_FLAGS(to_btn, GTK_CAN_DEFAULT);
690 gtk_box_pack_start(GTK_BOX(hbbox), to_btn, TRUE, TRUE, 0);
691 cc_btn = gtk_button_new_with_label
692 (prefs_common.trans_hdr ? _("Cc:") : "Cc:");
693 GTK_WIDGET_SET_FLAGS(cc_btn, GTK_CAN_DEFAULT);
694 gtk_box_pack_start(GTK_BOX(hbbox), cc_btn, TRUE, TRUE, 0);
695 bcc_btn = gtk_button_new_with_label
696 (prefs_common.trans_hdr ? _("Bcc:") : "Bcc:");
697 GTK_WIDGET_SET_FLAGS(bcc_btn, GTK_CAN_DEFAULT);
698 gtk_box_pack_start(GTK_BOX(hbbox), bcc_btn, TRUE, TRUE, 0);
700 gtk_signal_connect(GTK_OBJECT(to_btn), "clicked",
701 GTK_SIGNAL_FUNC(addressbook_to_clicked),
702 GINT_TO_POINTER(COMPOSE_TO));
703 gtk_signal_connect(GTK_OBJECT(cc_btn), "clicked",
704 GTK_SIGNAL_FUNC(addressbook_to_clicked),
705 GINT_TO_POINTER(COMPOSE_CC));
706 gtk_signal_connect(GTK_OBJECT(bcc_btn), "clicked",
707 GTK_SIGNAL_FUNC(addressbook_to_clicked),
708 GINT_TO_POINTER(COMPOSE_BCC));
710 /* Build icons for interface */
711 stock_pixmap_gdk( window, STOCK_PIXMAP_INTERFACE,
712 &interfacexpm, &interfacexpmmask );
714 /* Build control tables */
715 addrbookctl_build_map(window);
716 addrbookctl_build_iflist();
717 addrbookctl_build_ifselect();
719 /* Add each interface into the tree as a root level folder */
720 nodeIf = _addressInterfaceList_;
722 AdapterInterface *adapter = nodeIf->data;
723 AddressInterface *iface = adapter->interface;
724 nodeIf = g_list_next(nodeIf);
726 if(iface->useInterface) {
727 AddressTypeControlItem *atci = adapter->atci;
728 text = atci->displayName;
730 gtk_ctree_insert_node( GTK_CTREE(ctree),
731 NULL, NULL, &text, FOLDER_SPACING,
732 interfacexpm, interfacexpmmask,
733 interfacexpm, interfacexpmmask,
735 menu_set_sensitive( menu_factory, atci->menuCommand, adapter->haveLibrary );
736 gtk_ctree_node_set_row_data_full(
737 GTK_CTREE(ctree), adapter->treeNode, adapter,
738 addressbook_free_treenode );
743 n_entries = sizeof(addressbook_tree_popup_entries) /
744 sizeof(addressbook_tree_popup_entries[0]);
745 tree_popup = menu_create_items(addressbook_tree_popup_entries,
747 "<AddressBookTree>", &tree_factory,
749 gtk_signal_connect(GTK_OBJECT(tree_popup), "selection_done",
750 GTK_SIGNAL_FUNC(addressbook_popup_close), NULL);
751 n_entries = sizeof(addressbook_list_popup_entries) /
752 sizeof(addressbook_list_popup_entries[0]);
753 list_popup = menu_create_items(addressbook_list_popup_entries,
755 "<AddressBookList>", &list_factory,
758 addrbook.window = window;
759 addrbook.menubar = menubar;
760 addrbook.ctree = ctree;
761 addrbook.clist = clist;
762 addrbook.entry = entry;
763 addrbook.statusbar = statusbar;
764 addrbook.status_cid = gtk_statusbar_get_context_id(
765 GTK_STATUSBAR(statusbar), "Addressbook Window" );
767 addrbook.del_btn = del_btn;
768 addrbook.reg_btn = reg_btn;
769 addrbook.lup_btn = lup_btn;
770 addrbook.to_btn = to_btn;
771 addrbook.cc_btn = cc_btn;
772 addrbook.bcc_btn = bcc_btn;
774 addrbook.tree_popup = tree_popup;
775 addrbook.list_popup = list_popup;
776 addrbook.tree_factory = tree_factory;
777 addrbook.list_factory = list_factory;
778 addrbook.menu_factory = menu_factory;
780 addrbook.listSelected = NULL;
781 address_completion_start(window);
782 gtk_widget_show_all(window);
786 static gint addressbook_close( void ) {
787 gtk_widget_hide(addrbook.window);
788 addressbook_export_to_file();
792 static void addressbook_status_show( gchar *msg ) {
793 if( addrbook.statusbar != NULL ) {
795 GTK_STATUSBAR(addrbook.statusbar),
796 addrbook.status_cid );
799 GTK_STATUSBAR(addrbook.statusbar),
800 addrbook.status_cid, msg );
805 static void addressbook_ds_status_message( AddressDataSource *ds, gchar *msg ) {
806 *addressbook_msgbuf = '\0';
810 name = addrindex_ds_get_name( ds );
811 sprintf( addressbook_msgbuf, "%s: %s", name, msg );
814 sprintf( addressbook_msgbuf, "%s", msg );
816 addressbook_status_show( addressbook_msgbuf );
819 static void addressbook_ds_show_message( AddressDataSource *ds ) {
822 *addressbook_msgbuf = '\0';
824 name = addrindex_ds_get_name( ds );
825 retVal = addrindex_ds_get_status_code( ds );
826 if( retVal == MGU_SUCCESS ) {
827 sprintf( addressbook_msgbuf, "%s", name );
830 sprintf( addressbook_msgbuf, "%s: %s", name,
831 mgu_error2string( retVal ) );
834 addressbook_status_show( addressbook_msgbuf );
837 static void addressbook_button_set_sensitive(void)
839 gboolean to_sens = FALSE;
840 gboolean cc_sens = FALSE;
841 gboolean bcc_sens = FALSE;
843 if (!addrbook.window) return;
845 if (addrbook.target_compose) {
849 if (addrbook.target_compose->use_bcc)
854 gtk_widget_set_sensitive(addrbook.to_btn, to_sens);
855 gtk_widget_set_sensitive(addrbook.cc_btn, cc_sens);
856 gtk_widget_set_sensitive(addrbook.bcc_btn, bcc_sens);
860 * Delete one or more objects from address list.
862 static void addressbook_del_clicked(GtkButton *button, gpointer data)
864 GtkCTree *clist = GTK_CTREE(addrbook.clist);
865 GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
867 AdapterDSource *ads = NULL;
868 GtkCTreeNode *nodeList;
871 AddressBookFile *abf = NULL;
872 AddressDataSource *ds = NULL;
873 AddressInterface *iface;
875 AddrSelectItem *item;
878 pobj = gtk_ctree_node_get_row_data(ctree, addrbook.opened );
879 g_return_if_fail(pobj != NULL);
881 /* Test whether anything selected for deletion */
882 nodeList = addrbook.listSelected;
883 aio = gtk_ctree_node_get_row_data( clist, nodeList );
884 if( aio == NULL) return;
885 ds = addressbook_find_datasource( addrbook.treeSelected );
886 if( ds == NULL ) return;
888 /* Test for read only */
889 iface = ds->interface;
890 if( iface->readOnly ) {
891 alertpanel( _("Delete address(es)"),
892 _("This address data is readonly and cannot be deleted."),
893 _("Close"), NULL, NULL );
897 /* Test whether Ok to proceed */
899 if( pobj->type == ADDR_DATASOURCE ) {
900 ads = ADAPTER_DSOURCE(pobj);
901 if( ads->subType == ADDR_BOOK ) procFlag = TRUE;
903 else if( pobj->type == ADDR_ITEM_FOLDER ) {
906 else if( pobj->type == ADDR_ITEM_GROUP ) {
909 if( ! procFlag ) return;
910 abf = ds->rawDataSource;
911 if( abf == NULL ) return;
913 /* Confirm deletion */
914 aval = alertpanel( _("Delete address(es)"),
915 _("Really delete the address(es)?"),
916 _("Yes"), _("No"), NULL );
917 if( aval != G_ALERTDEFAULT ) return;
919 /* Process deletions */
920 if( pobj->type == ADDR_DATASOURCE || pobj->type == ADDR_ITEM_FOLDER ) {
921 /* Items inside folders */
922 list = addrselect_get_list( _addressSelect_ );
926 node = g_list_next( node );
927 aio = ( AddrItemObject * ) item->addressItem;
928 if( aio->type == ADDR_ITEM_GROUP ) {
929 ItemGroup *item = ( ItemGroup * ) aio;
930 GtkCTreeNode *nd = NULL;
932 nd = addressbook_find_group_node( addrbook.opened, item );
933 item = addrbook_remove_group( abf, item );
935 addritem_free_item_group( item );
937 /* Remove group from parent node */
938 gtk_ctree_remove_node( ctree, nd );
940 else if( aio->type == ADDR_ITEM_PERSON ) {
941 ItemPerson *item = ( ItemPerson * ) aio;
942 item = addrbook_remove_person( abf, item );
944 addritem_free_item_person( item );
947 else if( aio->type == ADDR_ITEM_EMAIL ) {
948 ItemEMail *item = ( ItemEMail * ) aio;
949 ItemPerson *person = ( ItemPerson * ) ADDRITEM_PARENT(item);
950 item = addrbook_person_remove_email( abf, person, item );
952 addritem_free_item_email( item );
957 addressbook_list_select_clear();
958 gtk_ctree_select( ctree, addrbook.opened);
961 else if( pobj->type == ADDR_ITEM_GROUP ) {
962 /* Items inside groups */
963 list = addrselect_get_list( _addressSelect_ );
967 node = g_list_next( node );
968 aio = ( AddrItemObject * ) item->addressItem;
969 if( aio->type == ADDR_ITEM_EMAIL ) {
970 ItemEMail *item = ( ItemEMail * ) aio;
971 ItemPerson *person = ( ItemPerson * ) ADDRITEM_PARENT(item);
972 item = addrbook_person_remove_email( abf, person, item );
974 addritem_free_item_email( item );
979 addressbook_list_select_clear();
980 gtk_ctree_select( ctree, addrbook.opened);
984 gtk_ctree_node_set_row_data( clist, nodeList, NULL );
985 gtk_ctree_remove_node( clist, nodeList );
989 static void addressbook_reg_clicked(GtkButton *button, gpointer data)
991 addressbook_new_address_cb( NULL, 0, NULL );
994 gchar *addressbook_format_address( AddrItemObject * aio ) {
997 gchar *address = NULL;
999 if( aio->type == ADDR_ITEM_EMAIL ) {
1000 ItemPerson *person = NULL;
1001 ItemEMail *email = ( ItemEMail * ) aio;
1003 person = ( ItemPerson * ) ADDRITEM_PARENT(email);
1004 if( email->address ) {
1005 if( ADDRITEM_NAME(email) ) {
1006 name = ADDRITEM_NAME(email);
1007 if( *name == '\0' ) {
1008 name = ADDRITEM_NAME(person);
1011 else if( ADDRITEM_NAME(person) ) {
1012 name = ADDRITEM_NAME(person);
1015 buf = g_strdup( email->address );
1017 address = email->address;
1020 else if( aio->type == ADDR_ITEM_PERSON ) {
1021 ItemPerson *person = ( ItemPerson * ) aio;
1022 GList *node = person->listEMail;
1024 name = ADDRITEM_NAME(person);
1026 ItemEMail *email = ( ItemEMail * ) node->data;
1027 address = email->address;
1031 if( name && name[0] != '\0' ) {
1032 if( strchr_with_skip_quote( name, '"', ',' ) )
1033 buf = g_strdup_printf( "\"%s\" <%s>", name, address );
1035 buf = g_strdup_printf( "%s <%s>", name, address );
1038 buf = g_strdup( address );
1045 static void addressbook_to_clicked(GtkButton *button, gpointer data)
1049 AddrSelectItem *item;
1050 AddrItemObject *aio;
1053 compose = addrbook.target_compose;
1054 if( ! compose ) return;
1056 /* Nothing selected, but maybe there is something in text entry */
1057 if ( list == NULL ) {
1058 addr = gtk_entry_get_text( GTK_ENTRY( addrbook.entry) );
1060 compose_entry_append(
1061 compose, addr, (ComposeEntryType)data );
1065 /* Select from address list */
1066 list = addrselect_get_list( _addressSelect_ );
1070 node = g_list_next( node );
1071 aio = item->addressItem;
1072 if( aio->type == ADDR_ITEM_PERSON ||
1073 aio->type == ADDR_ITEM_EMAIL ) {
1074 addr = addressbook_format_address( aio );
1075 compose_entry_append(
1076 compose, addr, (ComposeEntryType) data );
1079 else if( aio->type == ADDR_ITEM_GROUP ) {
1080 ItemGroup *group = ( ItemGroup * ) aio;
1081 GList *nodeMail = group->listEMail;
1083 ItemEMail *email = nodeMail->data;
1085 addr = addressbook_format_address(
1086 ( AddrItemObject * ) email );
1087 compose_entry_append(
1088 compose, addr, (ComposeEntryType) data );
1090 nodeMail = g_list_next( nodeMail );
1094 g_list_free( list );
1097 static void addressbook_menubar_set_sensitive( gboolean sensitive ) {
1098 menu_set_sensitive( addrbook.menu_factory, "/File/Edit", sensitive );
1099 menu_set_sensitive( addrbook.menu_factory, "/File/Delete", sensitive );
1101 menu_set_sensitive( addrbook.menu_factory, "/Edit/Cut", sensitive );
1102 menu_set_sensitive( addrbook.menu_factory, "/Edit/Copy", sensitive );
1103 menu_set_sensitive( addrbook.menu_factory, "/Edit/Paste", sensitive );
1104 menu_set_sensitive( addrbook.menu_factory, "/Edit/Paste Address", sensitive );
1106 menu_set_sensitive( addrbook.menu_factory, "/Address/New Address", sensitive );
1107 menu_set_sensitive( addrbook.menu_factory, "/Address/New Group", sensitive );
1108 menu_set_sensitive( addrbook.menu_factory, "/Address/New Folder", sensitive );
1109 gtk_widget_set_sensitive( addrbook.reg_btn, sensitive );
1110 gtk_widget_set_sensitive( addrbook.del_btn, sensitive );
1113 static void addressbook_menuitem_set_sensitive( AddressObject *obj, GtkCTreeNode *node ) {
1114 gboolean canEdit = FALSE;
1115 gboolean canAdd = FALSE;
1116 gboolean canEditTr = TRUE;
1117 gboolean editAddress = FALSE;
1118 gboolean canExport = TRUE;
1119 AddressTypeControlItem *atci = NULL;
1120 AddressDataSource *ds = NULL;
1121 AddressInterface *iface = NULL;
1123 if( obj == NULL ) return;
1124 if( obj->type == ADDR_INTERFACE ) {
1125 AdapterInterface *adapter = ADAPTER_INTERFACE(obj);
1126 iface = adapter->interface;
1128 if( iface->haveLibrary ) {
1129 /* Enable appropriate File / New command */
1130 atci = adapter->atci;
1131 menu_set_sensitive( addrbook.menu_factory, atci->menuCommand, TRUE );
1134 canEditTr = canExport = FALSE;
1136 else if( obj->type == ADDR_DATASOURCE ) {
1137 AdapterDSource *ads = ADAPTER_DSOURCE(obj);
1138 ds = ads->dataSource;
1139 iface = ds->interface;
1140 if( ! iface->readOnly ) {
1141 canAdd = canEdit = editAddress = TRUE;
1143 if( ! iface->haveLibrary ) {
1144 canAdd = canEdit = editAddress = canExport = FALSE;
1147 else if( obj->type == ADDR_ITEM_FOLDER ) {
1148 ds = addressbook_find_datasource( addrbook.treeSelected );
1150 iface = ds->interface;
1151 if( iface->readOnly ) {
1155 canAdd = editAddress = TRUE;
1159 else if( obj->type == ADDR_ITEM_GROUP ) {
1160 ds = addressbook_find_datasource( addrbook.treeSelected );
1162 iface = ds->interface;
1163 if( ! iface->readOnly ) {
1169 if( addrbook.listSelected == NULL ) canEdit = FALSE;
1172 menu_set_sensitive( addrbook.menu_factory, "/Address/New Address", editAddress );
1173 menu_set_sensitive( addrbook.menu_factory, "/Address/New Group", canAdd );
1174 menu_set_sensitive( addrbook.menu_factory, "/Address/New Folder", canAdd );
1175 gtk_widget_set_sensitive( addrbook.reg_btn, editAddress );
1178 menu_set_sensitive( addrbook.menu_factory, "/Address/Edit", canEdit );
1179 menu_set_sensitive( addrbook.menu_factory, "/Address/Delete", canEdit );
1180 gtk_widget_set_sensitive( addrbook.del_btn, canEdit );
1182 menu_set_sensitive( addrbook.menu_factory, "/File/Edit", canEditTr );
1183 menu_set_sensitive( addrbook.menu_factory, "/File/Delete", canEditTr );
1186 menu_set_sensitive( addrbook.menu_factory, "/Tools/Export HTML...", canExport );
1189 static void addressbook_tree_selected(GtkCTree *ctree, GtkCTreeNode *node,
1190 gint column, gpointer data)
1192 AddressObject *obj = NULL;
1193 AdapterDSource *ads = NULL;
1194 AddressDataSource *ds = NULL;
1195 ItemFolder *rootFolder = NULL;
1197 addrbook.treeSelected = node;
1198 addrbook.listSelected = NULL;
1199 addressbook_status_show( "" );
1200 if( addrbook.entry != NULL ) gtk_entry_set_text(GTK_ENTRY(addrbook.entry), "");
1202 if( addrbook.clist ) gtk_clist_clear( GTK_CLIST(addrbook.clist) );
1203 if( node ) obj = gtk_ctree_node_get_row_data( ctree, node );
1204 if( obj == NULL ) return;
1206 addrbook.opened = node;
1208 if( obj->type == ADDR_DATASOURCE ) {
1209 /* Read from file */
1210 static gboolean tVal = TRUE;
1212 ads = ADAPTER_DSOURCE(obj);
1213 if( ads == NULL ) return;
1214 ds = ads->dataSource;
1215 if( ds == NULL ) return;
1217 if( addrindex_ds_get_modify_flag( ds ) ) {
1218 addrindex_ds_read_data( ds );
1221 if( ! addrindex_ds_get_read_flag( ds ) ) {
1222 addrindex_ds_read_data( ds );
1224 addressbook_ds_show_message( ds );
1226 if( ! addrindex_ds_get_access_flag( ds ) ) {
1227 /* Remove existing folders and groups */
1228 gtk_clist_freeze( GTK_CLIST(ctree) );
1229 addressbook_tree_remove_children( ctree, node );
1230 gtk_clist_thaw( GTK_CLIST(ctree) );
1232 /* Load folders into the tree */
1233 rootFolder = addrindex_ds_get_root_folder( ds );
1234 if( ds->type == ADDR_IF_JPILOT ) {
1235 addressbook_node_add_folder( node, ds, rootFolder, ADDR_CATEGORY );
1238 addressbook_node_add_folder( node, ds, rootFolder, ADDR_ITEM_FOLDER );
1240 addrindex_ds_set_access_flag( ds, &tVal );
1241 gtk_ctree_expand( ctree, node );
1245 /* Update address list */
1246 addressbook_set_clist( obj );
1248 /* Setup main menu selections */
1249 addressbook_menubar_set_sensitive( FALSE );
1250 addressbook_menuitem_set_sensitive( obj, node );
1252 addressbook_list_select_clear();
1256 * Setup address list popup menu.
1257 * Enter: pobj Parent address object in address tree.
1258 * obj Address object in address list.
1260 static void addressbook_list_menu_setup( void ) {
1261 GtkCTree *clist = NULL;
1262 AddressObject *pobj = NULL;
1263 AddressObject *obj = NULL;
1264 AdapterDSource *ads = NULL;
1265 AddressInterface *iface = NULL;
1266 AddressDataSource *ds = NULL;
1267 gboolean canEdit = FALSE;
1268 gboolean canDelete = FALSE;
1269 gboolean canCut = FALSE;
1270 gboolean canCopy = FALSE;
1271 gboolean canPaste = FALSE;
1273 pobj = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), addrbook.treeSelected );
1274 if( pobj == NULL ) return;
1276 clist = GTK_CTREE(addrbook.clist);
1277 obj = gtk_ctree_node_get_row_data( clist, addrbook.listSelected );
1278 if( obj == NULL ) canEdit = FALSE;
1280 menu_set_insensitive_all( GTK_MENU_SHELL(addrbook.list_popup) );
1282 if( pobj->type == ADDR_DATASOURCE ) {
1283 ads = ADAPTER_DSOURCE(pobj);
1284 ds = ads->dataSource;
1285 iface = ds->interface;
1286 if( ! iface->readOnly ) {
1287 menu_set_sensitive( addrbook.list_factory, "/New Address", TRUE );
1288 menu_set_sensitive( addrbook.list_factory, "/New Folder", TRUE );
1289 menu_set_sensitive( addrbook.list_factory, "/New Group", TRUE );
1290 gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
1291 if( ! addrclip_is_empty( _clipBoard_ ) ) canPaste = TRUE;
1292 if( ! addrselect_test_empty( _addressSelect_ ) ) canCut = TRUE;
1293 if( obj ) canEdit = TRUE;
1296 else if( pobj->type != ADDR_INTERFACE ) {
1297 ds = addressbook_find_datasource( addrbook.treeSelected );
1298 iface = ds->interface;
1299 if( ! iface->readOnly ) {
1300 if( pobj->type == ADDR_ITEM_FOLDER || pobj->type == ADDR_ITEM_GROUP ) {
1301 menu_set_sensitive( addrbook.list_factory, "/New Address", TRUE );
1302 gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
1303 if( obj ) canEdit = TRUE;
1305 if( pobj->type == ADDR_ITEM_FOLDER ) {
1306 menu_set_sensitive( addrbook.list_factory, "/New Folder", TRUE );
1307 menu_set_sensitive( addrbook.list_factory, "/New Group", TRUE );
1308 if( obj ) canEdit = TRUE;
1310 if( ! addrclip_is_empty( _clipBoard_ ) ) canPaste = TRUE;
1311 if( ! addrselect_test_empty( _addressSelect_ ) ) canCut = TRUE;
1314 if( ! addrselect_test_empty( _addressSelect_ ) ) canCopy = TRUE;
1316 canDelete = canEdit;
1317 canDelete = canEdit;
1319 /* Disable edit if more than one row selected */
1320 if( GTK_CLIST(clist)->selection && GTK_CLIST(clist)->selection->next ) canEdit = FALSE;
1322 menu_set_sensitive( addrbook.list_factory, "/Edit", canEdit );
1323 menu_set_sensitive( addrbook.list_factory, "/Delete", canDelete );
1325 menu_set_sensitive( addrbook.list_factory, "/Cut", canCut );
1326 menu_set_sensitive( addrbook.list_factory, "/Copy", canCopy );
1327 menu_set_sensitive( addrbook.list_factory, "/Paste", canPaste );
1328 menu_set_sensitive( addrbook.list_factory, "/Paste Address", canPaste );
1330 menu_set_sensitive( addrbook.menu_factory, "/Edit/Cut", canCut );
1331 menu_set_sensitive( addrbook.menu_factory, "/Edit/Copy", canCopy );
1332 menu_set_sensitive( addrbook.menu_factory, "/Edit/Paste", canPaste );
1333 menu_set_sensitive( addrbook.menu_factory, "/Edit/Paste Address", canPaste );
1335 menu_set_sensitive( addrbook.tree_factory, "/Cut", canCut );
1336 menu_set_sensitive( addrbook.tree_factory, "/Copy", canCopy );
1337 menu_set_sensitive( addrbook.tree_factory, "/Paste", canPaste );
1339 menu_set_sensitive( addrbook.menu_factory, "/Address/Edit", canEdit );
1340 menu_set_sensitive( addrbook.menu_factory, "/Address/Delete", canDelete );
1342 gtk_widget_set_sensitive( addrbook.del_btn, canDelete );
1345 static void addressbook_list_selected(GtkCList *clist, gint row, gint column,
1346 GdkEvent *event, gpointer data)
1348 if (event && event->type == GDK_2BUTTON_PRESS) {
1349 /* Handle double click */
1350 if (prefs_common.add_address_by_click &&
1351 addrbook.target_compose)
1352 addressbook_to_clicked(NULL, NULL);
1354 addressbook_edit_address_cb(NULL, 0, NULL);
1359 * Add list of items into tree node below specified tree node.
1360 * Enter: treeNode Tree node.
1362 * listItems List of items.
1364 static void addressbook_treenode_add_list(
1365 GtkCTreeNode *treeNode, AddressDataSource *ds, GList *listItems )
1371 AddrItemObject *aio;
1375 if( ADDRESS_OBJECT_TYPE(aio) == ITEMTYPE_GROUP ) {
1378 group = ( ItemGroup * ) aio;
1379 nn = addressbook_node_add_group( treeNode, ds, group );
1381 else if( ADDRESS_OBJECT_TYPE(aio) == ITEMTYPE_FOLDER ) {
1384 folder = ( ItemFolder * ) aio;
1385 nn = addressbook_node_add_folder(
1386 treeNode, ds, folder, ADDR_ITEM_FOLDER );
1388 node = g_list_next( node );
1393 * Cut from address list widget.
1395 static void addressbook_clip_cut_cb( void ) {
1396 _clipBoard_->cutFlag = TRUE;
1397 addrclip_clear( _clipBoard_ );
1398 addrclip_add( _clipBoard_, _addressSelect_ );
1399 /* addrclip_list_show( _clipBoard_, stdout ); */
1403 * Copy from address list widget.
1405 static void addressbook_clip_copy_cb( void ) {
1406 _clipBoard_->cutFlag = FALSE;
1407 addrclip_clear( _clipBoard_ );
1408 addrclip_add( _clipBoard_, _addressSelect_ );
1409 /* addrclip_list_show( _clipBoard_, stdout ); */
1413 * Paste clipboard into address list widget.
1415 static void addressbook_clip_paste_cb( void ) {
1416 GtkCTree *ctree = GTK_CTREE( addrbook.ctree );
1417 AddressObject *pobj = NULL;
1418 AddressDataSource *ds = NULL;
1419 AddressBookFile *abf = NULL;
1420 ItemFolder *folder = NULL;
1421 GList *folderGroup = NULL;
1423 ds = addressbook_find_datasource( GTK_CTREE_NODE(addrbook.treeSelected) );
1424 if( ds == NULL ) return;
1425 if( addrindex_ds_get_readonly( ds ) ) {
1426 addressbook_ds_status_message(
1427 ds, _( "Cannot paste. Target address book is readonly." ) );
1431 pobj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
1433 if( pobj->type == ADDR_ITEM_FOLDER ) {
1434 folder = ADAPTER_FOLDER(pobj)->itemFolder;
1436 else if( pobj->type == ADDR_ITEM_GROUP ) {
1437 addressbook_ds_status_message(
1438 ds, _( "Cannot paste into an address group." ) );
1443 /* Get an address book */
1444 abf = addressbook_get_book_file();
1445 if( abf == NULL ) return;
1447 if( _clipBoard_->cutFlag ) {
1449 folderGroup = addrclip_paste_cut( _clipBoard_, abf, folder );
1451 /* Remove all groups and folders in clipboard from tree node */
1452 addressbook_treenode_remove_item();
1454 /* Remove all "cut" items */
1455 addrclip_delete_item( _clipBoard_ );
1457 /* Clear clipboard - cut items??? */
1458 addrclip_clear( _clipBoard_ );
1462 folderGroup = addrclip_paste_copy( _clipBoard_, abf, folder );
1465 /* addrclip_list_show( _clipBoard_, stdout ); */
1467 /* Update tree by inserting node for each folder or group */
1468 addressbook_treenode_add_list(
1469 addrbook.treeSelected, ds, folderGroup );
1470 gtk_ctree_expand( ctree, addrbook.treeSelected );
1471 g_list_free( folderGroup );
1475 /* Display items pasted */
1476 gtk_ctree_select( ctree, addrbook.opened );
1481 * Paste clipboard email addresses only into address list widget.
1483 static void addressbook_clip_paste_address_cb( void ) {
1484 GtkCTree *clist = GTK_CTREE(addrbook.clist);
1486 AddressObject *pobj = NULL;
1487 AddressDataSource *ds = NULL;
1488 AddressBookFile *abf = NULL;
1489 ItemFolder *folder = NULL;
1490 AddrItemObject *aio;
1493 if( addrbook.listSelected == NULL ) return;
1495 ctree = GTK_CTREE( addrbook.ctree );
1496 ds = addressbook_find_datasource( GTK_CTREE_NODE(addrbook.treeSelected) );
1497 if( ds == NULL ) return;
1498 if( addrindex_ds_get_readonly( ds ) ) {
1499 addressbook_ds_status_message(
1500 ds, _( "Cannot paste. Target address book is readonly." ) );
1504 pobj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
1506 if( pobj->type == ADDR_ITEM_FOLDER ) {
1507 folder = ADAPTER_FOLDER(pobj)->itemFolder;
1511 abf = addressbook_get_book_file();
1512 if( abf == NULL ) return;
1515 aio = gtk_ctree_node_get_row_data( clist, addrbook.listSelected );
1516 if( aio->type == ADDR_ITEM_PERSON ) {
1519 person = ( ItemPerson * ) aio;
1520 if( _clipBoard_->cutFlag ) {
1522 cnt = addrclip_paste_person_cut( _clipBoard_, abf, person );
1524 /* Remove all "cut" items */
1525 addrclip_delete_address( _clipBoard_ );
1527 /* Clear clipboard */
1528 addrclip_clear( _clipBoard_ );
1532 cnt = addrclip_paste_person_copy( _clipBoard_, abf, person );
1535 addritem_person_set_opened( person, TRUE );
1539 /* Display items pasted */
1541 gtk_ctree_select( ctree, addrbook.opened );
1546 * Add current treenode object to clipboard. Note that widget only allows
1547 * one entry from the tree list to be selected.
1549 static void addressbook_treenode_to_clipboard( void ) {
1550 AddressObject *obj = NULL;
1551 AddressDataSource *ds = NULL;
1552 AddrSelectItem *item;
1553 GtkCTree *ctree = GTK_CTREE( addrbook.ctree );
1556 node = addrbook.treeSelected;
1557 if( node == NULL ) return;
1558 obj = gtk_ctree_node_get_row_data( ctree, node );
1559 if( obj == NULL ) return;
1561 ds = addressbook_find_datasource( node );
1562 if( ds == NULL ) return;
1565 if( obj->type == ADDR_ITEM_FOLDER ) {
1566 AdapterFolder *adapter = ADAPTER_FOLDER(obj);
1567 ItemFolder *folder = adapter->itemFolder;
1569 item = addrselect_create_node( obj );
1570 item->uid = g_strdup( ADDRITEM_ID(folder) );
1572 else if( obj->type == ADDR_ITEM_GROUP ) {
1573 AdapterGroup *adapter = ADAPTER_GROUP(obj);
1574 ItemGroup *group = adapter->itemGroup;
1576 item = addrselect_create_node( obj );
1577 item->uid = g_strdup( ADDRITEM_ID(group) );
1579 else if( obj->type == ADDR_DATASOURCE ) {
1581 item = addrselect_create_node( obj );
1586 /* Clear existing list and add item into list */
1589 addressbook_list_select_clear();
1590 cacheID = addrindex_get_cache_id( _addressIndex_, ds );
1591 addrselect_list_add( _addressSelect_, item, cacheID );
1597 * Cut from tree widget.
1599 static void addressbook_treenode_cut_cb( void ) {
1600 _clipBoard_->cutFlag = TRUE;
1601 addressbook_treenode_to_clipboard();
1602 addrclip_clear( _clipBoard_ );
1603 addrclip_add( _clipBoard_, _addressSelect_ );
1604 /* addrclip_list_show( _clipBoard_, stdout ); */
1608 * Copy from tree widget.
1610 static void addressbook_treenode_copy_cb( void ) {
1611 _clipBoard_->cutFlag = FALSE;
1612 addressbook_treenode_to_clipboard();
1613 addrclip_clear( _clipBoard_ );
1614 addrclip_add( _clipBoard_, _addressSelect_ );
1615 /* addrclip_list_show( _clipBoard_, stdout ); */
1619 * Paste clipboard into address tree widget.
1621 static void addressbook_treenode_paste_cb( void ) {
1622 addressbook_clip_paste_cb();
1625 static void addressbook_list_select_clear( void ) {
1626 addrselect_list_clear( _addressSelect_ );
1629 static void addressbook_list_select_add( AddrItemObject *aio, AddressDataSource *ds ) {
1632 if( ds == NULL ) return;
1633 cacheID = addrindex_get_cache_id( _addressIndex_, ds );
1634 addrselect_list_add_obj( _addressSelect_, aio, cacheID );
1638 static void addressbook_list_select_remove( AddrItemObject *aio ) {
1639 addrselect_list_remove( _addressSelect_, aio );
1642 static void addressbook_list_row_selected( GtkCTree *clist,
1647 GtkEntry *entry = GTK_ENTRY(addrbook.entry);
1648 AddrItemObject *aio = NULL;
1649 AddressObject *pobj = NULL;
1650 AdapterDSource *ads = NULL;
1651 AddressDataSource *ds = NULL;
1653 gtk_entry_set_text( entry, "" );
1654 addrbook.listSelected = node;
1656 pobj = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), addrbook.treeSelected );
1657 if( pobj == NULL ) return;
1659 if( pobj->type == ADDR_DATASOURCE ) {
1660 ads = ADAPTER_DSOURCE(pobj);
1661 ds = ads->dataSource;
1663 else if( pobj->type != ADDR_INTERFACE ) {
1664 ds = addressbook_find_datasource( addrbook.treeSelected );
1667 aio = gtk_ctree_node_get_row_data( clist, node );
1669 /* printf( "list select: %d : '%s'\n", aio->type, aio->name ); */
1670 addressbook_list_select_add( aio, ds );
1673 addressbook_list_menu_setup();
1676 static void addressbook_list_row_unselected( GtkCTree *ctree,
1681 AddrItemObject *aio;
1683 aio = gtk_ctree_node_get_row_data( ctree, node );
1685 /* printf( "list unselect: %d : '%s'\n", aio->type, aio->name ); */
1686 addressbook_list_select_remove( aio );
1690 static void addressbook_entry_gotfocus( GtkWidget *widget ) {
1691 gtk_editable_select_region( GTK_EDITABLE(addrbook.entry), 0, -1 );
1694 static void addressbook_list_button_pressed(GtkWidget *widget,
1695 GdkEventButton *event,
1698 if( ! event ) return;
1700 addressbook_list_menu_setup();
1702 if( event->button == 3 ) {
1703 gtk_menu_popup( GTK_MENU(addrbook.list_popup), NULL, NULL, NULL, NULL,
1704 event->button, event->time );
1708 static void addressbook_list_button_released(GtkWidget *widget,
1709 GdkEventButton *event,
1714 static void addressbook_tree_button_pressed(GtkWidget *ctree,
1715 GdkEventButton *event,
1718 GtkCList *clist = GTK_CLIST(ctree);
1720 AddressObject *obj = NULL;
1721 AdapterDSource *ads = NULL;
1722 AddressInterface *iface = NULL;
1723 AddressDataSource *ds = NULL;
1724 gboolean canEdit = FALSE;
1725 gboolean canCut = FALSE;
1726 gboolean canCopy = FALSE;
1727 gboolean canPaste = FALSE;
1728 gboolean canTreeCut = FALSE;
1729 gboolean canTreeCopy = FALSE;
1730 gboolean canTreePaste = FALSE;
1732 if( ! event ) return;
1733 addressbook_menubar_set_sensitive( FALSE );
1735 if( gtk_clist_get_selection_info( clist, event->x, event->y, &row, &column ) ) {
1736 gtk_clist_select_row( clist, row, column );
1737 gtkut_clist_set_focus_row(clist, row);
1738 obj = gtk_clist_get_row_data( clist, row );
1741 menu_set_insensitive_all(GTK_MENU_SHELL(addrbook.tree_popup));
1743 if( obj == NULL ) return;
1745 if( ! addrclip_is_empty( _clipBoard_ ) ) {
1746 canTreePaste = TRUE;
1749 if (obj->type == ADDR_DATASOURCE) {
1750 ads = ADAPTER_DSOURCE(obj);
1751 ds = ads->dataSource;
1752 iface = ds->interface;
1754 if( iface->readOnly ) {
1755 canTreePaste = FALSE;
1758 menu_set_sensitive( addrbook.tree_factory, "/New Address", TRUE );
1759 menu_set_sensitive( addrbook.tree_factory, "/New Folder", TRUE );
1760 menu_set_sensitive( addrbook.tree_factory, "/New Group", TRUE );
1761 gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
1765 else if (obj->type == ADDR_ITEM_FOLDER) {
1766 ds = addressbook_find_datasource( addrbook.treeSelected );
1767 iface = ds->interface;
1768 if( iface->readOnly ) {
1769 canTreePaste = FALSE;
1774 menu_set_sensitive( addrbook.tree_factory, "/New Address", TRUE );
1775 menu_set_sensitive( addrbook.tree_factory, "/New Folder", TRUE );
1776 menu_set_sensitive( addrbook.tree_factory, "/New Group", TRUE );
1777 gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
1781 else if (obj->type == ADDR_ITEM_GROUP) {
1782 ds = addressbook_find_datasource( addrbook.treeSelected );
1783 iface = ds->interface;
1784 if( ! iface->readOnly ) {
1786 menu_set_sensitive( addrbook.tree_factory, "/New Address", TRUE );
1787 gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
1790 else if (obj->type == ADDR_INTERFACE) {
1791 canTreePaste = FALSE;
1795 if( ! addrselect_test_empty( _addressSelect_ ) ) canCut = TRUE;
1797 if( ! addrselect_test_empty( _addressSelect_ ) ) canCopy = TRUE;
1798 if( ! addrclip_is_empty( _clipBoard_ ) ) canPaste = TRUE;
1801 menu_set_sensitive( addrbook.tree_factory, "/Edit", canEdit );
1802 menu_set_sensitive( addrbook.tree_factory, "/Delete", canEdit );
1803 menu_set_sensitive( addrbook.tree_factory, "/Cut", canTreeCut );
1804 menu_set_sensitive( addrbook.tree_factory, "/Copy", canTreeCopy );
1805 menu_set_sensitive( addrbook.tree_factory, "/Paste", canTreePaste );
1807 menu_set_sensitive( addrbook.menu_factory, "/File/Edit", canEdit );
1808 menu_set_sensitive( addrbook.menu_factory, "/File/Delete", canEdit );
1809 menu_set_sensitive( addrbook.menu_factory, "/Edit/Cut", canCut );
1810 menu_set_sensitive( addrbook.menu_factory, "/Edit/Copy", canCopy );
1811 menu_set_sensitive( addrbook.menu_factory, "/Edit/Paste", canPaste );
1812 menu_set_sensitive( addrbook.menu_factory, "/Edit/Paste Address", canPaste );
1814 if( event->button == 3 ) {
1815 gtk_menu_popup(GTK_MENU(addrbook.tree_popup), NULL, NULL, NULL, NULL,
1816 event->button, event->time);
1821 static void addressbook_tree_button_released(GtkWidget *ctree,
1822 GdkEventButton *event,
1825 gtk_ctree_select(GTK_CTREE(addrbook.ctree), addrbook.opened);
1826 gtkut_ctree_set_focus_row(GTK_CTREE(addrbook.ctree), addrbook.opened);
1829 static void addressbook_popup_close(GtkMenuShell *menu_shell, gpointer data)
1831 if (!addrbook.opened) return;
1833 gtk_ctree_select(GTK_CTREE(addrbook.ctree), addrbook.opened);
1834 gtkut_ctree_set_focus_row(GTK_CTREE(addrbook.ctree),
1838 static void addressbook_new_folder_cb(gpointer data, guint action,
1841 GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1842 AddressObject *obj = NULL;
1843 AddressDataSource *ds = NULL;
1844 AddressBookFile *abf = NULL;
1845 ItemFolder *parentFolder = NULL;
1846 ItemFolder *folder = NULL;
1848 if( ! addrbook.treeSelected ) return;
1849 obj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
1850 if( obj == NULL ) return;
1851 ds = addressbook_find_datasource( addrbook.treeSelected );
1852 if( ds == NULL ) return;
1854 if( obj->type == ADDR_DATASOURCE ) {
1855 if( ADAPTER_DSOURCE(obj)->subType != ADDR_BOOK ) return;
1857 else if( obj->type == ADDR_ITEM_FOLDER ) {
1858 parentFolder = ADAPTER_FOLDER(obj)->itemFolder;
1864 abf = ds->rawDataSource;
1865 if( abf == NULL ) return;
1866 folder = addressbook_edit_folder( abf, parentFolder, NULL );
1869 nn = addressbook_node_add_folder( addrbook.treeSelected, ds, folder, ADDR_ITEM_FOLDER );
1870 gtk_ctree_expand( ctree, addrbook.treeSelected );
1871 if( addrbook.treeSelected == addrbook.opened ) addressbook_set_clist(obj);
1876 static void addressbook_new_group_cb(gpointer data, guint action,
1879 GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1880 AddressObject *obj = NULL;
1881 AddressDataSource *ds = NULL;
1882 AddressBookFile *abf = NULL;
1883 ItemFolder *parentFolder = NULL;
1884 ItemGroup *group = NULL;
1886 if( ! addrbook.treeSelected ) return;
1887 obj = gtk_ctree_node_get_row_data(ctree, addrbook.treeSelected);
1888 if( obj == NULL ) return;
1889 ds = addressbook_find_datasource( addrbook.treeSelected );
1890 if( ds == NULL ) return;
1892 if( obj->type == ADDR_DATASOURCE ) {
1893 if( ADAPTER_DSOURCE(obj)->subType != ADDR_BOOK ) return;
1895 else if( obj->type == ADDR_ITEM_FOLDER ) {
1896 parentFolder = ADAPTER_FOLDER(obj)->itemFolder;
1902 abf = ds->rawDataSource;
1903 if( abf == NULL ) return;
1904 group = addressbook_edit_group( abf, parentFolder, NULL );
1907 nn = addressbook_node_add_group( addrbook.treeSelected, ds, group );
1908 gtk_ctree_expand( ctree, addrbook.treeSelected );
1909 if( addrbook.treeSelected == addrbook.opened ) addressbook_set_clist(obj);
1914 static void addressbook_change_node_name(GtkCTreeNode *node, const gchar *name)
1916 GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1919 GdkPixmap *pix_cl, *pix_op;
1920 GdkBitmap *mask_cl, *mask_op;
1921 gboolean is_leaf, expanded;
1923 gtk_ctree_get_node_info(ctree, node, text, &spacing,
1924 &pix_cl, &mask_cl, &pix_op, &mask_op,
1925 &is_leaf, &expanded);
1926 gtk_ctree_set_node_info(ctree, node, name, spacing,
1927 pix_cl, mask_cl, pix_op, mask_op,
1933 * Enter: obj Address object to edit.
1934 * node Node in tree.
1935 * Return: New name of data source.
1937 static gchar *addressbook_edit_datasource( AddressObject *obj, GtkCTreeNode *node ) {
1938 gchar *newName = NULL;
1939 AddressDataSource *ds = NULL;
1940 AddressInterface *iface = NULL;
1941 AdapterDSource *ads = NULL;
1943 ds = addressbook_find_datasource( node );
1944 if( ds == NULL ) return NULL;
1945 iface = ds->interface;
1946 if( ! iface->haveLibrary ) return NULL;
1948 /* Read data from data source */
1949 if( addrindex_ds_get_modify_flag( ds ) ) {
1950 addrindex_ds_read_data( ds );
1953 if( ! addrindex_ds_get_read_flag( ds ) ) {
1954 addrindex_ds_read_data( ds );
1958 ads = ADAPTER_DSOURCE(obj);
1959 if( ads->subType == ADDR_BOOK ) {
1960 if( addressbook_edit_book( _addressIndex_, ads ) == NULL ) return NULL;
1962 else if( ads->subType == ADDR_VCARD ) {
1963 if( addressbook_edit_vcard( _addressIndex_, ads ) == NULL ) return NULL;
1966 else if( ads->subType == ADDR_JPILOT ) {
1967 if( addressbook_edit_jpilot( _addressIndex_, ads ) == NULL ) return NULL;
1971 else if( ads->subType == ADDR_LDAP ) {
1972 if( addressbook_edit_ldap( _addressIndex_, ads ) == NULL ) return NULL;
1978 newName = obj->name;
1983 * Edit an object that is in the address tree area.
1985 static void addressbook_treenode_edit_cb(gpointer data, guint action,
1988 GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
1990 AddressDataSource *ds = NULL;
1991 AddressBookFile *abf = NULL;
1992 GtkCTreeNode *node = NULL, *parentNode = NULL;
1995 if( ! addrbook.treeSelected ) return;
1996 node = addrbook.treeSelected;
1997 if( GTK_CTREE_ROW(node)->level == 1 ) return;
1998 obj = gtk_ctree_node_get_row_data( ctree, node );
1999 if( obj == NULL ) return;
2000 parentNode = GTK_CTREE_ROW(node)->parent;
2002 ds = addressbook_find_datasource( node );
2003 if( ds == NULL ) return;
2005 if( obj->type == ADDR_DATASOURCE ) {
2006 name = addressbook_edit_datasource( obj, node );
2007 if( name == NULL ) return;
2010 abf = ds->rawDataSource;
2011 if( abf == NULL ) return;
2012 if( obj->type == ADDR_ITEM_FOLDER ) {
2013 AdapterFolder *adapter = ADAPTER_FOLDER(obj);
2014 ItemFolder *item = adapter->itemFolder;
2015 ItemFolder *parentFolder = NULL;
2016 parentFolder = ( ItemFolder * ) ADDRITEM_PARENT(item);
2017 if( addressbook_edit_folder( abf, parentFolder, item ) == NULL ) return;
2018 name = ADDRITEM_NAME(item);
2020 else if( obj->type == ADDR_ITEM_GROUP ) {
2021 AdapterGroup *adapter = ADAPTER_GROUP(obj);
2022 ItemGroup *item = adapter->itemGroup;
2023 ItemFolder *parentFolder = NULL;
2024 parentFolder = ( ItemFolder * ) ADDRITEM_PARENT(item);
2025 if( addressbook_edit_group( abf, parentFolder, item ) == NULL ) return;
2026 name = ADDRITEM_NAME(item);
2029 if( name && parentNode ) {
2030 /* Update node in tree view */
2031 addressbook_change_node_name( node, name );
2032 gtk_ctree_sort_node(ctree, parentNode);
2033 gtk_ctree_expand( ctree, node );
2034 gtk_ctree_select( ctree, node );
2039 * Delete an item from the tree widget.
2041 static void addressbook_treenode_delete_cb(gpointer data, guint action,
2044 GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
2045 GtkCTreeNode *node = NULL;
2049 AddressBookFile *abf = NULL;
2050 AdapterDSource *ads = NULL;
2051 AddressInterface *iface = NULL;
2052 AddressDataSource *ds = NULL;
2053 gboolean remFlag = FALSE;
2055 if( ! addrbook.treeSelected ) return;
2056 node = addrbook.treeSelected;
2057 if( GTK_CTREE_ROW(node)->level == 1 ) return;
2059 obj = gtk_ctree_node_get_row_data( ctree, node );
2060 g_return_if_fail(obj != NULL);
2062 if( obj->type == ADDR_DATASOURCE ) {
2063 ads = ADAPTER_DSOURCE(obj);
2064 if( ads == NULL ) return;
2065 ds = ads->dataSource;
2066 if( ds == NULL ) return;
2069 /* Must be folder or something else */
2070 ds = addressbook_find_datasource( node );
2071 if( ds == NULL ) return;
2073 /* Only allow deletion from non-readOnly data sources */
2074 iface = ds->interface;
2075 if( iface->readOnly ) return;
2078 /* Confirm deletion */
2079 if( obj->type == ADDR_ITEM_FOLDER ) {
2080 message = g_strdup_printf( _(
2081 "Do you want to delete the folder AND all addresses in `%s' ? \n" \
2082 "If deleting the folder only, addresses will be moved into parent folder." ),
2084 aval = alertpanel( _("Delete"), message,
2085 _("Folder only"), _("Folder and Addresses"), _("Cancel") );
2087 if( aval == G_ALERTOTHER ) return;
2090 message = g_strdup_printf(_("Really delete `%s' ?"), obj->name);
2091 aval = alertpanel(_("Delete"), message, _("Yes"), _("No"), NULL);
2093 if (aval != G_ALERTDEFAULT) return;
2096 /* Proceed with deletion */
2097 if( obj->type == ADDR_DATASOURCE ) {
2098 /* Remove data source. */
2099 if( addrindex_index_remove_datasource( _addressIndex_, ds ) ) {
2100 addrindex_free_datasource( ds );
2105 abf = addressbook_get_book_file();
2106 if( abf == NULL ) return;
2109 if( obj->type == ADDR_ITEM_FOLDER ) {
2110 AdapterFolder *adapter = ADAPTER_FOLDER(obj);
2111 ItemFolder *item = adapter->itemFolder;
2112 if( aval == G_ALERTDEFAULT ) {
2113 /* Remove folder only */
2114 item = addrbook_remove_folder( abf, item );
2116 addritem_free_item_folder( item );
2117 addressbook_move_nodes_up( ctree, node );
2121 else if( aval == G_ALERTALTERNATE ) {
2122 /* Remove folder and addresses */
2123 item = addrbook_remove_folder_delete( abf, item );
2125 addritem_free_item_folder( item );
2130 else if( obj->type == ADDR_ITEM_GROUP ) {
2131 AdapterGroup *adapter = ADAPTER_GROUP(obj);
2132 ItemGroup *item = adapter->itemGroup;
2134 item = addrbook_remove_group( abf, item );
2136 addritem_free_item_group( item );
2143 gtk_ctree_remove_node(ctree, node );
2147 static void addressbook_new_address_cb( gpointer data, guint action, GtkWidget *widget ) {
2148 AddressObject *pobj = NULL;
2149 AddressDataSource *ds = NULL;
2150 AddressBookFile *abf = NULL;
2152 pobj = gtk_ctree_node_get_row_data(GTK_CTREE(addrbook.ctree), addrbook.treeSelected);
2153 if( pobj == NULL ) return;
2154 ds = addressbook_find_datasource( GTK_CTREE_NODE(addrbook.treeSelected) );
2155 if( ds == NULL ) return;
2157 abf = ds->rawDataSource;
2158 if( abf == NULL ) return;
2160 if( pobj->type == ADDR_DATASOURCE ) {
2161 if( ADAPTER_DSOURCE(pobj)->subType == ADDR_BOOK ) {
2163 ItemPerson *person = addressbook_edit_person( abf, NULL, NULL, FALSE );
2165 if( addrbook.treeSelected == addrbook.opened ) {
2166 gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
2171 else if( pobj->type == ADDR_ITEM_FOLDER ) {
2173 ItemFolder *folder = ADAPTER_FOLDER(pobj)->itemFolder;
2174 ItemPerson *person = addressbook_edit_person( abf, folder, NULL, FALSE );
2176 if (addrbook.treeSelected == addrbook.opened) {
2177 gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
2181 else if( pobj->type == ADDR_ITEM_GROUP ) {
2182 /* New address in group */
2183 ItemGroup *group = ADAPTER_GROUP(pobj)->itemGroup;
2184 if( addressbook_edit_group( abf, NULL, group ) == NULL ) return;
2185 if (addrbook.treeSelected == addrbook.opened) {
2186 /* Change node name in tree. */
2187 addressbook_change_node_name( addrbook.treeSelected, ADDRITEM_NAME(group) );
2188 gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened );
2194 * Search for specified child group node in address index tree.
2195 * Enter: parent Parent node.
2196 * group Group to find.
2198 static GtkCTreeNode *addressbook_find_group_node( GtkCTreeNode *parent, ItemGroup *group ) {
2199 GtkCTreeNode *node = NULL;
2200 GtkCTreeRow *currRow;
2202 currRow = GTK_CTREE_ROW( parent );
2204 node = currRow->children;
2208 obj = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), node );
2209 if( obj->type == ADDR_ITEM_GROUP ) {
2210 ItemGroup *g = ADAPTER_GROUP(obj)->itemGroup;
2211 if( g == group ) return node;
2213 currRow = GTK_CTREE_ROW(node);
2214 node = currRow->sibling;
2221 * Search for specified child folder node in address index tree.
2222 * Enter: parent Parent node.
2223 * folder Folder to find.
2225 static GtkCTreeNode *addressbook_find_folder_node( GtkCTreeNode *parent, ItemFolder *folder ) {
2226 GtkCTreeNode *node = NULL;
2227 GtkCTreeRow *currRow;
2229 currRow = GTK_CTREE_ROW( parent );
2231 node = currRow->children;
2235 obj = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), node );
2236 if( obj->type == ADDR_ITEM_FOLDER ) {
2237 ItemFolder *f = ADAPTER_FOLDER(obj)->itemFolder;
2238 if( f == folder ) return node;
2240 currRow = GTK_CTREE_ROW(node);
2241 node = currRow->sibling;
2247 static AddressBookFile *addressbook_get_book_file() {
2248 AddressBookFile *abf = NULL;
2249 AddressDataSource *ds = NULL;
2251 ds = addressbook_find_datasource( addrbook.treeSelected );
2252 if( ds == NULL ) return NULL;
2253 if( ds->type == ADDR_IF_BOOK ) abf = ds->rawDataSource;
2257 static void addressbook_tree_remove_children( GtkCTree *ctree, GtkCTreeNode *parent ) {
2261 /* Remove existing folders and groups */
2262 row = GTK_CTREE_ROW( parent );
2264 while( (node = row->children) ) {
2265 gtk_ctree_remove_node( ctree, node );
2270 static void addressbook_move_nodes_up( GtkCTree *ctree, GtkCTreeNode *node ) {
2271 GtkCTreeNode *parent, *child;
2272 GtkCTreeRow *currRow;
2273 currRow = GTK_CTREE_ROW( node );
2275 parent = currRow->parent;
2276 while( (child = currRow->children) ) {
2277 gtk_ctree_move( ctree, child, parent, node );
2279 gtk_ctree_sort_node( ctree, parent );
2283 static void addressbook_edit_address_cb( gpointer data, guint action, GtkWidget *widget ) {
2284 GtkCTree *clist = GTK_CTREE(addrbook.clist);
2286 AddressObject *obj = NULL, *pobj = NULL;
2287 AddressDataSource *ds = NULL;
2288 GtkCTreeNode *node = NULL, *parentNode = NULL;
2290 AddressBookFile *abf = NULL;
2292 if( addrbook.listSelected == NULL ) return;
2293 obj = gtk_ctree_node_get_row_data( clist, addrbook.listSelected );
2294 g_return_if_fail(obj != NULL);
2296 ctree = GTK_CTREE( addrbook.ctree );
2297 pobj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
2298 node = gtk_ctree_find_by_row_data( ctree, addrbook.treeSelected, obj );
2300 ds = addressbook_find_datasource( GTK_CTREE_NODE(addrbook.treeSelected) );
2301 if( ds == NULL ) return;
2303 abf = addressbook_get_book_file();
2304 if( abf == NULL ) return;
2305 if( obj->type == ADDR_ITEM_EMAIL ) {
2306 ItemEMail *email = ( ItemEMail * ) obj;
2307 if( email == NULL ) return;
2308 if( pobj && pobj->type == ADDR_ITEM_GROUP ) {
2309 /* Edit parent group */
2310 AdapterGroup *adapter = ADAPTER_GROUP(pobj);
2311 ItemGroup *itemGrp = adapter->itemGroup;
2312 if( addressbook_edit_group( abf, NULL, itemGrp ) == NULL ) return;
2313 name = ADDRITEM_NAME(itemGrp);
2314 node = addrbook.treeSelected;
2315 parentNode = GTK_CTREE_ROW(node)->parent;
2318 /* Edit person - email page */
2320 person = ( ItemPerson * ) ADDRITEM_PARENT(email);
2321 if( addressbook_edit_person( abf, NULL, person, TRUE ) == NULL ) return;
2322 gtk_ctree_select( ctree, addrbook.opened );
2323 invalidate_address_completion();
2327 else if( obj->type == ADDR_ITEM_PERSON ) {
2328 /* Edit person - basic page */
2329 ItemPerson *person = ( ItemPerson * ) obj;
2330 if( addressbook_edit_person( abf, NULL, person, FALSE ) == NULL ) return;
2331 gtk_ctree_select( ctree, addrbook.opened);
2332 invalidate_address_completion();
2335 else if( obj->type == ADDR_ITEM_GROUP ) {
2336 ItemGroup *itemGrp = ( ItemGroup * ) obj;
2337 if( addressbook_edit_group( abf, NULL, itemGrp ) == NULL ) return;
2338 parentNode = addrbook.treeSelected;
2339 node = addressbook_find_group_node( parentNode, itemGrp );
2340 name = ADDRITEM_NAME(itemGrp);
2346 /* Update tree node with node name */
2347 if( node == NULL ) return;
2348 addressbook_change_node_name( node, name );
2349 gtk_ctree_sort_node( ctree, parentNode );
2350 gtk_ctree_select( ctree, addrbook.opened );
2353 static void addressbook_delete_address_cb(gpointer data, guint action,
2356 addressbook_del_clicked(NULL, NULL);
2359 static void close_cb(gpointer data, guint action, GtkWidget *widget)
2361 addressbook_close();
2364 static void addressbook_file_save_cb( gpointer data, guint action, GtkWidget *widget ) {
2365 addressbook_export_to_file();
2368 static void addressbook_person_expand_node( GtkCTree *ctree, GList *node, gpointer *data ) {
2370 ItemPerson *person = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
2371 if( person ) addritem_person_set_opened( person, TRUE );
2375 static void addressbook_person_collapse_node( GtkCTree *ctree, GList *node, gpointer *data ) {
2377 ItemPerson *person = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
2378 if( person ) addritem_person_set_opened( person, FALSE );
2382 static gchar *addressbook_format_item_clist( ItemPerson *person, ItemEMail *email ) {
2384 gchar *eMailAlias = ADDRITEM_NAME(email);
2385 if( eMailAlias && *eMailAlias != '\0' ) {
2387 str = g_strdup_printf( "%s - %s", ADDRITEM_NAME(person), eMailAlias );
2390 str = g_strdup( eMailAlias );
2396 static void addressbook_load_group( GtkCTree *clist, ItemGroup *itemGroup ) {
2397 GList *items = itemGroup->listEMail;
2398 AddressTypeControlItem *atci = addrbookctl_lookup( ADDR_ITEM_EMAIL );
2399 for( ; items != NULL; items = g_list_next( items ) ) {
2400 GtkCTreeNode *nodeEMail = NULL;
2401 gchar *text[N_COLS];
2402 ItemEMail *email = items->data;
2406 if( ! email ) continue;
2408 person = ( ItemPerson * ) ADDRITEM_PARENT(email);
2409 str = addressbook_format_item_clist( person, email );
2411 text[COL_NAME] = str;
2414 text[COL_NAME] = ADDRITEM_NAME(person);
2416 text[COL_ADDRESS] = email->address;
2417 text[COL_REMARKS] = email->remarks;
2418 nodeEMail = gtk_ctree_insert_node(
2420 text, FOLDER_SPACING,
2421 atci->iconXpm, atci->maskXpm,
2422 atci->iconXpmOpen, atci->maskXpmOpen,
2424 gtk_ctree_node_set_row_data( clist, nodeEMail, email );
2430 static void addressbook_folder_load_person( GtkCTree *clist, ItemFolder *itemFolder ) {
2432 AddressTypeControlItem *atci = addrbookctl_lookup( ADDR_ITEM_PERSON );
2433 AddressTypeControlItem *atciMail = addrbookctl_lookup( ADDR_ITEM_EMAIL );
2435 if( atci == NULL ) return;
2436 if( atciMail == NULL ) return;
2438 /* Load email addresses */
2439 items = addritem_folder_get_person_list( itemFolder );
2440 for( ; items != NULL; items = g_list_next( items ) ) {
2441 GtkCTreeNode *nodePerson = NULL;
2442 GtkCTreeNode *nodeEMail = NULL;
2443 gchar *text[N_COLS];
2444 gboolean flgFirst = TRUE, haveAddr = FALSE;
2448 person = ( ItemPerson * ) items->data;
2449 if( person == NULL ) continue;
2451 text[COL_NAME] = NULL;
2452 node = person->listEMail;
2454 ItemEMail *email = node->data;
2455 gchar *eMailAddr = NULL;
2456 node = g_list_next( node );
2458 text[COL_ADDRESS] = email->address;
2459 text[COL_REMARKS] = email->remarks;
2460 eMailAddr = ADDRITEM_NAME(email);
2461 if( eMailAddr && *eMailAddr == '\0' ) eMailAddr = NULL;
2463 /* First email belongs with person */
2464 gchar *str = addressbook_format_item_clist( person, email );
2466 text[COL_NAME] = str;
2469 text[COL_NAME] = ADDRITEM_NAME(person);
2471 nodePerson = gtk_ctree_insert_node(
2473 text, FOLDER_SPACING,
2474 atci->iconXpm, atci->maskXpm,
2475 atci->iconXpmOpen, atci->maskXpmOpen,
2476 FALSE, person->isOpened );
2479 gtk_ctree_node_set_row_data(clist, nodePerson, person );
2482 /* Subsequent email is a child node of person */
2483 text[COL_NAME] = ADDRITEM_NAME(email);
2484 nodeEMail = gtk_ctree_insert_node(
2485 clist, nodePerson, NULL,
2486 text, FOLDER_SPACING,
2487 atciMail->iconXpm, atciMail->maskXpm,
2488 atciMail->iconXpmOpen, atciMail->maskXpmOpen,
2490 gtk_ctree_node_set_row_data(clist, nodeEMail, email );
2496 /* Have name without EMail */
2497 text[COL_NAME] = ADDRITEM_NAME(person);
2498 text[COL_ADDRESS] = NULL;
2499 text[COL_REMARKS] = NULL;
2500 nodePerson = gtk_ctree_insert_node(
2502 text, FOLDER_SPACING,
2503 atci->iconXpm, atci->maskXpm,
2504 atci->iconXpmOpen, atci->maskXpmOpen,
2505 FALSE, person->isOpened );
2506 gtk_ctree_node_set_row_data(clist, nodePerson, person );
2508 gtk_ctree_sort_node(GTK_CTREE(clist), NULL);
2510 /* Free up the list */
2511 mgu_clear_list( items );
2512 g_list_free( items );
2515 static void addressbook_folder_load_group( GtkCTree *clist, ItemFolder *itemFolder ) {
2517 AddressTypeControlItem *atci = addrbookctl_lookup( ADDR_ITEM_GROUP );
2519 /* Load any groups */
2520 if( ! atci ) return;
2521 items = addritem_folder_get_group_list( itemFolder );
2522 for( ; items != NULL; items = g_list_next( items ) ) {
2523 GtkCTreeNode *nodeGroup = NULL;
2524 gchar *text[N_COLS];
2525 ItemGroup *group = items->data;
2526 if( group == NULL ) continue;
2527 text[COL_NAME] = ADDRITEM_NAME(group);
2528 text[COL_ADDRESS] = NULL;
2529 text[COL_REMARKS] = NULL;
2530 nodeGroup = gtk_ctree_insert_node(clist, NULL, NULL,
2531 text, FOLDER_SPACING,
2532 atci->iconXpm, atci->maskXpm,
2533 atci->iconXpmOpen, atci->maskXpmOpen,
2535 gtk_ctree_node_set_row_data(clist, nodeGroup, group );
2536 gtk_ctree_sort_node(clist, NULL);
2538 /* Free up the list */
2539 mgu_clear_list( items );
2540 g_list_free( items );
2544 * Load data sources into list.
2546 static void addressbook_node_load_datasource( GtkCTree *clist, AddressObject *obj ) {
2547 AdapterInterface *adapter;
2548 AddressInterface *iface;
2549 AddressTypeControlItem *atci = NULL;
2550 GtkCTreeNode *newNode, *node;
2552 GtkCell *cell = NULL;
2553 gchar *text[N_COLS];
2555 adapter = ADAPTER_INTERFACE(obj);
2556 if( adapter == NULL ) return;
2557 iface = adapter->interface;
2558 atci = adapter->atci;
2559 if( atci == NULL ) return;
2561 /* Create nodes in list copying values for data sources in tree */
2562 row = GTK_CTREE_ROW( adapter->treeNode );
2564 node = row->children;
2568 data = gtk_ctree_node_get_row_data( clist, node );
2569 row = GTK_CTREE_ROW( node );
2570 cell = ( ( GtkCListRow * )row )->cell;
2571 text[COL_NAME] = cell->u.text;
2572 text[COL_ADDRESS] = NULL;
2573 text[COL_REMARKS] = NULL;
2574 newNode = gtk_ctree_insert_node( clist, NULL, NULL,
2575 text, FOLDER_SPACING,
2576 atci->iconXpm, atci->maskXpm,
2577 atci->iconXpmOpen, atci->maskXpmOpen,
2580 gtk_ctree_node_set_row_data( clist, newNode, data );
2581 gtk_ctree_node_set_row_data_full( clist, newNode, NULL, NULL );
2583 node = row->sibling;
2586 gtk_ctree_sort_node( clist, NULL );
2590 * Search ctree widget callback function.
2591 * Enter: pA Pointer to node.
2592 * pB Pointer to data item being sought.
2593 * Return: Zero (0) if group found.
2595 static int addressbook_treenode_find_group_cb( gconstpointer pA, gconstpointer pB ) {
2598 aoA = ( AddressObject * ) pA;
2599 if( aoA->type == ADDR_ITEM_GROUP ) {
2600 ItemGroup *group, *grp;
2602 grp = ADAPTER_GROUP(aoA)->itemGroup;
2603 group = ( ItemGroup * ) pB;
2604 if( grp == group ) return 0; /* Found group */
2610 * Search ctree widget callback function.
2611 * Enter: pA Pointer to node.
2612 * pB Pointer to data item being sought.
2613 * Return: Zero (0) if folder found.
2615 static int addressbook_treenode_find_folder_cb( gconstpointer pA, gconstpointer pB ) {
2618 aoA = ( AddressObject * ) pA;
2619 if( aoA->type == ADDR_ITEM_FOLDER ) {
2620 ItemFolder *folder, *fld;
2622 fld = ADAPTER_FOLDER(aoA)->itemFolder;
2623 folder = ( ItemFolder * ) pB;
2624 if( fld == folder ) return 0; /* Found folder */
2630 * Remove folder and group nodes from tree widget for items contained ("cut")
2633 static void addressbook_treenode_remove_item( void ) {
2635 AddrSelectItem *cutItem;
2636 AddressCache *cache;
2637 AddrItemObject *aio;
2638 GtkCTree *ctree = GTK_CTREE( addrbook.ctree );
2641 node = _clipBoard_->objectList;
2643 cutItem = node->data;
2644 node = g_list_next( node );
2645 cache = addrindex_get_cache(
2646 _clipBoard_->addressIndex, cutItem->cacheID );
2647 if( cache == NULL ) continue;
2648 aio = addrcache_get_object( cache, cutItem->uid );
2651 if( ADDRITEM_TYPE(aio) == ITEMTYPE_FOLDER ) {
2654 folder = ( ItemFolder * ) aio;
2655 tn = gtk_ctree_find_by_row_data_custom(
2656 ctree, NULL, folder,
2657 addressbook_treenode_find_folder_cb );
2659 else if( ADDRITEM_TYPE(aio) == ITEMTYPE_GROUP ) {
2662 group = ( ItemGroup * ) aio;
2663 tn = gtk_ctree_find_by_row_data_custom(
2665 addressbook_treenode_find_group_cb );
2669 /* Free up adapter and remove node. */
2670 gtk_ctree_remove_node( ctree, tn );
2677 * Find parent datasource for specified tree node.
2678 * Enter: node Node to test.
2679 * Return: Data source, or NULL if not found.
2681 static AddressDataSource *addressbook_find_datasource( GtkCTreeNode *node ) {
2682 AddressDataSource *ds = NULL;
2685 g_return_val_if_fail(addrbook.ctree != NULL, NULL);
2688 if( GTK_CTREE_ROW(node)->level < 2 ) return NULL;
2689 ao = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), node );
2691 /* printf( "ao->type = %d\n", ao->type ); */
2692 if( ao->type == ADDR_DATASOURCE ) {
2693 AdapterDSource *ads = ADAPTER_DSOURCE(ao);
2694 /* printf( "found it\n" ); */
2695 ds = ads->dataSource;
2699 node = GTK_CTREE_ROW(node)->parent;
2705 * Load address list widget with children of specified object.
2706 * Enter: obj Parent object to be loaded.
2708 static void addressbook_set_clist( AddressObject *obj ) {
2709 GtkCTree *ctreelist = GTK_CTREE(addrbook.clist);
2710 GtkCList *clist = GTK_CLIST(addrbook.clist);
2711 AddressDataSource *ds = NULL;
2712 AdapterDSource *ads = NULL;
2715 gtk_clist_clear(clist);
2719 if( obj->type == ADDR_INTERFACE ) {
2720 /* printf( "set_clist: loading datasource...\n" ); */
2721 /* addressbook_node_load_datasource( GTK_CTREE(clist), obj ); */
2725 gtk_clist_freeze(clist);
2726 gtk_clist_clear(clist);
2728 if( obj->type == ADDR_DATASOURCE ) {
2729 ads = ADAPTER_DSOURCE(obj);
2730 ds = ADAPTER_DSOURCE(obj)->dataSource;
2732 /* Load root folder */
2733 ItemFolder *rootFolder = NULL;
2734 rootFolder = addrindex_ds_get_root_folder( ds );
2735 addressbook_folder_load_person( ctreelist, addrindex_ds_get_root_folder( ds ) );
2736 addressbook_folder_load_group( ctreelist, addrindex_ds_get_root_folder( ds ) );
2740 if( obj->type == ADDR_ITEM_GROUP ) {
2742 ItemGroup *itemGroup = ADAPTER_GROUP(obj)->itemGroup;
2743 addressbook_load_group( ctreelist, itemGroup );
2745 else if( obj->type == ADDR_ITEM_FOLDER ) {
2747 ItemFolder *itemFolder = ADAPTER_FOLDER(obj)->itemFolder;
2748 addressbook_folder_load_person( ctreelist, itemFolder );
2749 addressbook_folder_load_group( ctreelist, itemFolder );
2752 /* gtk_clist_sort(clist); */
2753 gtk_clist_thaw(clist);
2757 * Call back function to free adaptor. Call back is setup by function
2758 * gtk_ctree_node_set_row_data_full() when node is populated. This function is
2759 * called when the address book tree widget node is removed by calling
2760 * function gtk_ctree_remove_node().
2761 * Enter: data Tree node's row data.
2763 static void addressbook_free_treenode( gpointer data ) {
2766 ao = ( AddressObject * ) data;
2767 if( ao == NULL ) return;
2768 if( ao->type == ADDR_INTERFACE ) {
2769 AdapterInterface *ai = ADAPTER_INTERFACE(ao);
2770 addrbookctl_free_interface( ai );
2772 else if( ao->type == ADDR_DATASOURCE ) {
2773 AdapterDSource *ads = ADAPTER_DSOURCE(ao);
2774 addrbookctl_free_datasource( ads );
2776 else if( ao->type == ADDR_ITEM_FOLDER ) {
2777 AdapterFolder *af = ADAPTER_FOLDER(ao);
2778 addrbookctl_free_folder( af );
2780 else if( ao->type == ADDR_ITEM_GROUP ) {
2781 AdapterGroup *ag = ADAPTER_GROUP(ao);
2782 addrbookctl_free_group( ag );
2787 * Create new adaptor for specified data source.
2789 AdapterDSource *addressbook_create_ds_adapter( AddressDataSource *ds,
2790 AddressObjectType otype, gchar *name )
2792 AdapterDSource *adapter = g_new0( AdapterDSource, 1 );
2793 ADDRESS_OBJECT(adapter)->type = ADDR_DATASOURCE;
2794 ADDRESS_OBJECT_NAME(adapter) = g_strdup( name );
2795 adapter->dataSource = ds;
2796 adapter->subType = otype;
2800 void addressbook_ads_set_name( AdapterDSource *adapter, gchar *value ) {
2801 ADDRESS_OBJECT_NAME(adapter) = mgu_replace_string( ADDRESS_OBJECT_NAME(adapter), value );
2805 * Load tree from address index with the initial data.
2807 static void addressbook_load_tree( void ) {
2808 GtkCTree *ctree = GTK_CTREE( addrbook.ctree );
2809 GList *nodeIf, *nodeDS;
2810 AdapterInterface *adapter;
2811 AddressInterface *iface;
2812 AddressTypeControlItem *atci;
2813 AddressDataSource *ds;
2814 AdapterDSource *ads;
2815 GtkCTreeNode *node, *newNode;
2818 nodeIf = _addressInterfaceList_;
2820 adapter = nodeIf->data;
2821 node = adapter->treeNode;
2822 iface = adapter->interface;
2823 atci = adapter->atci;
2825 if( iface->useInterface ) {
2826 /* Load data sources below interface node */
2827 nodeDS = iface->listSource;
2831 name = addrindex_ds_get_name( ds );
2832 ads = addressbook_create_ds_adapter( ds, atci->objectType, name );
2833 newNode = addressbook_add_object( node, ADDRESS_OBJECT(ads) );
2834 nodeDS = g_list_next( nodeDS );
2836 gtk_ctree_expand( ctree, node );
2839 nodeIf = g_list_next( nodeIf );
2844 * Convert the old address book to new format.
2846 static gboolean addressbook_convert( AddressIndex *addrIndex ) {
2847 gboolean retVal = FALSE;
2848 gboolean errFlag = TRUE;
2851 /* Read old address book, performing conversion */
2852 debug_print( "Reading and converting old address book...\n" );
2853 addrindex_set_file_name( addrIndex, ADDRESSBOOK_OLD_FILE );
2854 addrindex_read_data( addrIndex );
2855 if( addrIndex->retVal == MGU_NO_FILE ) {
2856 /* We do not have a file - new user */
2857 debug_print( "New user... create new books...\n" );
2858 addrindex_create_new_books( addrIndex );
2859 if( addrIndex->retVal == MGU_SUCCESS ) {
2860 /* Save index file */
2861 addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2862 addrindex_save_data( addrIndex );
2863 if( addrIndex->retVal == MGU_SUCCESS ) {
2868 msg = _( "New user, could not save index file." );
2872 msg = _( "New user, could not save address book files." );
2876 /* We have an old file */
2877 if( addrIndex->wasConverted ) {
2878 /* Converted successfully - save address index */
2879 addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2880 addrindex_save_data( addrIndex );
2881 if( addrIndex->retVal == MGU_SUCCESS ) {
2882 msg = _( "Old address book converted successfully." );
2887 msg = _("Old address book converted,\n"
2888 "could not save new address index file" );
2892 /* File conversion failed - just create new books */
2893 debug_print( "File conversion failed... just create new books...\n" );
2894 addrindex_create_new_books( addrIndex );
2895 if( addrIndex->retVal == MGU_SUCCESS ) {
2897 addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2898 addrindex_save_data( addrIndex );
2899 if( addrIndex->retVal == MGU_SUCCESS ) {
2900 msg = _("Could not convert address book,\n"
2901 "but created empty new address book files." );
2906 msg = _("Could not convert address book,\n"
2907 "could not create new address book files." );
2911 msg = _("Could not convert address book\n"
2912 "and could not create new address book files." );
2917 debug_print( "Error\n%s\n", msg );
2918 alertpanel( _( "Addressbook conversion error" ), msg, _( "Close" ), NULL, NULL );
2921 debug_print( "Warning\n%s\n", msg );
2922 alertpanel( _( "Addressbook conversion" ), msg, _( "Close" ), NULL, NULL );
2928 void addressbook_read_file( void ) {
2929 AddressIndex *addrIndex = NULL;
2931 debug_print( "Reading address index...\n" );
2932 if( _addressIndex_ ) {
2933 debug_print( "address book already read!!!\n" );
2937 addrIndex = addrindex_create_index();
2939 /* Use new address book index. */
2940 addrindex_set_file_path( addrIndex, get_rc_dir() );
2941 addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
2942 addrindex_read_data( addrIndex );
2943 if( addrIndex->retVal == MGU_NO_FILE ) {
2944 /* Conversion required */
2945 debug_print( "Converting...\n" );
2946 if( addressbook_convert( addrIndex ) ) {
2947 _addressIndex_ = addrIndex;
2950 else if( addrIndex->retVal == MGU_SUCCESS ) {
2951 _addressIndex_ = addrIndex;
2954 /* Error reading address book */
2955 debug_print( "Could not read address index.\n" );
2956 addrindex_print_index( addrIndex, stdout );
2957 alertpanel( _( "Addressbook Error" ),
2958 _( "Could not read address index" ),
2959 _( "Close" ), NULL, NULL );
2961 debug_print( "done.\n" );
2965 * Add object into the address index tree widget.
2966 * Enter: node Parent node.
2967 * obj Object to add.
2968 * Return: Node that was added, or NULL if object not added.
2970 static GtkCTreeNode *addressbook_add_object(GtkCTreeNode *node,
2973 GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
2974 GtkCTreeNode *added;
2975 AddressObject *pobj;
2976 AddressObjectType otype;
2977 AddressTypeControlItem *atci = NULL;
2979 g_return_val_if_fail(node != NULL, NULL);
2980 g_return_val_if_fail(obj != NULL, NULL);
2982 pobj = gtk_ctree_node_get_row_data(ctree, node);
2983 g_return_val_if_fail(pobj != NULL, NULL);
2985 /* Determine object type to be displayed */
2986 if( obj->type == ADDR_DATASOURCE ) {
2987 otype = ADAPTER_DSOURCE(obj)->subType;
2993 /* Handle any special conditions. */
2995 atci = addrbookctl_lookup( otype );
2997 if( atci->showInTree ) {
2998 /* Add object to tree */
3001 added = gtk_ctree_insert_node( ctree, node, NULL, name, FOLDER_SPACING,
3002 atci->iconXpm, atci->maskXpm, atci->iconXpmOpen, atci->maskXpmOpen,
3003 atci->treeLeaf, atci->treeExpand );
3004 gtk_ctree_node_set_row_data_full( ctree, added, obj,
3005 addressbook_free_treenode );
3009 gtk_ctree_sort_node(ctree, node);
3015 * Add group into the address index tree.
3016 * Enter: node Parent node.
3018 * itemGroup Group to add.
3019 * Return: Inserted node.
3021 static GtkCTreeNode *addressbook_node_add_group( GtkCTreeNode *node, AddressDataSource *ds, ItemGroup *itemGroup ) {
3022 GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
3023 GtkCTreeNode *newNode;
3024 AdapterGroup *adapter;
3025 AddressTypeControlItem *atci = NULL;
3028 if( ds == NULL ) return NULL;
3029 if( node == NULL || itemGroup == NULL ) return NULL;
3031 name = &itemGroup->obj.name;
3033 atci = addrbookctl_lookup( ADDR_ITEM_GROUP );
3035 adapter = g_new0( AdapterGroup, 1 );
3036 ADDRESS_OBJECT_TYPE(adapter) = ADDR_ITEM_GROUP;
3037 ADDRESS_OBJECT_NAME(adapter) = g_strdup( ADDRITEM_NAME(itemGroup) );
3038 adapter->itemGroup = itemGroup;
3040 newNode = gtk_ctree_insert_node( ctree, node, NULL, name, FOLDER_SPACING,
3041 atci->iconXpm, atci->maskXpm, atci->iconXpm, atci->maskXpm,
3042 atci->treeLeaf, atci->treeExpand );
3043 gtk_ctree_node_set_row_data_full( ctree, newNode, adapter,
3044 addressbook_free_treenode );
3045 gtk_ctree_sort_node( ctree, node );
3050 * Add folder into the address index tree.
3051 * Enter: node Parent node.
3053 * itemFolder Folder to add.
3054 * otype Object type to display.
3055 * Return: Inserted node.
3057 static GtkCTreeNode *addressbook_node_add_folder(
3058 GtkCTreeNode *node, AddressDataSource *ds, ItemFolder *itemFolder, AddressObjectType otype )
3060 GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
3061 GtkCTreeNode *newNode = NULL;
3062 AdapterFolder *adapter;
3063 AddressTypeControlItem *atci = NULL;
3064 GList *listItems = NULL;
3066 ItemFolder *rootFolder;
3068 if( ds == NULL ) return NULL;
3069 if( node == NULL || itemFolder == NULL ) return NULL;
3071 /* Determine object type */
3072 atci = addrbookctl_lookup( otype );
3073 if( atci == NULL ) return NULL;
3075 rootFolder = addrindex_ds_get_root_folder( ds );
3076 if( itemFolder == rootFolder ) {
3080 name = &itemFolder->obj.name;
3082 adapter = g_new0( AdapterFolder, 1 );
3083 ADDRESS_OBJECT_TYPE(adapter) = ADDR_ITEM_FOLDER;
3084 ADDRESS_OBJECT_NAME(adapter) = g_strdup( ADDRITEM_NAME(itemFolder) );
3085 adapter->itemFolder = itemFolder;
3087 newNode = gtk_ctree_insert_node( ctree, node, NULL, name, FOLDER_SPACING,
3088 atci->iconXpm, atci->maskXpm, atci->iconXpm, atci->maskXpm,
3089 atci->treeLeaf, atci->treeExpand );
3090 gtk_ctree_node_set_row_data_full( ctree, newNode, adapter,
3091 addressbook_free_treenode );
3094 listItems = itemFolder->listFolder;
3095 while( listItems ) {
3096 ItemFolder *item = listItems->data;
3097 addressbook_node_add_folder( newNode, ds, item, otype );
3098 listItems = g_list_next( listItems );
3100 listItems = itemFolder->listGroup;
3101 while( listItems ) {
3102 ItemGroup *item = listItems->data;
3103 addressbook_node_add_group( newNode, ds, item );
3104 listItems = g_list_next( listItems );
3106 gtk_ctree_sort_node( ctree, node );
3110 static void addressbook_delete_object(AddressObject *obj) {
3111 AdapterDSource *ads = NULL;
3112 AddressDataSource *ds = NULL;
3115 /* Remove data source. */
3116 /* printf( "Delete obj type : %d\n", obj->type ); */
3118 ads = ADAPTER_DSOURCE(obj);
3119 if( ads == NULL ) return;
3120 ds = ads->dataSource;
3121 if( ds == NULL ) return;
3123 /* Remove data source */
3124 if( addrindex_index_remove_datasource( _addressIndex_, ds ) ) {
3125 addrindex_free_datasource( ds );
3127 /* Free up Adapter object */
3131 void addressbook_export_to_file( void ) {
3132 if( _addressIndex_ ) {
3133 /* Save all new address book data */
3134 debug_print( "Saving address books...\n" );
3135 addrindex_save_all_books( _addressIndex_ );
3137 debug_print( "Exporting addressbook to file...\n" );
3138 addrindex_save_data( _addressIndex_ );
3139 if( _addressIndex_->retVal != MGU_SUCCESS ) {
3140 addrindex_print_index( _addressIndex_, stdout );
3143 /* Notify address completion of new data */
3144 invalidate_address_completion();
3148 static void key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
3150 if (event && event->keyval == GDK_Escape)
3151 addressbook_close();
3155 * Comparison using cell contents (text in first column). Used for sort
3156 * address index widget.
3158 static gint addressbook_treenode_compare_func(
3159 GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2 )
3161 GtkCell *cell1 = ((GtkCListRow *)ptr1)->cell;
3162 GtkCell *cell2 = ((GtkCListRow *)ptr2)->cell;
3163 gchar *name1 = NULL, *name2 = NULL;
3164 if( cell1 ) name1 = cell1->u.text;
3165 if( cell2 ) name2 = cell2->u.text;
3166 if( ! name1 ) return ( name2 != NULL );
3167 if( ! name2 ) return -1;
3168 return strcasecmp( name1, name2 );
3172 * Comparison using object names and types.
3174 static gint addressbook_list_compare_func(
3175 GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2 )
3177 AddrItemObject *aio1 = ((GtkCListRow *)ptr1)->data;
3178 AddrItemObject *aio2 = ((GtkCListRow *)ptr2)->data;
3179 gchar *name1 = NULL, *name2 = NULL;
3181 /* Order by cell contents */
3182 name1 = ADDRITEM_NAME( aio1 );
3183 name2 = ADDRITEM_NAME( aio2 );
3185 if( aio1->type == aio2->type ) {
3187 if( ! name1 ) return ( name2 != NULL );
3188 if( ! name2 ) return -1;
3189 return strcasecmp( name1, name2 );
3192 /* Order groups before person */
3193 if( aio1->type == ITEMTYPE_GROUP ) {
3196 else if( aio2->type == ITEMTYPE_GROUP ) {
3203 static void addressbook_new_book_cb( gpointer data, guint action, GtkWidget *widget ) {
3204 AdapterDSource *ads;
3205 AdapterInterface *adapter;
3206 GtkCTreeNode *newNode;
3208 adapter = addrbookctl_find_interface( ADDR_IF_BOOK );
3209 if( adapter == NULL ) return;
3210 ads = addressbook_edit_book( _addressIndex_, NULL );
3212 newNode = addressbook_add_object( adapter->treeNode, ADDRESS_OBJECT(ads) );
3214 gtk_ctree_select( GTK_CTREE(addrbook.ctree), newNode );
3215 addrbook.treeSelected = newNode;
3220 static void addressbook_new_vcard_cb( gpointer data, guint action, GtkWidget *widget ) {
3221 AdapterDSource *ads;
3222 AdapterInterface *adapter;
3223 GtkCTreeNode *newNode;
3225 adapter = addrbookctl_find_interface( ADDR_IF_VCARD );
3226 if( adapter == NULL ) return;
3227 ads = addressbook_edit_vcard( _addressIndex_, NULL );
3229 newNode = addressbook_add_object( adapter->treeNode, ADDRESS_OBJECT(ads) );
3231 gtk_ctree_select( GTK_CTREE(addrbook.ctree), newNode );
3232 addrbook.treeSelected = newNode;
3238 static void addressbook_new_jpilot_cb( gpointer data, guint action, GtkWidget *widget ) {
3239 AdapterDSource *ads;
3240 AdapterInterface *adapter;
3241 AddressInterface *iface;
3242 GtkCTreeNode *newNode;
3244 adapter = addrbookctl_find_interface( ADDR_IF_JPILOT );
3245 if( adapter == NULL ) return;
3246 iface = adapter->interface;
3247 if( ! iface->haveLibrary ) return;
3248 ads = addressbook_edit_jpilot( _addressIndex_, NULL );
3250 newNode = addressbook_add_object( adapter->treeNode, ADDRESS_OBJECT(ads) );
3252 gtk_ctree_select( GTK_CTREE(addrbook.ctree), newNode );
3253 addrbook.treeSelected = newNode;
3260 static void addressbook_new_ldap_cb( gpointer data, guint action, GtkWidget *widget ) {
3261 AdapterDSource *ads;
3262 AdapterInterface *adapter;
3263 AddressInterface *iface;
3264 GtkCTreeNode *newNode;
3266 adapter = addrbookctl_find_interface( ADDR_IF_LDAP );
3267 if( adapter == NULL ) return;
3268 iface = adapter->interface;
3269 if( ! iface->haveLibrary ) return;
3270 ads = addressbook_edit_ldap( _addressIndex_, NULL );
3272 newNode = addressbook_add_object( adapter->treeNode, ADDRESS_OBJECT(ads) );
3274 gtk_ctree_select( GTK_CTREE(addrbook.ctree), newNode );
3275 addrbook.treeSelected = newNode;
3280 static void addressbook_ldap_show_message( SyldapServer *svr ) {
3282 *addressbook_msgbuf = '\0';
3284 name = syldap_get_name( svr );
3285 if( svr->busyFlag ) {
3286 sprintf( addressbook_msgbuf, "%s: %s", name, ADDRESSBOOK_LDAP_BUSYMSG );
3289 if( svr->retVal == MGU_SUCCESS ) {
3290 sprintf( addressbook_msgbuf, "%s", name );
3293 sprintf( addressbook_msgbuf, "%s: %s", name, mgu_error2string( svr->retVal ) );
3297 addressbook_status_show( addressbook_msgbuf );
3300 static void ldapsearch_callback( SyldapServer *sls ) {
3301 GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
3303 AdapterDSource *ads = NULL;
3304 AddressDataSource *ds = NULL;
3305 AddressInterface *iface = NULL;
3307 if( sls == NULL ) return;
3308 if( ! addrbook.treeSelected ) return;
3309 if( GTK_CTREE_ROW( addrbook.treeSelected )->level == 1 ) return;
3311 obj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
3312 if( obj == NULL ) return;
3313 if( obj->type == ADDR_DATASOURCE ) {
3314 ads = ADAPTER_DSOURCE(obj);
3315 if( ads->subType == ADDR_LDAP ) {
3316 SyldapServer *server;
3318 ds = ads->dataSource;
3319 if( ds == NULL ) return;
3320 iface = ds->interface;
3321 if( ! iface->haveLibrary ) return;
3322 server = ds->rawDataSource;
3323 if( server == sls ) {
3324 /* Read from cache */
3325 gtk_widget_show_all(addrbook.window);
3326 addressbook_set_clist( obj );
3327 addressbook_ldap_show_message( sls );
3328 gtk_widget_show_all(addrbook.window);
3329 gtk_entry_set_text( GTK_ENTRY(addrbook.entry), "" );
3337 * Lookup button handler.
3339 static void addressbook_lup_clicked( GtkButton *button, gpointer data ) {
3340 GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
3343 AdapterDSource *ads = NULL;
3344 AddressDataSource *ds = NULL;
3345 AddressInterface *iface = NULL;
3349 sLookup = gtk_editable_get_chars( GTK_EDITABLE(addrbook.entry), 0, -1 );
3350 g_strchomp( sLookup );
3352 if( ! addrbook.treeSelected ) return;
3353 if( GTK_CTREE_ROW( addrbook.treeSelected )->level == 1 ) return;
3355 obj = gtk_ctree_node_get_row_data( ctree, addrbook.treeSelected );
3356 if( obj == NULL ) return;
3359 if( obj->type == ADDR_DATASOURCE ) {
3360 ads = ADAPTER_DSOURCE(obj);
3361 if( ads->subType == ADDR_LDAP ) {
3362 SyldapServer *server;
3364 ds = ads->dataSource;
3365 if( ds == NULL ) return;
3366 iface = ds->interface;
3367 if( ! iface->haveLibrary ) return;
3368 server = ds->rawDataSource;
3370 syldap_cancel_read( server );
3371 if( *sLookup == '\0' || strlen( sLookup ) < 1 ) return;
3372 syldap_set_search_value( server, sLookup );
3373 syldap_set_callback( server, ldapsearch_callback );
3374 syldap_read_data_th( server );
3375 addressbook_ldap_show_message( server );
3383 /* **********************************************************************
3384 * Build lookup tables.
3385 * ***********************************************************************
3389 * Remap object types.
3390 * Enter: abType AddressObjectType (used in tree node).
3391 * Return: ItemObjectType (used in address cache data).
3393 ItemObjectType addressbook_type2item( AddressObjectType abType ) {
3394 ItemObjectType ioType;
3396 ioType = ITEMTYPE_NONE;
3398 case ADDR_ITEM_PERSON: ioType = ITEMTYPE_PERSON; break;
3399 case ADDR_ITEM_EMAIL: ioType = ITEMTYPE_EMAIL; break;
3400 case ADDR_ITEM_FOLDER: ioType = ITEMTYPE_FOLDER; break;
3401 case ADDR_ITEM_GROUP: ioType = ITEMTYPE_GROUP; break;
3402 case ADDR_DATASOURCE: ioType = ITEMTYPE_DATASOURCE; break;
3408 * Build table that controls the rendering of object types.
3410 void addrbookctl_build_map( GtkWidget *window ) {
3411 AddressTypeControlItem *atci;
3414 stock_pixmap_gdk(window, STOCK_PIXMAP_DIR_CLOSE, &folderxpm, &folderxpmmask);
3415 stock_pixmap_gdk(window, STOCK_PIXMAP_DIR_OPEN, &folderopenxpm, &folderopenxpmmask);
3416 stock_pixmap_gdk(window, STOCK_PIXMAP_GROUP, &groupxpm, &groupxpmmask);
3417 stock_pixmap_gdk(window, STOCK_PIXMAP_VCARD, &vcardxpm, &vcardxpmmask);
3418 stock_pixmap_gdk(window, STOCK_PIXMAP_BOOK, &bookxpm, &bookxpmmask);
3419 stock_pixmap_gdk(window, STOCK_PIXMAP_ADDRESS, &addressxpm, &addressxpmmask);
3420 stock_pixmap_gdk(window, STOCK_PIXMAP_JPILOT, &jpilotxpm, &jpilotxpmmask);
3421 stock_pixmap_gdk(window, STOCK_PIXMAP_CATEGORY, &categoryxpm, &categoryxpmmask);
3422 stock_pixmap_gdk(window, STOCK_PIXMAP_LDAP, &ldapxpm, &ldapxpmmask);
3424 _addressBookTypeHash_ = g_hash_table_new( g_int_hash, g_int_equal );
3425 _addressBookTypeList_ = NULL;
3428 atci = g_new0( AddressTypeControlItem, 1 );
3429 atci->objectType = ADDR_INTERFACE;
3430 atci->interfaceType = ADDR_IF_NONE;
3431 atci->showInTree = TRUE;
3432 atci->treeExpand = TRUE;
3433 atci->treeLeaf = FALSE;
3434 atci->displayName = _( "Interface" );
3435 atci->iconXpm = folderxpm;
3436 atci->maskXpm = folderxpmmask;
3437 atci->iconXpmOpen = folderopenxpm;
3438 atci->maskXpmOpen = folderopenxpmmask;
3439 atci->menuCommand = NULL;
3440 g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3441 _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3444 atci = g_new0( AddressTypeControlItem, 1 );
3445 atci->objectType = ADDR_BOOK;
3446 atci->interfaceType = ADDR_IF_BOOK;
3447 atci->showInTree = TRUE;
3448 atci->treeExpand = TRUE;
3449 atci->treeLeaf = FALSE;
3450 atci->displayName = _( "Address Book" );
3451 atci->iconXpm = bookxpm;
3452 atci->maskXpm = bookxpmmask;
3453 atci->iconXpmOpen = bookxpm;
3454 atci->maskXpmOpen = bookxpmmask;
3455 atci->menuCommand = "/File/New Book";
3456 g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3457 _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3460 atci = g_new0( AddressTypeControlItem, 1 );
3461 atci->objectType = ADDR_ITEM_PERSON;
3462 atci->interfaceType = ADDR_IF_NONE;
3463 atci->showInTree = FALSE;
3464 atci->treeExpand = FALSE;
3465 atci->treeLeaf = FALSE;
3466 atci->displayName = _( "Person" );
3467 atci->iconXpm = NULL;
3468 atci->maskXpm = NULL;
3469 atci->iconXpmOpen = NULL;
3470 atci->maskXpmOpen = NULL;
3471 atci->menuCommand = NULL;
3472 g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3473 _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3476 atci = g_new0( AddressTypeControlItem, 1 );
3477 atci->objectType = ADDR_ITEM_EMAIL;
3478 atci->interfaceType = ADDR_IF_NONE;
3479 atci->showInTree = FALSE;
3480 atci->treeExpand = FALSE;
3481 atci->treeLeaf = TRUE;
3482 atci->displayName = _( "EMail Address" );
3483 atci->iconXpm = addressxpm;
3484 atci->maskXpm = addressxpmmask;
3485 atci->iconXpmOpen = addressxpm;
3486 atci->maskXpmOpen = addressxpmmask;
3487 atci->menuCommand = NULL;
3488 g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3489 _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3492 atci = g_new0( AddressTypeControlItem, 1 );
3493 atci->objectType = ADDR_ITEM_GROUP;
3494 atci->interfaceType = ADDR_IF_BOOK;
3495 atci->showInTree = TRUE;
3496 atci->treeExpand = FALSE;
3497 atci->treeLeaf = FALSE;
3498 atci->displayName = _( "Group" );
3499 atci->iconXpm = groupxpm;
3500 atci->maskXpm = groupxpmmask;
3501 atci->iconXpmOpen = groupxpm;
3502 atci->maskXpmOpen = groupxpmmask;
3503 atci->menuCommand = NULL;
3504 g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3505 _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3508 atci = g_new0( AddressTypeControlItem, 1 );
3509 atci->objectType = ADDR_ITEM_FOLDER;
3510 atci->interfaceType = ADDR_IF_BOOK;
3511 atci->showInTree = TRUE;
3512 atci->treeExpand = FALSE;
3513 atci->treeLeaf = FALSE;
3514 atci->displayName = _( "Folder" );
3515 atci->iconXpm = folderxpm;
3516 atci->maskXpm = folderxpmmask;
3517 atci->iconXpmOpen = folderopenxpm;
3518 atci->maskXpmOpen = folderopenxpmmask;
3519 atci->menuCommand = NULL;
3520 g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3521 _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3524 atci = g_new0( AddressTypeControlItem, 1 );
3525 atci->objectType = ADDR_VCARD;
3526 atci->interfaceType = ADDR_IF_VCARD;
3527 atci->showInTree = TRUE;
3528 atci->treeExpand = TRUE;
3529 atci->treeLeaf = TRUE;
3530 atci->displayName = _( "vCard" );
3531 atci->iconXpm = vcardxpm;
3532 atci->maskXpm = vcardxpmmask;
3533 atci->iconXpmOpen = vcardxpm;
3534 atci->maskXpmOpen = vcardxpmmask;
3535 atci->menuCommand = "/File/New vCard";
3536 g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3537 _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3540 atci = g_new0( AddressTypeControlItem, 1 );
3541 atci->objectType = ADDR_JPILOT;
3542 atci->interfaceType = ADDR_IF_JPILOT;
3543 atci->showInTree = TRUE;
3544 atci->treeExpand = TRUE;
3545 atci->treeLeaf = FALSE;
3546 atci->displayName = _( "JPilot" );
3547 atci->iconXpm = jpilotxpm;
3548 atci->maskXpm = jpilotxpmmask;
3549 atci->iconXpmOpen = jpilotxpm;
3550 atci->maskXpmOpen = jpilotxpmmask;
3551 atci->menuCommand = "/File/New JPilot";
3552 g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3553 _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3556 atci = g_new0( AddressTypeControlItem, 1 );
3557 atci->objectType = ADDR_CATEGORY;
3558 atci->interfaceType = ADDR_IF_JPILOT;
3559 atci->showInTree = TRUE;
3560 atci->treeExpand = TRUE;
3561 atci->treeLeaf = TRUE;
3562 atci->displayName = _( "JPilot" );
3563 atci->iconXpm = categoryxpm;
3564 atci->maskXpm = categoryxpmmask;
3565 atci->iconXpmOpen = categoryxpm;
3566 atci->maskXpmOpen = categoryxpmmask;
3567 atci->menuCommand = NULL;
3568 g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3569 _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3572 atci = g_new0( AddressTypeControlItem, 1 );
3573 atci->objectType = ADDR_LDAP;
3574 atci->interfaceType = ADDR_IF_LDAP;
3575 atci->showInTree = TRUE;
3576 atci->treeExpand = TRUE;
3577 atci->treeLeaf = TRUE;
3578 atci->displayName = _( "LDAP Server" );
3579 atci->iconXpm = ldapxpm;
3580 atci->maskXpm = ldapxpmmask;
3581 atci->iconXpmOpen = ldapxpm;
3582 atci->maskXpmOpen = ldapxpmmask;
3583 atci->menuCommand = "/File/New Server";
3584 g_hash_table_insert( _addressBookTypeHash_, &atci->objectType, atci );
3585 _addressBookTypeList_ = g_list_append( _addressBookTypeList_, atci );
3590 * Search for specified object type.
3592 AddressTypeControlItem *addrbookctl_lookup( gint ot ) {
3594 return ( AddressTypeControlItem * ) g_hash_table_lookup( _addressBookTypeHash_, &objType );
3598 * Search for specified interface type.
3600 AddressTypeControlItem *addrbookctl_lookup_iface( AddressIfType ifType ) {
3601 GList *node = _addressBookTypeList_;
3603 AddressTypeControlItem *atci = node->data;
3604 if( atci->interfaceType == ifType ) return atci;
3605 node = g_list_next( node );
3610 static void addrbookctl_free_address( AddressObject *obj ) {
3611 g_free( obj->name );
3612 obj->type = ADDR_NONE;
3616 static void addrbookctl_free_interface( AdapterInterface *adapter ) {
3617 addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
3618 adapter->interface = NULL;
3619 adapter->interfaceType = ADDR_IF_NONE;
3620 adapter->atci = NULL;
3621 adapter->enabled = FALSE;
3622 adapter->haveLibrary = FALSE;
3623 adapter->treeNode = NULL;
3627 static void addrbookctl_free_datasource( AdapterDSource *adapter ) {
3628 addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
3629 adapter->dataSource = NULL;
3630 adapter->subType = ADDR_NONE;
3634 static void addrbookctl_free_folder( AdapterFolder *adapter ) {
3635 addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
3636 adapter->itemFolder = NULL;
3640 static void addrbookctl_free_group( AdapterGroup *adapter ) {
3641 addrbookctl_free_address( ADDRESS_OBJECT(adapter) );
3642 adapter->itemGroup = NULL;
3647 * Build GUI interface list.
3649 void addrbookctl_build_iflist() {
3650 AddressTypeControlItem *atci;
3651 AdapterInterface *adapter;
3654 if( _addressIndex_ == NULL ) {
3655 _addressIndex_ = addrindex_create_index();
3656 if( _clipBoard_ == NULL ) {
3657 _clipBoard_ = addrclip_create();
3659 addrclip_set_index( _clipBoard_, _addressIndex_ );
3661 _addressInterfaceList_ = NULL;
3662 list = addrindex_get_interface_list( _addressIndex_ );
3664 AddressInterface *interface = list->data;
3665 atci = addrbookctl_lookup_iface( interface->type );
3667 adapter = g_new0( AdapterInterface, 1 );
3668 adapter->interfaceType = interface->type;
3669 adapter->atci = atci;
3670 adapter->interface = interface;
3671 adapter->treeNode = NULL;
3672 adapter->enabled = TRUE;
3673 adapter->haveLibrary = interface->haveLibrary;
3674 ADDRESS_OBJECT(adapter)->type = ADDR_INTERFACE;
3675 ADDRESS_OBJECT_NAME(adapter) = g_strdup( atci->displayName );
3676 _addressInterfaceList_ = g_list_append( _addressInterfaceList_, adapter );
3678 list = g_list_next( list );
3682 void addrbookctl_free_selection( GList *list ) {
3685 AdapterInterface *adapter = node->data;
3687 node = g_list_next( node );
3689 g_list_free( list );
3693 * Find GUI interface type specified interface type.
3694 * Return: Interface item, or NULL if not found.
3696 AdapterInterface *addrbookctl_find_interface( AddressIfType ifType ) {
3697 GList *node = _addressInterfaceList_;
3699 AdapterInterface *adapter = node->data;
3700 if( adapter->interfaceType == ifType ) return adapter;
3701 node = g_list_next( node );
3707 * Build interface list selection.
3709 void addrbookctl_build_ifselect() {
3710 GList *newList = NULL;
3715 gchar *endptr = NULL;
3717 AdapterInterface *adapter;
3720 selectStr = g_strdup( ADDRESSBOOK_IFACE_SELECTION );
3723 splitStr = g_strsplit( selectStr, ",", -1 );
3724 for( i = 0; i < ADDRESSBOOK_MAX_IFACE; i++ ) {
3726 /* printf( "%d : %s\n", i, splitStr[i] ); */
3727 ifType = strtol( splitStr[i], &endptr, 10 );
3730 if( strcmp( endptr, "/n" ) == 0 ) {
3734 /* printf( "\t%d : %s\n", ifType, enabled ? "yes" : "no" ); */
3735 adapter = addrbookctl_find_interface( ifType );
3737 newList = g_list_append( newList, adapter );
3744 /* printf( "i=%d\n", i ); */
3745 g_strfreev( splitStr );
3746 g_free( selectStr );
3748 /* Replace existing list */
3749 mgu_clear_list( _addressIFaceSelection_ );
3750 g_list_free( _addressIFaceSelection_ );
3751 _addressIFaceSelection_ = newList;
3756 /* **********************************************************************
3757 * Add sender to address book.
3758 * ***********************************************************************
3762 * This function is used by the Add sender to address book function.
3764 gboolean addressbook_add_contact( const gchar *name, const gchar *address, const gchar *remarks ) {
3765 debug_print( "addressbook_add_contact: name/address: %s - %s\n", name, address );
3766 if( addressadd_selection( _addressIndex_, name, address, remarks ) ) {
3767 debug_print( "addressbook_add_contact - added\n" );
3768 addressbook_refresh();
3773 /* **********************************************************************
3774 * Address completion support.
3775 * ***********************************************************************
3779 * This function is used by the address completion function to load
3781 * Enter: callBackFunc Function to be called when an address is
3783 * Return: TRUE if data loaded, FALSE if address index not loaded.
3785 gboolean addressbook_load_completion( gint (*callBackFunc) ( const gchar *, const gchar *, const gchar * ) ) {
3786 AddressDataSource *ds;
3787 GList *nodeIf, *nodeDS;
3788 GList *listP, *nodeP;
3790 gchar *sName, *sAddress, *sAlias, *sFriendly;
3792 debug_print( "addressbook_load_completion\n" );
3794 if( _addressIndex_ == NULL ) return FALSE;
3796 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3798 AddressInterface *interface = nodeIf->data;
3799 nodeDS = interface->listSource;
3803 /* Read address book */
3804 if( addrindex_ds_get_modify_flag( ds ) ) {
3805 addrindex_ds_read_data( ds );
3808 if( ! addrindex_ds_get_read_flag( ds ) ) {
3809 addrindex_ds_read_data( ds );
3812 /* Get all persons */
3813 listP = addrindex_ds_get_all_persons( ds );
3816 ItemPerson *person = nodeP->data;
3817 nodeM = person->listEMail;
3819 /* Figure out name to use */
3820 sName = person->nickName;
3821 if( sName == NULL || *sName == '\0' ) {
3822 sName = ADDRITEM_NAME(person);
3825 /* Process each E-Mail address */
3827 ItemEMail *email = nodeM->data;
3830 sAddress = email->address;
3831 if( sAddress || *sAddress != '\0' ) {
3832 sAlias = ADDRITEM_NAME(email);
3833 if( sAlias && *sAlias != '\0' ) {
3836 ( callBackFunc ) ( sFriendly, sAddress, sName );
3839 nodeM = g_list_next( nodeM );
3841 nodeP = g_list_next( nodeP );
3843 /* Free up the list */
3844 g_list_free( listP );
3846 nodeDS = g_list_next( nodeDS );
3848 nodeIf = g_list_next( nodeIf );
3850 debug_print( "addressbook_load_completion... done\n" );
3855 /* **********************************************************************
3857 * ***********************************************************************
3863 static void addressbook_import_ldif_cb() {
3864 AddressDataSource *ds = NULL;
3865 AdapterDSource *ads = NULL;
3866 AddressBookFile *abf = NULL;
3867 AdapterInterface *adapter;
3868 GtkCTreeNode *newNode;
3870 adapter = addrbookctl_find_interface( ADDR_IF_BOOK );
3872 if( adapter->treeNode ) {
3873 abf = addressbook_imp_ldif( _addressIndex_ );
3875 ds = addrindex_index_add_datasource(
3876 _addressIndex_, ADDR_IF_BOOK, abf );
3877 ads = addressbook_create_ds_adapter(
3878 ds, ADDR_BOOK, NULL );
3879 addressbook_ads_set_name(
3880 ads, addrbook_get_name( abf ) );
3881 newNode = addressbook_add_object(
3883 ADDRESS_OBJECT(ads) );
3886 GTK_CTREE(addrbook.ctree),
3888 addrbook.treeSelected = newNode;
3891 /* Notify address completion */
3892 invalidate_address_completion();
3901 static void addressbook_import_mutt_cb() {
3902 AddressDataSource *ds = NULL;
3903 AdapterDSource *ads = NULL;
3904 AddressBookFile *abf = NULL;
3905 AdapterInterface *adapter;
3906 GtkCTreeNode *newNode;
3908 adapter = addrbookctl_find_interface( ADDR_IF_BOOK );
3910 if( adapter->treeNode ) {
3911 abf = addressbook_imp_mutt( _addressIndex_ );
3913 ds = addrindex_index_add_datasource(
3914 _addressIndex_, ADDR_IF_BOOK, abf );
3915 ads = addressbook_create_ds_adapter(
3916 ds, ADDR_BOOK, NULL );
3917 addressbook_ads_set_name(
3918 ads, addrbook_get_name( abf ) );
3919 newNode = addressbook_add_object(
3921 ADDRESS_OBJECT(ads) );
3924 GTK_CTREE(addrbook.ctree),
3926 addrbook.treeSelected = newNode;
3929 /* Notify address completion */
3930 invalidate_address_completion();
3939 static void addressbook_import_pine_cb() {
3940 AddressDataSource *ds = NULL;
3941 AdapterDSource *ads = NULL;
3942 AddressBookFile *abf = NULL;
3943 AdapterInterface *adapter;
3944 GtkCTreeNode *newNode;
3946 adapter = addrbookctl_find_interface( ADDR_IF_BOOK );
3948 if( adapter->treeNode ) {
3949 abf = addressbook_imp_pine( _addressIndex_ );
3951 ds = addrindex_index_add_datasource(
3952 _addressIndex_, ADDR_IF_BOOK, abf );
3953 ads = addressbook_create_ds_adapter(
3954 ds, ADDR_BOOK, NULL );
3955 addressbook_ads_set_name(
3956 ads, addrbook_get_name( abf ) );
3957 newNode = addressbook_add_object(
3959 ADDRESS_OBJECT(ads) );
3962 GTK_CTREE(addrbook.ctree),
3964 addrbook.treeSelected = newNode;
3967 /* Notify address completion */
3968 invalidate_address_completion();
3975 * Harvest addresses.
3976 * Enter: folderItem Folder to import.
3977 * sourceInd Source indicator: FALSE - Folder, TRUE - Messages.
3978 * msgList List of message numbers, or NULL to process folder.
3980 void addressbook_harvest(
3981 FolderItem *folderItem, gboolean sourceInd, GList *msgList )
3983 AddressDataSource *ds = NULL;
3984 AdapterDSource *ads = NULL;
3985 AddressBookFile *abf = NULL;
3986 AdapterInterface *adapter;
3987 GtkCTreeNode *newNode;
3989 abf = addrgather_dlg_execute(
3990 folderItem, _addressIndex_, sourceInd, msgList );
3992 ds = addrindex_index_add_datasource(
3993 _addressIndex_, ADDR_IF_BOOK, abf );
3995 adapter = addrbookctl_find_interface( ADDR_IF_BOOK );
3997 if( adapter->treeNode ) {
3998 ads = addressbook_create_ds_adapter(
3999 ds, ADDR_BOOK, addrbook_get_name( abf ) );
4000 newNode = addressbook_add_object(
4002 ADDRESS_OBJECT(ads) );
4006 /* Notify address completion */
4007 invalidate_address_completion();
4014 static void addressbook_export_html_cb( void ) {
4015 GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
4017 AddressDataSource *ds = NULL;
4018 AddrBookBase *adbase;
4019 AddressCache *cache;
4020 GtkCTreeNode *node = NULL;
4022 if( ! addrbook.treeSelected ) return;
4023 node = addrbook.treeSelected;
4024 if( GTK_CTREE_ROW(node)->level == 1 ) return;
4025 obj = gtk_ctree_node_get_row_data( ctree, node );
4026 if( obj == NULL ) return;
4028 ds = addressbook_find_datasource( node );
4029 if( ds == NULL ) return;
4030 adbase = ( AddrBookBase * ) ds->rawDataSource;
4031 cache = adbase->addressCache;
4032 addressbook_exp_html( cache );