2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
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 3 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, see <http://www.gnu.org/licenses/>.
27 #include <glib/gi18n.h>
28 #include <gdk/gdkkeysyms.h>
32 #include <sys/types.h>
36 #include "addressbook.h"
37 #include "manage_window.h"
38 #include "prefs_common.h"
39 #include "alertpanel.h"
40 #include "inputdialog.h"
42 #include "stock_pixmap.h"
44 #include "prefs_gtk.h"
50 #include "addr_compl.h"
53 #include "addressitem.h"
55 #include "addrcache.h"
57 #include "addrindex.h"
58 #include "addressadd.h"
59 #include "addrduplicates.h"
60 #include "addressbook_foldersel.h"
62 #include "editvcard.h"
63 #include "editgroup.h"
64 #include "editaddress.h"
66 #include "importldif.h"
67 #include "importmutt.h"
68 #include "importpine.h"
73 #include "editjpilot.h"
78 #include "ldapserver.h"
80 #include "ldapupdate.h"
82 #define ADDRESSBOOK_LDAP_BUSYMSG "Busy"
85 #include "addrquery.h"
86 #include "addrselect.h"
88 #include "addrgather.h"
89 #include "adbookbase.h"
90 #include "exphtmldlg.h"
91 #include "expldifdlg.h"
92 #include "browseldap.h"
93 #include "addrcustomattr.h"
99 } AddressIndexColumns;
107 } AddressListColumns;
110 AddressBookFile *book;
118 AddressDataSource *book;
122 static gchar *list_titles[] = { N_("Name"),
126 #define COL_NAME_WIDTH 164
127 #define COL_ADDRESS_WIDTH 156
129 #define COL_FOLDER_WIDTH 170
130 #define ADDRESSBOOK_WIDTH 640
131 #define ADDRESSBOOK_HEIGHT 360
133 #define ADDRESSBOOK_MSGBUF_SIZE 2048
135 static GdkPixmap *folderxpm;
136 static GdkBitmap *folderxpmmask;
137 static GdkPixmap *folderopenxpm;
138 static GdkBitmap *folderopenxpmmask;
139 static GdkPixmap *groupxpm;
140 static GdkBitmap *groupxpmmask;
141 static GdkPixmap *interfacexpm;
142 static GdkBitmap *interfacexpmmask;
143 static GdkPixmap *bookxpm;
144 static GdkBitmap *bookxpmmask;
145 static GdkPixmap *addressxpm;
146 static GdkBitmap *addressxpmmask;
147 static GdkPixmap *vcardxpm;
148 static GdkBitmap *vcardxpmmask;
149 static GdkPixmap *jpilotxpm;
150 static GdkBitmap *jpilotxpmmask;
151 static GdkPixmap *categoryxpm;
152 static GdkBitmap *categoryxpmmask;
153 static GdkPixmap *ldapxpm;
154 static GdkBitmap *ldapxpmmask;
155 static GdkPixmap *addrsearchxpm;
156 static GdkPixmap *addrsearchxpmmask;
159 static gchar addressbook_msgbuf[ ADDRESSBOOK_MSGBUF_SIZE ];
161 /* Address list selection */
162 static AddrSelectList *_addressSelect_ = NULL;
163 static AddressClipboard *_clipBoard_ = NULL;
165 /* Address index file and interfaces */
166 static AddressIndex *_addressIndex_ = NULL;
167 static GList *_addressInterfaceList_ = NULL;
168 static GList *_addressIFaceSelection_ = NULL;
169 #define ADDRESSBOOK_IFACE_SELECTION "1/y,3/y,4/y,2/n"
171 static AddressBook_win addrbook;
173 static GHashTable *_addressBookTypeHash_ = NULL;
174 static GList *_addressBookTypeList_ = NULL;
176 static void addressbook_new_address_from_book_post_cb( ItemPerson *person );
177 static void addressbook_new_address_from_folder_post_cb( ItemPerson *person );
178 static void addressbook_edit_address_post_cb( ItemPerson *person );
180 static void addressbook_create (void);
181 static gint addressbook_close (void);
182 static void addressbook_button_set_sensitive (void);
184 static gboolean address_index_has_focus = FALSE;
185 static gboolean address_list_has_focus = FALSE;
187 /* callback functions */
188 static void addressbook_del_clicked (GtkButton *button,
190 static void addressbook_reg_clicked (GtkButton *button,
192 static void addressbook_to_clicked (GtkButton *button,
194 static void addressbook_lup_clicked (GtkButton *button,
196 static void addressbook_close_clicked (GtkButton *button,
199 static void addressbook_tree_selected (GtkCMCTree *ctree,
200 GtkCMCTreeNode *node,
203 static void addressbook_select_row_tree (GtkCMCTree *ctree,
204 GtkCMCTreeNode *node,
207 static void addressbook_list_row_selected (GtkCMCTree *clist,
208 GtkCMCTreeNode *node,
211 static void addressbook_list_row_unselected (GtkCMCTree *clist,
212 GtkCMCTreeNode *node,
215 static void addressbook_person_expand_node (GtkCMCTree *ctree,
218 static void addressbook_person_collapse_node (GtkCMCTree *ctree,
222 static gboolean addressbook_list_button_pressed (GtkWidget *widget,
223 GdkEventButton *event,
225 static gboolean addressbook_list_button_released(GtkWidget *widget,
226 GdkEventButton *event,
228 static gboolean addressbook_tree_button_pressed (GtkWidget *ctree,
229 GdkEventButton *event,
231 static gboolean addressbook_tree_button_released(GtkWidget *ctree,
232 GdkEventButton *event,
235 static void addressbook_new_folder_cb (GtkAction *action,
237 static void addressbook_new_group_cb (GtkAction *action,
239 static void addressbook_treenode_edit_cb (GtkAction *action,
241 static void addressbook_treenode_delete_cb (GtkAction *action,
244 static void addressbook_change_node_name (GtkCMCTreeNode *node,
247 static void addressbook_new_address_cb (GtkAction *action,
249 static void addressbook_edit_address_cb (GtkAction *action,
251 static void addressbook_delete_address_cb (GtkAction *action,
254 static void close_cb (GtkAction *action,
256 static void addressbook_file_save_cb (GtkAction *action,
259 /* Data source edit stuff */
260 static void addressbook_new_book_cb (GtkAction *action,
262 static void addressbook_new_vcard_cb (GtkAction *action,
266 static void addressbook_new_jpilot_cb (GtkAction *action,
271 static void addressbook_new_ldap_cb (GtkAction *action,
275 static void addressbook_set_clist (AddressObject *obj,
278 static void addressbook_load_tree (void);
279 void addressbook_read_file (void);
281 static GtkCMCTreeNode *addressbook_add_object (GtkCMCTreeNode *node,
283 static void addressbook_treenode_remove_item ( void );
285 static AddressDataSource *addressbook_find_datasource
286 (GtkCMCTreeNode *node );
288 static AddressBookFile *addressbook_get_book_file(void);
290 static GtkCMCTreeNode *addressbook_node_add_folder
291 (GtkCMCTreeNode *node,
292 AddressDataSource *ds,
293 ItemFolder *itemFolder,
294 AddressObjectType otype);
295 static GtkCMCTreeNode *addressbook_node_add_group (GtkCMCTreeNode *node,
296 AddressDataSource *ds,
297 ItemGroup *itemGroup);
298 static void addressbook_tree_remove_children (GtkCMCTree *ctree,
299 GtkCMCTreeNode *parent);
300 static void addressbook_move_nodes_up (GtkCMCTree *ctree,
301 GtkCMCTreeNode *node);
302 static GtkCMCTreeNode *addressbook_find_group_node (GtkCMCTreeNode *parent,
304 static gboolean addressbook_entry_key_pressed (GtkWidget *widget,
307 static gint addressbook_treenode_compare_func (GtkCMCList *clist,
310 static void addressbook_folder_load_one_person (GtkCMCTree *clist,
312 AddressTypeControlItem *atci,
313 AddressTypeControlItem *atciMail);
314 static void addressbook_folder_refresh_one_person(GtkCMCTree *clist,
316 static void addressbook_folder_remove_one_person(GtkCMCTree *clist,
318 static void addressbook_folder_remove_node (GtkCMCTree *clist,
319 GtkCMCTreeNode *node);
321 static void addressbook_edit_address( gpointer data, guint action, GtkWidget *widget,
322 gboolean force_focus );
324 /* LUT's and IF stuff */
325 static void addressbook_free_treenode ( gpointer data );
326 static AddressTypeControlItem *addrbookctl_lookup (gint ot);
327 static AddressTypeControlItem *addrbookctl_lookup_iface(AddressIfType ifType);
329 static void addrbookctl_build_map (GtkWidget *window);
330 static void addrbookctl_build_iflist (void);
331 static AdapterInterface *addrbookctl_find_interface (AddressIfType ifType);
332 static void addrbookctl_build_ifselect (void);
334 static void addrbookctl_free_interface (AdapterInterface *adapter);
335 static void addrbookctl_free_datasource (AdapterDSource *adapter);
336 static void addrbookctl_free_folder (AdapterFolder *adapter);
337 static void addrbookctl_free_group (AdapterGroup *adapter);
339 static void addressbook_list_select_clear ( void );
340 static void addressbook_list_select_add ( AddrItemObject *aio,
341 AddressDataSource *ds );
342 static void addressbook_list_select_remove ( AddrItemObject *aio );
344 static void addressbook_import_ldif_cb ( GtkAction *action, gpointer data );
345 static void addressbook_find_duplicates_cb ( GtkAction *action, gpointer data );
346 static void addressbook_edit_custom_attr_cb ( GtkAction *action, gpointer data );
347 static void addressbook_import_mutt_cb ( GtkAction *action, gpointer data );
348 static void addressbook_import_pine_cb ( GtkAction *action, gpointer data );
349 static void addressbook_export_html_cb ( GtkAction *action, gpointer data );
350 static void addressbook_export_ldif_cb ( GtkAction *action, gpointer data );
351 static void addressbook_select_all_cb ( GtkAction *action, gpointer data );
352 static void addressbook_clip_cut_cb ( GtkAction *action, gpointer data );
353 static void addressbook_clip_copy_cb ( GtkAction *action, gpointer data );
354 static void addressbook_clip_paste_cb ( GtkAction *action, gpointer data );
355 static void addressbook_treenode_cut_cb ( GtkAction *action, gpointer data );
356 static void addressbook_treenode_copy_cb ( GtkAction *action, gpointer data );
357 static void addressbook_treenode_paste_cb ( GtkAction *action, gpointer data );
359 static void addressbook_mail_to_cb ( GtkAction *action, gpointer data );
362 static void addressbook_browse_entry_cb ( GtkAction *action, gpointer data );
364 static void addressbook_edit_clicked(GtkButton *button, gpointer data);
366 static void addressbook_start_drag(GtkWidget *widget, gint button,
369 static void addressbook_drag_data_get(GtkWidget *widget,
370 GdkDragContext *drag_context,
371 GtkSelectionData *selection_data,
375 static gboolean addressbook_drag_motion_cb(GtkWidget *widget,
376 GdkDragContext *context,
381 static void addressbook_drag_leave_cb(GtkWidget *widget,
382 GdkDragContext *context,
385 static void addressbook_drag_received_cb(GtkWidget *widget,
386 GdkDragContext *drag_context,
389 GtkSelectionData *data,
393 static void addressbook_list_menu_setup( void );
395 static GtkTargetEntry addressbook_drag_types[] =
397 {"claws-mail/internal", GTK_TARGET_SAME_APP, TARGET_DUMMY}
400 static GtkTargetList *addressbook_target_list = NULL;
402 static void about_show_cb(GtkAction *action, gpointer data)
407 static GtkActionEntry addressbook_entries[] =
409 {"Menu", NULL, "Menu" },
411 {"Book", NULL, N_("_Book") },
412 {"Address", NULL, N_("_Edit") },
413 {"Tools", NULL, N_("_Tools") },
414 {"Help", NULL, N_("_Help") },
417 {"Book/NewBook", NULL, N_("New _Book"), "<control>B", NULL, G_CALLBACK(addressbook_new_book_cb) },
418 {"Book/NewFolder", NULL, N_("New _Folder"), "<control>R", NULL, G_CALLBACK(addressbook_new_folder_cb) },
419 {"Book/NewVCard", NULL, N_("New _vCard"), "<control><shift>D", NULL, G_CALLBACK(addressbook_new_vcard_cb) },
423 {"Book/NewJPilot", NULL, N_("New _JPilot"), "<control>J", NULL, G_CALLBACK(addressbook_new_jpilot_cb) },
426 {"Book/NewLDAPServer", NULL, N_("New LDAP _Server"), "<control><shift>S", NULL, G_CALLBACK(addressbook_new_ldap_cb) },
428 {"Book/---", NULL, "---", NULL, NULL, NULL },
430 {"Book/EditBook", NULL, N_("_Edit book"), NULL, NULL, G_CALLBACK(addressbook_treenode_edit_cb) },
431 {"Book/DeleteBook", NULL, N_("_Delete book"), NULL, NULL, G_CALLBACK(addressbook_treenode_delete_cb) },
432 /* {"Book/---", NULL, "---", NULL, NULL, NULL }, */
433 {"Book/Save", NULL, N_("_Save"), "<control>S", NULL, G_CALLBACK(addressbook_file_save_cb) },
434 {"Book/Close", NULL, N_("_Close"), "<control>W", NULL, G_CALLBACK(close_cb) },
437 {"Address/SelectAll", NULL, N_("_Select all"), "<control>A", NULL, G_CALLBACK(addressbook_select_all_cb) },
438 {"Address/---", NULL, "---", NULL, NULL, NULL },
439 {"Address/Cut", NULL, N_("C_ut"), "<control>X", NULL, G_CALLBACK(addressbook_clip_cut_cb) },
440 {"Address/Copy", NULL, N_("_Copy"), "<control>C", NULL, G_CALLBACK(addressbook_clip_copy_cb) },
441 {"Address/Paste", NULL, N_("_Paste"), "<control>V", NULL, G_CALLBACK(addressbook_clip_paste_cb) },
442 /* {"Address/---", NULL, "---", NULL, NULL, NULL }, */
443 {"Address/Edit", NULL, N_("_Edit"), "<control>Return", NULL, G_CALLBACK(addressbook_edit_address_cb) },
444 {"Address/Delete", NULL, N_("_Delete"), "<control>D", NULL, G_CALLBACK(addressbook_delete_address_cb) },
445 /* {"Address/---", NULL, "---", NULL, NULL, NULL }, */
446 {"Address/NewAddress", NULL, N_("New _Address"), "<control>N", NULL, G_CALLBACK(addressbook_new_address_cb) },
447 {"Address/NewGroup", NULL, N_("New _Group"), "<control>G", NULL, G_CALLBACK(addressbook_new_group_cb) },
448 /* {"Address/---", NULL, "---", NULL, NULL, NULL }, */
449 {"Address/Mailto", NULL, N_("_Mail To"), "<control>M", NULL, G_CALLBACK(addressbook_mail_to_cb) },
453 {"Tools/ImportLDIF", NULL, N_("Import _LDIF file..."), NULL, NULL, G_CALLBACK(addressbook_import_ldif_cb) },
454 {"Tools/ImportMutt", NULL, N_("Import M_utt file..."), NULL, NULL, G_CALLBACK(addressbook_import_mutt_cb) },
455 {"Tools/ImportPine", NULL, N_("Import _Pine file..."), NULL, NULL, G_CALLBACK(addressbook_import_pine_cb) },
456 {"Tools/---", NULL, "---", NULL, NULL, NULL },
457 {"Tools/ExportHTML", NULL, N_("Export _HTML..."), NULL, NULL, G_CALLBACK(addressbook_export_html_cb) },
458 {"Tools/ExportLDIF", NULL, N_("Export LDI_F..."), NULL, NULL, G_CALLBACK(addressbook_export_ldif_cb) },
459 /* {"Tools/---", NULL, "---", NULL, NULL, NULL },*/
460 {"Tools/FindDuplicates", NULL, N_("Find duplicates..."), NULL, NULL, G_CALLBACK(addressbook_find_duplicates_cb) },
461 {"Tools/EditAttrs", NULL, N_("Edit custom attributes..."), NULL, NULL, G_CALLBACK(addressbook_edit_custom_attr_cb) },
464 {"Help/About", NULL, N_("_About"), NULL, NULL, G_CALLBACK(about_show_cb) },
468 static GtkActionEntry addressbook_tree_popup_entries[] =
470 {"ABTreePopup", NULL, "ABTreePopup" },
471 {"ABTreePopup/EditBook", NULL, N_("_Edit"), NULL, NULL, G_CALLBACK(addressbook_treenode_edit_cb) },
472 {"ABTreePopup/DeleteBook", NULL, N_("_Delete"), NULL, NULL, G_CALLBACK(addressbook_treenode_delete_cb) },
473 {"ABTreePopup/---", NULL, "---", NULL, NULL, NULL },
474 {"ABTreePopup/NewBook", NULL, N_("New _Book"), NULL, NULL, G_CALLBACK(addressbook_new_book_cb) },
475 {"ABTreePopup/NewFolder", NULL, N_("New _Folder"), NULL, NULL, G_CALLBACK(addressbook_new_folder_cb) },
476 {"ABTreePopup/NewGroup", NULL, N_("New _Group"), NULL, NULL, G_CALLBACK(addressbook_new_group_cb) },
477 /* {"ABTreePopup/---", NULL, "---", NULL, NULL, NULL }, */
478 {"ABTreePopup/Cut", NULL, N_("C_ut"), NULL, NULL, G_CALLBACK(addressbook_treenode_cut_cb) },
479 {"ABTreePopup/Copy", NULL, N_("_Copy"), NULL, NULL, G_CALLBACK(addressbook_treenode_copy_cb) },
480 {"ABTreePopup/Paste", NULL, N_("_Paste"), NULL, NULL, G_CALLBACK(addressbook_treenode_paste_cb) },
483 static GtkActionEntry addressbook_list_popup_entries[] =
485 {"ABListPopup", NULL, "ABListPopup" },
486 {"ABListPopup/SelectAll", NULL, N_("_Select all"), NULL, NULL, G_CALLBACK(addressbook_select_all_cb) },
487 {"ABListPopup/---", NULL, "---", NULL, NULL, NULL },
488 {"ABListPopup/Edit", NULL, N_("_Edit"), NULL, NULL, G_CALLBACK(addressbook_edit_address_cb) },
489 {"ABListPopup/Delete", NULL, N_("_Delete"), NULL, NULL, G_CALLBACK(addressbook_delete_address_cb) },
490 /* {"ABListPopup/---", NULL, "---", NULL, NULL, NULL }, */
491 {"ABListPopup/NewAddress", NULL, N_("New _Address"), NULL, NULL, G_CALLBACK(addressbook_new_address_cb) },
492 {"ABListPopup/NewGroup", NULL, N_("New _Group"), NULL, NULL, G_CALLBACK(addressbook_new_group_cb) },
493 /* {"ABListPopup/---", NULL, "---", NULL, NULL, NULL }, */
494 {"ABListPopup/Cut", NULL, N_("C_ut"), NULL, NULL, G_CALLBACK(addressbook_clip_cut_cb) },
495 {"ABListPopup/Copy", NULL, N_("_Copy"), NULL, NULL, G_CALLBACK(addressbook_clip_copy_cb) },
496 {"ABListPopup/Paste", NULL, N_("_Paste"), NULL, NULL, G_CALLBACK(addressbook_clip_paste_cb) },
497 /* {"ABListPopup/---", NULL, "---", NULL, NULL, NULL }, */
498 {"ABListPopup/Mailto", NULL, N_("_Mail To"), NULL, NULL, G_CALLBACK(addressbook_mail_to_cb) },
500 {"ABListPopup/BrowseEntry", NULL, N_("_Browse Entry"), NULL, NULL, G_CALLBACK(addressbook_browse_entry_cb) },
505 * Structure of error message table.
507 typedef struct _ErrMsgTableEntry ErrMsgTableEntry;
508 struct _ErrMsgTableEntry {
513 static gchar *_errMsgUnknown_ = N_( "Unknown" );
516 * Lookup table of error messages for general errors. Note that a NULL
517 * description signifies the end of the table.
519 static ErrMsgTableEntry _lutErrorsGeneral_[] = {
520 { MGU_SUCCESS, N_("Success") },
521 { MGU_BAD_ARGS, N_("Bad arguments") },
522 { MGU_NO_FILE, N_("File not specified") },
523 { MGU_OPEN_FILE, N_("Error opening file") },
524 { MGU_ERROR_READ, N_("Error reading file") },
525 { MGU_EOF, N_("End of file encountered") },
526 { MGU_OO_MEMORY, N_("Error allocating memory") },
527 { MGU_BAD_FORMAT, N_("Bad file format") },
528 { MGU_ERROR_WRITE, N_("Error writing to file") },
529 { MGU_OPEN_DIRECTORY, N_("Error opening directory") },
530 { MGU_NO_PATH, N_("No path specified") },
536 * Lookup table of error messages for LDAP errors.
538 static ErrMsgTableEntry _lutErrorsLDAP_[] = {
539 { LDAPRC_SUCCESS, N_("Success") },
540 { LDAPRC_CONNECT, N_("Error connecting to LDAP server") },
541 { LDAPRC_INIT, N_("Error initializing LDAP") },
542 { LDAPRC_BIND, N_("Error binding to LDAP server") },
543 { LDAPRC_SEARCH, N_("Error searching LDAP database") },
544 { LDAPRC_TIMEOUT, N_("Timeout performing LDAP operation") },
545 { LDAPRC_CRITERIA, N_("Error in LDAP search criteria") },
546 { LDAPRC_NOENTRIES, N_("No LDAP entries found for search criteria") },
547 { LDAPRC_STOP_FLAG, N_("LDAP search terminated on request") },
548 { LDAPRC_TLS, N_("Error starting TLS connection") },
549 { LDAPRC_NODN, N_("Distinguished Name (dn) is missing") },
550 { LDAPRC_NAMING_VIOLATION, N_("Missing required information") },
551 { LDAPRC_ALREADY_EXIST, N_("Another contact exists with that key") },
552 { LDAPRC_STRONG_AUTH, N_("Strong(er) authentication required") },
558 * Lookup message for specified error code.
559 * \param lut Lookup table.
560 * \param code Code to lookup.
561 * \return Description associated to code.
563 static gchar *addressbook_err2string( ErrMsgTableEntry lut[], gint code ) {
565 ErrMsgTableEntry entry;
568 for( i = 0; ; i++ ) {
570 if( entry.description == NULL ) break;
571 if( entry.code == code ) {
572 desc = entry.description;
577 desc = _errMsgUnknown_;
582 static gboolean lastCanLookup = FALSE;
584 static void addressbook_show_buttons(gboolean add_and_delete, gboolean lookup, gboolean mail_ops)
586 if (add_and_delete) {
587 gtk_widget_show(addrbook.edit_btn);
588 gtk_widget_show(addrbook.del_btn);
589 gtk_widget_show(addrbook.reg_btn);
591 gtk_widget_hide(addrbook.edit_btn);
592 gtk_widget_hide(addrbook.del_btn);
593 gtk_widget_hide(addrbook.reg_btn);
597 gtk_widget_show(addrbook.lup_btn);
598 gtk_widget_show(addrbook.entry);
599 gtk_widget_show(addrbook.label);
601 gtk_widget_hide(addrbook.lup_btn);
602 gtk_widget_hide(addrbook.entry);
603 gtk_widget_hide(addrbook.label);
606 lastCanLookup = lookup;
609 gtk_widget_show(addrbook.to_btn);
610 gtk_widget_show(addrbook.cc_btn);
611 gtk_widget_show(addrbook.bcc_btn);
613 gtk_widget_hide(addrbook.to_btn);
614 gtk_widget_hide(addrbook.cc_btn);
615 gtk_widget_hide(addrbook.bcc_btn);
619 void addressbook_open(Compose *target)
621 /* Initialize all static members */
622 if( _clipBoard_ == NULL ) {
623 _clipBoard_ = addrclip_create();
625 if( _addressIndex_ != NULL ) {
626 addrclip_set_index( _clipBoard_, _addressIndex_ );
628 if( _addressSelect_ == NULL ) {
629 _addressSelect_ = addrselect_list_create();
631 if (!addrbook.window) {
632 addressbook_read_file();
633 addressbook_create();
634 addressbook_load_tree();
635 gtk_sctree_select( GTK_SCTREE(addrbook.ctree),
636 GTK_CMCTREE_NODE(GTK_CMCLIST(addrbook.ctree)->row_list));
639 gtk_widget_hide(addrbook.window);
642 gtk_widget_show_all(addrbook.window);
644 maemo_window_full_screen_if_needed(GTK_WINDOW(addrbook.window));
645 maemo_connect_key_press_to_mainwindow(GTK_WINDOW(addrbook.window));
647 if (!prefs_common.addressbook_use_editaddress_dialog)
648 addressbook_edit_person_widgetset_hide();
650 address_completion_start(addrbook.window);
652 addressbook_show_buttons(target == NULL, lastCanLookup, target != NULL);
653 addressbook_set_target_compose(target);
657 * Destroy addressbook.
659 void addressbook_destroy( void ) {
660 /* Free up address stuff */
661 if( _addressSelect_ != NULL ) {
662 addrselect_list_free( _addressSelect_ );
664 if( _clipBoard_ != NULL ) {
665 addrclip_free( _clipBoard_ );
667 if( _addressIndex_ != NULL ) {
668 addrindex_free_index( _addressIndex_ );
669 addrindex_teardown();
671 _addressSelect_ = NULL;
673 _addressIndex_ = NULL;
676 void addressbook_set_target_compose(Compose *target)
678 addrbook.target_compose = target;
679 addressbook_button_set_sensitive();
682 Compose *addressbook_get_target_compose(void)
684 return addrbook.target_compose;
688 * Refresh addressbook and save to file(s).
690 void addressbook_refresh( void )
692 if (addrbook.window) {
693 if (addrbook.treeSelected) {
694 gtk_sctree_select( GTK_SCTREE(addrbook.ctree),
695 addrbook.treeSelected);
696 addressbook_set_clist(
697 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook.ctree),
698 addrbook.treeSelected),
703 addressbook_export_to_file();
706 static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
708 if (event && event->keyval == GDK_Escape)
710 else if (event && event->keyval == GDK_Delete) {
711 /* TODO: enable deletion when focus is in ctree (needs implementation in _del_clicked() */
712 if ( /* address_index_has_focus || */ address_list_has_focus )
713 addressbook_del_clicked(NULL, NULL);
719 *\brief Save Gtk object size to prefs dataset
721 static void addressbook_size_allocate_cb(GtkWidget *widget,
722 GtkAllocation *allocation)
724 g_return_if_fail(allocation != NULL);
726 prefs_common.addressbookwin_width = allocation->width;
727 prefs_common.addressbookwin_height = allocation->height;
730 static gint sort_column_number = 0;
731 static GtkSortType sort_column_type = GTK_SORT_ASCENDING;
733 static gint list_case_sort(
734 GtkCMCList *clist, gconstpointer ptr1, gconstpointer ptr2 )
736 GtkCMCListRow *row1 = (GtkCMCListRow *) ptr1;
737 GtkCMCListRow *row2 = (GtkCMCListRow *) ptr2;
738 gchar *name1 = NULL, *name2 = NULL;
739 AddrItemObject *aio1 = ((GtkCMCListRow *)ptr1)->data;
740 AddrItemObject *aio2 = ((GtkCMCListRow *)ptr2)->data;
742 if( aio1->type == aio2->type ) {
744 name1 = GTK_CMCELL_TEXT (row1->cell[sort_column_number])->text;
746 name2 = GTK_CMCELL_TEXT (row2->cell[sort_column_number])->text;
747 if( ! name1 ) return ( name2 != NULL );
748 if( ! name2 ) return -1;
749 return g_utf8_collate( name1, name2 );
751 /* Order groups before person */
752 if( aio1->type == ITEMTYPE_GROUP ) {
753 return (sort_column_type==GTK_SORT_ASCENDING) ? -1:+1;
754 } else if( aio2->type == ITEMTYPE_GROUP ) {
755 return (sort_column_type==GTK_SORT_ASCENDING) ? +1:-1;
761 static void addressbook_sort_list(GtkCMCList *clist, const gint col,
762 const GtkSortType sort_type)
765 GtkWidget *hbox, *label, *arrow;
767 sort_column_number = col;
768 sort_column_type = sort_type;
769 gtk_cmclist_set_compare_func(clist, list_case_sort);
770 gtk_cmclist_set_sort_type(clist, sort_type);
771 gtk_cmclist_set_sort_column(clist, col);
773 gtk_cmclist_freeze(clist);
774 gtk_cmclist_sort(clist);
776 for(pos = 0 ; pos < N_LIST_COLS ; pos++) {
777 hbox = gtk_hbox_new(FALSE, 4);
778 label = gtk_label_new(gettext(list_titles[pos]));
779 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
782 arrow = gtk_arrow_new(sort_type == GTK_SORT_ASCENDING ?
783 GTK_ARROW_DOWN : GTK_ARROW_UP, GTK_SHADOW_IN);
784 gtk_box_pack_end(GTK_BOX(hbox), arrow, FALSE, FALSE, 0);
787 gtk_widget_show_all(hbox);
788 gtk_cmclist_set_column_widget(clist, pos, hbox);
791 gtk_cmclist_thaw(clist);
794 static void addressbook_name_clicked(GtkWidget *button, GtkCMCList *clist)
796 static GtkSortType sort_type = GTK_SORT_ASCENDING;
798 sort_type = (sort_type == GTK_SORT_ASCENDING) ? GTK_SORT_DESCENDING :
800 addressbook_sort_list(clist, COL_NAME, sort_type);
803 static void addressbook_address_clicked(GtkWidget *button, GtkCMCList *clist)
805 static GtkSortType sort_type = GTK_SORT_ASCENDING;
807 sort_type = (sort_type == GTK_SORT_ASCENDING) ? GTK_SORT_DESCENDING :
809 addressbook_sort_list(clist, COL_ADDRESS, sort_type);
812 static void addressbook_remarks_clicked(GtkWidget *button, GtkCMCList *clist)
814 static GtkSortType sort_type = GTK_SORT_ASCENDING;
816 sort_type = (sort_type == GTK_SORT_ASCENDING) ? GTK_SORT_DESCENDING :
818 addressbook_sort_list(clist, COL_REMARKS, sort_type);
821 static gboolean addressbook_address_index_focus_evt_in(GtkWidget *widget, GdkEventFocus *event,
824 address_index_has_focus = TRUE;
828 static gboolean addressbook_address_index_focus_evt_out(GtkWidget *widget, GdkEventFocus *event,
831 address_index_has_focus = FALSE;
832 if (!prefs_common.addressbook_use_editaddress_dialog
833 && !address_list_has_focus)
834 addressbook_address_list_disable_some_actions();
838 static gboolean addressbook_address_list_focus_evt_in(GtkWidget *widget, GdkEventFocus *event,
841 address_list_has_focus = TRUE;
845 static gboolean addressbook_address_list_focus_evt_out(GtkWidget *widget, GdkEventFocus *event,
848 address_list_has_focus = FALSE;
849 if (!prefs_common.addressbook_use_editaddress_dialog
850 && !address_index_has_focus)
851 addressbook_address_list_disable_some_actions();
855 /* save hpane and vpane's handle position when it moves */
856 static void addressbook_pane_save_position(void)
859 prefs_common.addressbook_hpaned_pos =
860 gtk_paned_get_position(GTK_PANED(addrbook.hpaned));
862 prefs_common.addressbook_vpaned_pos =
863 gtk_paned_get_position(GTK_PANED(addrbook.vpaned));
867 * Create the address book widgets. The address book contains two CTree widgets: the
868 * address index tree on the left and the address list on the right.
870 * The address index tree displays a hierarchy of interfaces and groups. Each node in
871 * this tree is linked to an address Adapter. Adapters have been created for interfaces,
872 * data sources and folder objects.
874 * The address list displays group, person and email objects. These items are linked
875 * directly to ItemGroup, ItemPerson and ItemEMail objects inside the address book data
878 * In the tradition of MVC architecture, the data stores have been separated from the
879 * GUI components. The addrindex.c file provides the interface to all data stores.
881 static void addressbook_create(void)
887 GtkWidget *ctree_swin;
889 GtkWidget *editaddress_vbox;
890 GtkWidget *clist_vbox;
891 GtkWidget *clist_swin;
898 GtkWidget *statusbar;
909 GtkWidget *close_btn;
910 GtkWidget *tree_popup;
911 GtkWidget *list_popup;
913 GtkUIManager *ui_manager;
914 GtkActionGroup *action_group;
915 gchar *index_titles[N_INDEX_COLS];
919 static GdkGeometry geometry;
921 debug_print("Creating addressbook window...\n");
923 index_titles[COL_SOURCES] = _("Sources");
925 /* Address book window */
926 window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "addressbook");
927 gtk_window_set_title(GTK_WINDOW(window), _("Address book"));
928 gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
929 gtk_widget_realize(window);
931 g_signal_connect(G_OBJECT(window), "delete_event",
932 G_CALLBACK(addressbook_close), NULL);
933 g_signal_connect(G_OBJECT(window), "size_allocate",
934 G_CALLBACK(addressbook_size_allocate_cb), NULL);
935 g_signal_connect(G_OBJECT(window), "key_press_event",
936 G_CALLBACK(key_pressed), NULL);
937 MANAGE_WINDOW_SIGNALS_CONNECT(window);
939 vbox = gtk_vbox_new(FALSE, 0);
940 gtk_container_add(GTK_CONTAINER(window), vbox);
943 ui_manager = gtk_ui_manager_new();
944 action_group = cm_menu_create_action_group_full(ui_manager,"Menu", addressbook_entries,
945 G_N_ELEMENTS(addressbook_entries), NULL);
946 gtk_action_group_add_actions(action_group, addressbook_tree_popup_entries,
947 G_N_ELEMENTS(addressbook_tree_popup_entries), NULL);
948 gtk_action_group_add_actions(action_group, addressbook_list_popup_entries,
949 G_N_ELEMENTS(addressbook_list_popup_entries), NULL);
952 MENUITEM_ADDUI_MANAGER(ui_manager, "/", "Menu", NULL, GTK_UI_MANAGER_MENUBAR)
954 MENUITEM_ADDUI_MANAGER(ui_manager, "/", "Menu", NULL, GTK_UI_MANAGER_POPUP)
957 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu", "Book", "Book", GTK_UI_MANAGER_MENU)
958 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu", "Address", "Address", GTK_UI_MANAGER_MENU)
959 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu", "Tools", "Tools", GTK_UI_MANAGER_MENU)
960 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu", "Help", "Help", GTK_UI_MANAGER_MENU)
963 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "NewBook", "Book/NewBook", GTK_UI_MANAGER_MENUITEM)
964 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "NewFolder", "Book/NewFolder", GTK_UI_MANAGER_MENUITEM)
965 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "NewVCard", "Book/NewVCard", GTK_UI_MANAGER_MENUITEM)
967 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "NewJPilot", "Book/NewJPilot", GTK_UI_MANAGER_MENUITEM)
970 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "NewLDAPServer", "Book/NewLDAPServer", GTK_UI_MANAGER_MENUITEM)
972 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "Separator1", "Book/---", GTK_UI_MANAGER_SEPARATOR)
973 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "EditBook", "Book/EditBook", GTK_UI_MANAGER_MENUITEM)
974 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "DeleteBook", "Book/DeleteBook", GTK_UI_MANAGER_MENUITEM)
975 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "Separator2", "Book/---", GTK_UI_MANAGER_SEPARATOR)
976 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "Save", "Book/Save", GTK_UI_MANAGER_MENUITEM)
977 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "Close", "Book/Close", GTK_UI_MANAGER_MENUITEM)
980 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "SelectAll", "Address/SelectAll", GTK_UI_MANAGER_MENUITEM)
981 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Separator1", "Address/---", GTK_UI_MANAGER_SEPARATOR)
982 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Cut", "Address/Cut", GTK_UI_MANAGER_MENUITEM)
983 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Copy", "Address/Copy", GTK_UI_MANAGER_MENUITEM)
984 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Paste", "Address/Paste", GTK_UI_MANAGER_MENUITEM)
985 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Separator2", "Address/---", GTK_UI_MANAGER_SEPARATOR)
986 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Edit", "Address/Edit", GTK_UI_MANAGER_MENUITEM)
987 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Delete", "Address/Delete", GTK_UI_MANAGER_MENUITEM)
988 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Separator3", "Address/---", GTK_UI_MANAGER_SEPARATOR)
989 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "NewAddress", "Address/NewAddress", GTK_UI_MANAGER_MENUITEM)
990 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "NewGroup", "Address/NewGroup", GTK_UI_MANAGER_MENUITEM)
991 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Separator4", "Address/---", GTK_UI_MANAGER_SEPARATOR)
992 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Mailto", "Address/Mailto", GTK_UI_MANAGER_MENUITEM)
995 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Tools", "ImportLDIF", "Tools/ImportLDIF", GTK_UI_MANAGER_MENUITEM)
996 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Tools", "ImportMutt", "Tools/ImportMutt", GTK_UI_MANAGER_MENUITEM)
997 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Tools", "ImportPine", "Tools/ImportPine", GTK_UI_MANAGER_MENUITEM)
998 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Tools", "Separator1", "Tools/---", GTK_UI_MANAGER_SEPARATOR)
999 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Tools", "ExportHTML", "Tools/ExportHTML", GTK_UI_MANAGER_MENUITEM)
1000 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Tools", "ExportLDIF", "Tools/ExportLDIF", GTK_UI_MANAGER_MENUITEM)
1001 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Tools", "Separator2", "Tools/---", GTK_UI_MANAGER_SEPARATOR)
1002 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Tools", "FindDuplicates", "Tools/FindDuplicates", GTK_UI_MANAGER_MENUITEM)
1003 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Tools", "EditAttrs", "Tools/EditAttrs", GTK_UI_MANAGER_MENUITEM)
1006 MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Help", "About", "Help/About", GTK_UI_MANAGER_MENUITEM)
1008 menubar = gtk_ui_manager_get_widget(ui_manager, "/Menu");
1011 gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0);
1013 hildon_window_set_menu(HILDON_WINDOW(window), GTK_MENU(menubar));
1016 vbox2 = gtk_vbox_new(FALSE, BORDER_WIDTH);
1017 gtk_container_set_border_width(GTK_CONTAINER(vbox2), BORDER_WIDTH);
1018 gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
1020 ctree_swin = gtk_scrolled_window_new(NULL, NULL);
1021 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ctree_swin),
1022 GTK_POLICY_AUTOMATIC,
1023 GTK_POLICY_AUTOMATIC);
1024 gtk_widget_set_size_request(ctree_swin, COL_FOLDER_WIDTH + 20, -1);
1027 ctree = gtk_sctree_new_with_titles(N_INDEX_COLS, 0, index_titles);
1028 GTK_WIDGET_UNSET_FLAGS(GTK_CMCLIST(ctree)->column[0].button,
1031 gtk_container_add(GTK_CONTAINER(ctree_swin), ctree);
1032 gtk_cmclist_set_selection_mode(GTK_CMCLIST(ctree), GTK_SELECTION_BROWSE);
1033 gtk_cmclist_set_column_width(GTK_CMCLIST(ctree), 0, COL_FOLDER_WIDTH);
1034 if (prefs_common.enable_dotted_lines) {
1035 gtk_cmctree_set_line_style(GTK_CMCTREE(ctree), GTK_CMCTREE_LINES_DOTTED);
1036 gtk_cmctree_set_expander_style(GTK_CMCTREE(ctree),
1037 GTK_CMCTREE_EXPANDER_SQUARE);
1039 gtk_cmctree_set_line_style(GTK_CMCTREE(ctree), GTK_CMCTREE_LINES_NONE);
1040 gtk_cmctree_set_expander_style(GTK_CMCTREE(ctree),
1041 GTK_CMCTREE_EXPANDER_TRIANGLE);
1043 gtk_sctree_set_stripes(GTK_SCTREE(ctree), prefs_common.use_stripes_in_summaries);
1044 gtk_cmctree_set_indent(GTK_CMCTREE(ctree), CTREE_INDENT);
1045 gtk_cmclist_set_compare_func(GTK_CMCLIST(ctree),
1046 addressbook_treenode_compare_func);
1048 g_signal_connect(G_OBJECT(ctree), "tree_select_row",
1049 G_CALLBACK(addressbook_tree_selected), NULL);
1050 g_signal_connect(G_OBJECT(ctree), "button_press_event",
1051 G_CALLBACK(addressbook_tree_button_pressed),
1053 g_signal_connect(G_OBJECT(ctree), "button_release_event",
1054 G_CALLBACK(addressbook_tree_button_released),
1057 g_signal_connect(G_OBJECT(ctree), "select_row",
1058 G_CALLBACK(addressbook_select_row_tree), NULL);
1060 gtk_drag_dest_set(ctree, GTK_DEST_DEFAULT_ALL & ~GTK_DEST_DEFAULT_HIGHLIGHT,
1061 addressbook_drag_types, 1,
1062 GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_DEFAULT);
1063 g_signal_connect(G_OBJECT(ctree), "drag_motion",
1064 G_CALLBACK(addressbook_drag_motion_cb),
1066 g_signal_connect(G_OBJECT(ctree), "drag_leave",
1067 G_CALLBACK(addressbook_drag_leave_cb),
1069 g_signal_connect(G_OBJECT(ctree), "drag_data_received",
1070 G_CALLBACK(addressbook_drag_received_cb),
1072 g_signal_connect(G_OBJECT(ctree), "focus_in_event",
1073 G_CALLBACK(addressbook_address_index_focus_evt_in), NULL);
1074 g_signal_connect(G_OBJECT(ctree), "focus_out_event",
1075 G_CALLBACK(addressbook_address_index_focus_evt_out), NULL);
1077 clist_vbox = gtk_vbox_new(FALSE, 4);
1079 clist_swin = gtk_scrolled_window_new(NULL, NULL);
1080 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
1081 GTK_POLICY_AUTOMATIC,
1082 GTK_POLICY_AUTOMATIC);
1083 gtk_box_pack_start(GTK_BOX(clist_vbox), clist_swin, TRUE, TRUE, 0);
1086 clist = gtk_sctree_new_with_titles(N_LIST_COLS, 0, list_titles);
1087 gtk_container_add(GTK_CONTAINER(clist_swin), clist);
1088 gtk_cmclist_set_selection_mode(GTK_CMCLIST(clist), GTK_SELECTION_EXTENDED);
1089 if (prefs_common.enable_dotted_lines) {
1090 gtk_cmctree_set_line_style(GTK_CMCTREE(clist), GTK_CMCTREE_LINES_DOTTED);
1091 gtk_cmctree_set_expander_style(GTK_CMCTREE(clist),
1092 GTK_CMCTREE_EXPANDER_SQUARE);
1094 gtk_cmctree_set_line_style(GTK_CMCTREE(clist), GTK_CMCTREE_LINES_NONE);
1095 gtk_cmctree_set_expander_style(GTK_CMCTREE(clist),
1096 GTK_CMCTREE_EXPANDER_TRIANGLE);
1098 gtk_sctree_set_stripes(GTK_SCTREE(ctree), prefs_common.use_stripes_in_summaries);
1099 gtk_cmctree_set_indent(GTK_CMCTREE(clist), CTREE_INDENT);
1100 gtk_cmclist_set_column_width(GTK_CMCLIST(clist), COL_NAME,
1102 gtk_cmclist_set_column_width(GTK_CMCLIST(clist), COL_ADDRESS,
1104 gtk_widget_set_size_request(clist, -1, 80);
1106 addressbook_sort_list(GTK_CMCLIST(clist), COL_NAME, GTK_SORT_ASCENDING);
1107 g_signal_connect(G_OBJECT(GTK_CMCLIST(clist)->column[COL_NAME].button),
1108 "clicked", G_CALLBACK(addressbook_name_clicked), clist);
1109 g_signal_connect(G_OBJECT(GTK_CMCLIST(clist)->column[COL_ADDRESS].button),
1110 "clicked", G_CALLBACK(addressbook_address_clicked), clist);
1111 g_signal_connect(G_OBJECT(GTK_CMCLIST(clist)->column[COL_REMARKS].button),
1112 "clicked", G_CALLBACK(addressbook_remarks_clicked), clist);
1113 g_signal_connect(G_OBJECT(clist), "focus_in_event",
1114 G_CALLBACK(addressbook_address_list_focus_evt_in), NULL);
1115 g_signal_connect(G_OBJECT(clist), "focus_out_event",
1116 G_CALLBACK(addressbook_address_list_focus_evt_out), NULL);
1118 for (i = 0; i < N_LIST_COLS; i++)
1119 GTK_WIDGET_UNSET_FLAGS(GTK_CMCLIST(clist)->column[i].button,
1122 g_signal_connect(G_OBJECT(clist), "tree_select_row",
1123 G_CALLBACK(addressbook_list_row_selected), NULL);
1124 g_signal_connect(G_OBJECT(clist), "tree_unselect_row",
1125 G_CALLBACK(addressbook_list_row_unselected), NULL);
1126 g_signal_connect(G_OBJECT(clist), "button_press_event",
1127 G_CALLBACK(addressbook_list_button_pressed),
1129 g_signal_connect(G_OBJECT(clist), "button_release_event",
1130 G_CALLBACK(addressbook_list_button_released),
1132 g_signal_connect(G_OBJECT(clist), "tree_expand",
1133 G_CALLBACK(addressbook_person_expand_node), NULL );
1134 g_signal_connect(G_OBJECT(clist), "tree_collapse",
1135 G_CALLBACK(addressbook_person_collapse_node), NULL );
1136 g_signal_connect(G_OBJECT(clist), "start_drag",
1137 G_CALLBACK(addressbook_start_drag), NULL);
1138 g_signal_connect(G_OBJECT(clist), "drag_data_get",
1139 G_CALLBACK(addressbook_drag_data_get), NULL);
1140 hbox = gtk_hbox_new(FALSE, 4);
1141 gtk_box_pack_start(GTK_BOX(clist_vbox), hbox, FALSE, FALSE, 0);
1143 label = gtk_label_new(_("Lookup name:"));
1144 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1146 entry = gtk_entry_new();
1147 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
1149 address_completion_register_entry(GTK_ENTRY(entry), FALSE);
1151 g_signal_connect(G_OBJECT(entry), "key_press_event",
1152 G_CALLBACK(addressbook_entry_key_pressed),
1155 if (!prefs_common.addressbook_use_editaddress_dialog) {
1156 editaddress_vbox = gtk_vbox_new(FALSE, 4);
1157 vpaned = gtk_vpaned_new();
1158 gtk_paned_pack1(GTK_PANED(vpaned), clist_vbox, FALSE, FALSE);
1159 gtk_paned_pack2(GTK_PANED(vpaned), editaddress_vbox, TRUE, FALSE);
1162 editaddress_vbox = NULL;
1164 hpaned = gtk_hpaned_new();
1165 gtk_box_pack_start(GTK_BOX(vbox2), hpaned, TRUE, TRUE, 0);
1166 gtk_paned_pack1(GTK_PANED(hpaned), ctree_swin, FALSE, FALSE);
1167 if (prefs_common.addressbook_use_editaddress_dialog)
1168 gtk_paned_pack2(GTK_PANED(hpaned), clist_vbox, TRUE, FALSE);
1170 gtk_paned_pack2(GTK_PANED(hpaned), vpaned, TRUE, FALSE);
1173 hsbox = gtk_hbox_new(FALSE, 0);
1174 gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, BORDER_WIDTH);
1175 statusbar = gtk_statusbar_new();
1176 gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, BORDER_WIDTH);
1179 hbbox = gtk_hbutton_box_new();
1180 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox), GTK_BUTTONBOX_END);
1181 gtk_box_set_spacing(GTK_BOX(hbbox), 2);
1182 gtk_container_set_border_width(GTK_CONTAINER(hbbox), 4);
1183 gtk_box_pack_end(GTK_BOX(vbox), hbbox, FALSE, FALSE, 0);
1185 gtkut_stock_button_add_help(hbbox, &help_btn);
1187 edit_btn = gtk_button_new_from_stock(GTK_STOCK_EDIT);
1188 GTK_WIDGET_SET_FLAGS(edit_btn, GTK_CAN_DEFAULT);
1189 gtk_box_pack_start(GTK_BOX(hbbox), edit_btn, TRUE, TRUE, 0);
1190 del_btn = gtk_button_new_from_stock(GTK_STOCK_DELETE);
1191 GTK_WIDGET_SET_FLAGS(del_btn, GTK_CAN_DEFAULT);
1192 gtk_box_pack_start(GTK_BOX(hbbox), del_btn, TRUE, TRUE, 0);
1193 reg_btn = gtk_button_new_from_stock(GTK_STOCK_NEW);
1194 GTK_WIDGET_SET_FLAGS(reg_btn, GTK_CAN_DEFAULT);
1195 gtk_box_pack_start(GTK_BOX(hbbox), reg_btn, TRUE, TRUE, 0);
1198 lup_btn = gtk_button_new_from_stock(GTK_STOCK_FIND);
1199 GTK_WIDGET_SET_FLAGS(lup_btn, GTK_CAN_DEFAULT);
1200 gtk_box_pack_start(GTK_BOX(hbox), lup_btn, TRUE, TRUE, 0);
1202 g_signal_connect(G_OBJECT(help_btn), "clicked",
1203 G_CALLBACK(manual_open_with_anchor_cb),
1204 MANUAL_ANCHOR_ADDRBOOK);
1206 g_signal_connect(G_OBJECT(edit_btn), "clicked",
1207 G_CALLBACK(addressbook_edit_clicked), NULL);
1208 g_signal_connect(G_OBJECT(del_btn), "clicked",
1209 G_CALLBACK(addressbook_del_clicked), NULL);
1210 g_signal_connect(G_OBJECT(reg_btn), "clicked",
1211 G_CALLBACK(addressbook_reg_clicked), NULL);
1212 g_signal_connect(G_OBJECT(lup_btn), "clicked",
1213 G_CALLBACK(addressbook_lup_clicked), NULL);
1215 to_btn = gtk_button_new_with_label
1216 (prefs_common_translated_header_name("To:"));
1217 GTK_WIDGET_SET_FLAGS(to_btn, GTK_CAN_DEFAULT);
1218 gtk_box_pack_start(GTK_BOX(hbbox), to_btn, TRUE, TRUE, 0);
1219 cc_btn = gtk_button_new_with_label
1220 (prefs_common_translated_header_name("Cc:"));
1221 GTK_WIDGET_SET_FLAGS(cc_btn, GTK_CAN_DEFAULT);
1222 gtk_box_pack_start(GTK_BOX(hbbox), cc_btn, TRUE, TRUE, 0);
1223 bcc_btn = gtk_button_new_with_label
1224 (prefs_common_translated_header_name("Bcc:"));
1225 GTK_WIDGET_SET_FLAGS(bcc_btn, GTK_CAN_DEFAULT);
1226 gtk_box_pack_start(GTK_BOX(hbbox), bcc_btn, TRUE, TRUE, 0);
1228 close_btn = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
1229 GTK_WIDGET_SET_FLAGS(close_btn, GTK_CAN_DEFAULT);
1230 gtk_box_pack_start(GTK_BOX(hbbox), close_btn, TRUE, TRUE, 0);
1232 g_signal_connect(G_OBJECT(to_btn), "clicked",
1233 G_CALLBACK(addressbook_to_clicked),
1234 GINT_TO_POINTER(COMPOSE_TO));
1235 g_signal_connect(G_OBJECT(cc_btn), "clicked",
1236 G_CALLBACK(addressbook_to_clicked),
1237 GINT_TO_POINTER(COMPOSE_CC));
1238 g_signal_connect(G_OBJECT(bcc_btn), "clicked",
1239 G_CALLBACK(addressbook_to_clicked),
1240 GINT_TO_POINTER(COMPOSE_BCC));
1241 g_signal_connect(G_OBJECT(close_btn), "clicked",
1242 G_CALLBACK(addressbook_close_clicked), NULL);
1244 /* Build icons for interface */
1245 stock_pixmap_gdk( window, STOCK_PIXMAP_INTERFACE,
1246 &interfacexpm, &interfacexpmmask );
1248 /* Build control tables */
1249 addrbookctl_build_map(window);
1250 addrbookctl_build_iflist();
1251 addrbookctl_build_ifselect();
1253 addrbook.clist = NULL;
1255 /* Add each interface into the tree as a root level folder */
1256 nodeIf = _addressInterfaceList_;
1258 AdapterInterface *adapter = nodeIf->data;
1259 AddressInterface *iface = adapter->interface;
1260 nodeIf = g_list_next(nodeIf);
1262 if(iface->useInterface) {
1263 AddressTypeControlItem *atci = adapter->atci;
1264 text = atci->displayName;
1266 gtk_sctree_insert_node( GTK_CMCTREE(ctree),
1267 NULL, NULL, &text, FOLDER_SPACING,
1268 interfacexpm, interfacexpmmask,
1269 interfacexpm, interfacexpmmask,
1271 cm_menu_set_sensitive_full(ui_manager, atci->menuCommand, adapter->haveLibrary );
1272 gtk_cmctree_node_set_row_data_full(
1273 GTK_CMCTREE(ctree), adapter->treeNode, adapter,
1274 addressbook_free_treenode );
1280 MENUITEM_ADDUI_MANAGER(ui_manager, "/", "Popups", NULL, GTK_UI_MANAGER_MENUBAR);
1281 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups", "ABTreePopup", "ABTreePopup", GTK_UI_MANAGER_MENU)
1282 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABTreePopup", "EditBook", "ABTreePopup/EditBook", GTK_UI_MANAGER_MENUITEM)
1283 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABTreePopup", "DeleteBook", "ABTreePopup/DeleteBook", GTK_UI_MANAGER_MENUITEM)
1284 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABTreePopup", "Separator1", "ABTreePopup/---", GTK_UI_MANAGER_SEPARATOR)
1285 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABTreePopup", "NewBook", "ABTreePopup/NewBook", GTK_UI_MANAGER_MENUITEM)
1286 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABTreePopup", "NewFolder", "ABTreePopup/NewFolder", GTK_UI_MANAGER_MENUITEM)
1287 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABTreePopup", "NewGroup", "ABTreePopup/NewGroup", GTK_UI_MANAGER_MENUITEM)
1288 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABTreePopup", "Separator2", "ABTreePopup/---", GTK_UI_MANAGER_SEPARATOR)
1289 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABTreePopup", "Cut", "ABTreePopup/Cut", GTK_UI_MANAGER_MENUITEM)
1290 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABTreePopup", "Copy", "ABTreePopup/Copy", GTK_UI_MANAGER_MENUITEM)
1291 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABTreePopup", "Paste", "ABTreePopup/Paste", GTK_UI_MANAGER_MENUITEM)
1293 tree_popup = gtk_menu_item_get_submenu(GTK_MENU_ITEM(
1294 gtk_ui_manager_get_widget(ui_manager, "/Popups/ABTreePopup")));
1296 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups", "ABListPopup", "ABListPopup", GTK_UI_MANAGER_MENU)
1297 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "SelectAll", "ABListPopup/SelectAll", GTK_UI_MANAGER_MENUITEM)
1298 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Separator1", "ABListPopup/---", GTK_UI_MANAGER_SEPARATOR)
1299 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Edit", "ABListPopup/Edit", GTK_UI_MANAGER_MENUITEM)
1300 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Delete", "ABListPopup/Delete", GTK_UI_MANAGER_MENUITEM)
1301 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Separator2", "ABListPopup/---", GTK_UI_MANAGER_SEPARATOR)
1302 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "NewAddress", "ABListPopup/NewAddress", GTK_UI_MANAGER_MENUITEM)
1303 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "NewGroup", "ABListPopup/NewGroup", GTK_UI_MANAGER_MENUITEM)
1304 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Separator3", "ABListPopup/---", GTK_UI_MANAGER_SEPARATOR)
1305 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Cut", "ABListPopup/Cut", GTK_UI_MANAGER_MENUITEM)
1306 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Copy", "ABListPopup/Copy", GTK_UI_MANAGER_MENUITEM)
1307 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Paste", "ABListPopup/Paste", GTK_UI_MANAGER_MENUITEM)
1308 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Separator4", "ABListPopup/---", GTK_UI_MANAGER_SEPARATOR)
1309 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Mailto", "ABListPopup/Mailto", GTK_UI_MANAGER_MENUITEM)
1311 MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "BrowseEntry", "ABListPopup/BrowseEntry", GTK_UI_MANAGER_MENUITEM)
1313 list_popup = gtk_menu_item_get_submenu(GTK_MENU_ITEM(
1314 gtk_ui_manager_get_widget(ui_manager, "/Popups/ABListPopup")));
1316 addrbook.window = window;
1317 addrbook.hpaned = hpaned;
1318 addrbook.vpaned = vpaned;
1319 addrbook.menubar = menubar;
1320 addrbook.ctree = ctree;
1323 addrbook.editaddress_vbox = editaddress_vbox;
1324 addrbook.clist = clist;
1325 addrbook.label = label;
1326 addrbook.entry = entry;
1327 addrbook.statusbar = statusbar;
1328 addrbook.status_cid = gtk_statusbar_get_context_id(
1329 GTK_STATUSBAR(statusbar), "Addressbook Window" );
1331 addrbook.help_btn = help_btn;
1332 addrbook.edit_btn = edit_btn;
1333 addrbook.del_btn = del_btn;
1334 addrbook.reg_btn = reg_btn;
1335 addrbook.lup_btn = lup_btn;
1336 addrbook.to_btn = to_btn;
1337 addrbook.cc_btn = cc_btn;
1338 addrbook.bcc_btn = bcc_btn;
1340 addrbook.tree_popup = tree_popup;
1341 addrbook.list_popup = list_popup;
1342 addrbook.ui_manager = ui_manager;
1344 addrbook.listSelected = NULL;
1346 if (!geometry.min_height) {
1347 geometry.min_width = ADDRESSBOOK_WIDTH;
1348 geometry.min_height = ADDRESSBOOK_HEIGHT;
1351 gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
1353 gtk_widget_set_size_request(window, prefs_common.addressbookwin_width,
1354 prefs_common.addressbookwin_height);
1356 if (!prefs_common.addressbook_use_editaddress_dialog) {
1357 if (prefs_common.addressbook_vpaned_pos > 0)
1358 gtk_paned_set_position(GTK_PANED(vpaned),
1359 prefs_common.addressbook_vpaned_pos);
1361 if (prefs_common.addressbook_hpaned_pos > 0)
1362 gtk_paned_set_position(GTK_PANED(hpaned),
1363 prefs_common.addressbook_hpaned_pos);
1366 gtk_widget_show_all(window);
1370 * Close address book window and save to file(s).
1372 static gint addressbook_close( void ) {
1373 address_completion_end(addrbook.window);
1374 if (!prefs_common.addressbook_use_editaddress_dialog)
1375 addressbook_edit_person_invalidate(NULL, NULL, NULL);
1377 addressbook_pane_save_position();
1379 gtk_widget_hide(addrbook.window);
1380 addressbook_export_to_file();
1385 * Display message in status line.
1386 * \param msg Message to display.
1388 static void addressbook_status_show( gchar *msg ) {
1389 if( addrbook.statusbar != NULL ) {
1391 GTK_STATUSBAR(addrbook.statusbar),
1392 addrbook.status_cid );
1395 GTK_STATUSBAR(addrbook.statusbar),
1396 addrbook.status_cid, msg );
1401 static void addressbook_ds_show_message( AddressDataSource *ds ) {
1405 *addressbook_msgbuf = '\0';
1407 name = addrindex_ds_get_name( ds );
1408 retVal = addrindex_ds_get_status_code( ds );
1409 if( retVal == MGU_SUCCESS ) {
1410 g_snprintf( addressbook_msgbuf,
1411 sizeof(addressbook_msgbuf), "%s", name );
1414 desc = addressbook_err2string( _lutErrorsGeneral_, retVal );
1415 g_snprintf( addressbook_msgbuf,
1416 sizeof(addressbook_msgbuf), "%s: %s", name, desc );
1419 addressbook_status_show( addressbook_msgbuf );
1422 static void addressbook_button_set_sensitive(void)
1424 gboolean to_sens = FALSE;
1425 gboolean cc_sens = FALSE;
1426 gboolean bcc_sens = FALSE;
1428 if (!addrbook.window) return;
1430 if (addrbook.target_compose) {
1436 gtk_widget_set_sensitive(addrbook.to_btn, to_sens);
1437 gtk_widget_set_sensitive(addrbook.cc_btn, cc_sens);
1438 gtk_widget_set_sensitive(addrbook.bcc_btn, bcc_sens);
1441 static void addressbook_edit_clicked(GtkButton *button, gpointer data)
1443 addressbook_edit_address_cb(NULL, NULL);
1446 static gboolean find_person(AddrSelectItem *item_a, ItemPerson *person)
1448 return ((ItemPerson *)item_a->addressItem == person)?0:-1;
1452 * Delete one or more objects from address list.
1454 static void addressbook_del_clicked(GtkButton *button, gpointer data)
1456 GtkCMCTree *clist = GTK_CMCTREE(addrbook.clist);
1457 GtkCMCTree *ctree = GTK_CMCTREE(addrbook.ctree);
1458 AddressObject *pobj;
1459 AdapterDSource *ads = NULL;
1460 GtkCMCTreeNode *nodeList;
1463 AddressBookFile *abf = NULL;
1464 AddressDataSource *ds = NULL;
1465 AddressInterface *iface;
1466 AddrItemObject *aio;
1467 AddrSelectItem *item;
1469 gboolean refreshList = FALSE;
1471 pobj = gtk_cmctree_node_get_row_data(ctree, addrbook.opened );
1472 g_return_if_fail(pobj != NULL);
1474 /* Test whether anything selected for deletion */
1475 nodeList = addrbook.listSelected;
1477 aio = gtk_cmctree_node_get_row_data( clist, nodeList );
1478 if( aio == NULL) return;
1479 ds = addressbook_find_datasource( addrbook.treeSelected );
1480 if( ds == NULL ) return;
1482 /* Test for read only */
1483 iface = ds->interface;
1484 if( iface->readOnly ) {
1485 alertpanel( _("Delete address(es)"),
1486 _("This address data is readonly and cannot be deleted."),
1487 GTK_STOCK_CLOSE, NULL, NULL );
1491 /* Test whether Ok to proceed */
1493 if( pobj->type == ADDR_DATASOURCE ) {
1494 ads = ADAPTER_DSOURCE(pobj);
1495 if( ads->subType == ADDR_BOOK ) procFlag = TRUE;
1497 else if( pobj->type == ADDR_ITEM_FOLDER ) {
1500 else if( pobj->type == ADDR_ITEM_GROUP ) {
1503 if( ! procFlag ) return;
1504 abf = ds->rawDataSource;
1505 if( abf == NULL ) return;
1507 gtk_cmclist_freeze(GTK_CMCLIST(addrbook.clist));
1508 g_signal_handlers_block_by_func
1509 (G_OBJECT(addrbook.clist),
1510 G_CALLBACK(addressbook_list_row_unselected), NULL);
1512 /* Process deletions */
1513 if( pobj->type == ADDR_DATASOURCE || pobj->type == ADDR_ITEM_FOLDER ) {
1514 GList *groups = NULL, *persons = NULL, *emails = NULL;
1515 gboolean group_delete = TRUE;
1516 /* Items inside folders */
1517 list = addrselect_get_list( _addressSelect_ );
1518 /* Confirm deletion */
1522 node = g_list_next( node );
1523 aio = ( AddrItemObject * ) item->addressItem;
1524 if( aio->type == ADDR_ITEM_PERSON || aio->type == ADDR_ITEM_EMAIL ) {
1525 group_delete = FALSE;
1530 aval = alertpanel( _("Delete group"),
1531 _("Really delete the group(s)?\n"
1532 "The addresses it contains will not be lost."),
1533 GTK_STOCK_CANCEL, "+"GTK_STOCK_DELETE, NULL );
1534 if( aval != G_ALERTALTERNATE ) {
1538 aval = alertpanel( _("Delete address(es)"),
1539 _("Really delete the address(es)?"),
1540 GTK_STOCK_CANCEL, "+"GTK_STOCK_DELETE, NULL );
1541 if( aval != G_ALERTALTERNATE ) {
1546 /* first, set lists of groups and persons to remove */
1550 node = g_list_next( node );
1551 aio = ( AddrItemObject * ) item->addressItem;
1554 if( aio->type == ADDR_ITEM_GROUP ) {
1555 groups = g_list_prepend(groups, item);
1557 else if( aio->type == ADDR_ITEM_PERSON ) {
1558 persons = g_list_prepend(persons, item);
1561 /* then set list of emails to remove *if* they're not children of
1562 * persons to remove */
1566 node = g_list_next( node );
1567 aio = ( AddrItemObject * ) item->addressItem;
1570 if( aio->type == ADDR_ITEM_EMAIL ) {
1571 ItemEMail *sitem = ( ItemEMail * ) aio;
1572 ItemPerson *person = ( ItemPerson * ) ADDRITEM_PARENT(sitem);
1573 if (!g_list_find_custom(persons, person, (GCompareFunc)(find_person))) {
1574 emails = g_list_prepend(emails, item);
1576 /* else, the email will be removed via the parent person */
1579 /* then delete groups */
1583 node = g_list_next( node );
1584 aio = ( AddrItemObject * ) item->addressItem;
1587 if( aio->type == ADDR_ITEM_GROUP ) {
1588 ItemGroup *item = ( ItemGroup * ) aio;
1589 GtkCMCTreeNode *nd = NULL;
1590 nd = addressbook_find_group_node( addrbook.opened, item );
1591 item = addrbook_remove_group( abf, item );
1593 addritem_free_item_group( item );
1595 /* Remove group from parent node */
1596 gtk_cmctree_remove_node( ctree, nd );
1600 /* then delete persons */
1604 node = g_list_next( node );
1605 aio = ( AddrItemObject * ) item->addressItem;
1608 if( aio->type == ADDR_ITEM_PERSON ) {
1609 ItemPerson *item = ( ItemPerson * ) aio;
1610 item->status = DELETE_ENTRY;
1611 addressbook_folder_remove_one_person( clist, item );
1612 if (pobj->type == ADDR_ITEM_FOLDER)
1613 addritem_folder_remove_person(ADAPTER_FOLDER(pobj)->itemFolder, item);
1614 item = addrbook_remove_person( abf, item );
1616 if (ds && ds->type == ADDR_IF_LDAP) {
1617 LdapServer *server = ds->rawDataSource;
1618 ldapsvr_set_modified(server, TRUE);
1619 ldapsvr_update_book(server, item);
1623 gchar *filename = addritem_person_get_picture(item);
1624 if (filename && is_file_exist(filename))
1625 claws_unlink(filename);
1627 addritem_free_item_person( item );
1631 /* then delete emails */
1635 node = g_list_next( node );
1636 aio = ( AddrItemObject * ) item->addressItem;
1640 if( aio->type == ADDR_ITEM_EMAIL ) {
1641 ItemEMail *sitem = ( ItemEMail * ) aio;
1642 ItemPerson *person = ( ItemPerson * ) ADDRITEM_PARENT(sitem);
1643 sitem = addrbook_person_remove_email( abf, person, sitem );
1645 addrcache_remove_email(abf->addressCache, sitem);
1646 addritem_free_item_email( sitem );
1648 addressbook_folder_refresh_one_person( clist, person );
1651 g_list_free( groups );
1652 g_list_free( persons );
1653 g_list_free( emails );
1654 g_list_free( list );
1655 addressbook_list_select_clear();
1657 gtk_sctree_select( GTK_SCTREE(ctree), addrbook.opened);
1658 addressbook_set_clist(
1659 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook.ctree),
1663 addrbook_set_dirty(abf, TRUE);
1664 addressbook_export_to_file();
1665 addressbook_list_menu_setup();
1668 else if( pobj->type == ADDR_ITEM_GROUP ) {
1669 /* Items inside groups */
1670 list = addrselect_get_list( _addressSelect_ );
1674 node = g_list_next( node );
1675 aio = ( AddrItemObject * ) item->addressItem;
1676 if( aio->type == ADDR_ITEM_EMAIL ) {
1677 ItemEMail *item = ( ItemEMail * ) aio;
1678 ItemPerson *person = ( ItemPerson * ) ADDRITEM_PARENT(item);
1679 item = addrbook_person_remove_email( abf, person, item );
1681 addritem_free_item_email( item );
1685 g_list_free( list );
1686 addressbook_list_select_clear();
1687 gtk_sctree_select( GTK_SCTREE(ctree), addrbook.opened);
1688 addressbook_set_clist(
1689 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook.ctree),
1693 addrbook_set_dirty(abf, TRUE);
1694 addressbook_export_to_file();
1695 addressbook_list_menu_setup();
1699 gtk_cmctree_node_set_row_data( clist, nodeList, NULL );
1700 gtk_cmctree_remove_node( clist, nodeList );
1702 gtk_cmclist_thaw(GTK_CMCLIST(addrbook.clist));
1703 g_signal_handlers_unblock_by_func
1704 (G_OBJECT(addrbook.clist),
1705 G_CALLBACK(addressbook_list_row_unselected), NULL);
1708 static void addressbook_reg_clicked(GtkButton *button, gpointer data)
1710 addressbook_new_address_cb( NULL, NULL );
1713 static gchar *addressbook_format_address( AddrItemObject * aio ) {
1716 gchar *address = NULL;
1718 if( aio->type == ADDR_ITEM_EMAIL ) {
1719 ItemPerson *person = NULL;
1720 ItemEMail *email = ( ItemEMail * ) aio;
1722 person = ( ItemPerson * ) ADDRITEM_PARENT(email);
1723 if( email->address ) {
1724 if( ADDRITEM_NAME(email) ) {
1725 name = ADDRITEM_NAME(email);
1726 if( *name == '\0' ) {
1727 name = ADDRITEM_NAME(person);
1730 else if( ADDRITEM_NAME(person) ) {
1731 name = ADDRITEM_NAME(person);
1734 buf = g_strdup( email->address );
1736 address = email->address;
1739 else if( aio->type == ADDR_ITEM_PERSON ) {
1740 ItemPerson *person = ( ItemPerson * ) aio;
1741 GList *node = person->listEMail;
1743 name = ADDRITEM_NAME(person);
1745 ItemEMail *email = ( ItemEMail * ) node->data;
1746 address = email->address;
1750 if( name && name[0] != '\0' ) {
1751 if( strchr_with_skip_quote( name, '"', ',' ) )
1752 buf = g_strdup_printf( "\"%s\" <%s>", name, address );
1754 buf = g_strdup_printf( "%s <%s>", name, address );
1757 buf = g_strdup( address );
1764 static void addressbook_to_clicked(GtkButton *button, gpointer data)
1768 AddrSelectItem *item;
1769 AddrItemObject *aio;
1772 compose = addrbook.target_compose;
1773 if( ! compose ) return;
1775 /* Nothing selected, but maybe there is something in text entry */
1776 addr = (char *)gtk_entry_get_text( GTK_ENTRY( addrbook.entry) );
1778 compose_entry_append(
1779 compose, addr, (ComposeEntryType)data );
1782 /* Select from address list */
1783 list = addrselect_get_list( _addressSelect_ );
1788 node = g_list_next( node );
1789 aio = item->addressItem;
1790 if( aio->type == ADDR_ITEM_PERSON ||
1791 aio->type == ADDR_ITEM_EMAIL ) {
1792 addr = addressbook_format_address( aio );
1793 compose_entry_append(
1794 compose, addr, (ComposeEntryType) data );
1797 else if( aio->type == ADDR_ITEM_GROUP ) {
1798 ItemGroup *group = ( ItemGroup * ) aio;
1799 GList *nodeMail = group->listEMail;
1801 ItemEMail *email = nodeMail->data;
1803 addr = addressbook_format_address(
1804 ( AddrItemObject * ) email );
1805 compose_entry_append(
1806 compose, addr, (ComposeEntryType) data );
1808 nodeMail = g_list_next( nodeMail );
1813 AddressObject *obj = NULL;
1815 obj = gtk_cmctree_node_get_row_data( GTK_CMCTREE(addrbook.ctree), addrbook.treeSelected );
1817 if( obj && obj->type == ADDR_ITEM_GROUP ) {
1818 ItemGroup *itemGroup = ADAPTER_GROUP(obj)->itemGroup;
1819 GList *nodeMail = itemGroup->listEMail;
1821 ItemEMail *email = nodeMail->data;
1823 addr = addressbook_format_address(
1824 ( AddrItemObject * ) email );
1825 compose_entry_append(
1826 compose, addr, (ComposeEntryType) data );
1828 nodeMail = g_list_next( nodeMail );
1832 g_list_free( list );
1835 static void addressbook_menubar_set_sensitive( gboolean sensitive ) {
1836 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Book/EditBook", sensitive );
1837 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Book/DeleteBook", sensitive );
1838 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Book/NewFolder", sensitive );
1840 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/SelectAll", TRUE );
1841 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Cut", sensitive );
1842 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Copy", sensitive );
1843 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Paste", sensitive );
1845 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/NewAddress", sensitive );
1846 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/NewGroup", sensitive );
1847 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Mailto", sensitive );
1848 gtk_widget_set_sensitive( addrbook.edit_btn, sensitive );
1849 gtk_widget_set_sensitive( addrbook.del_btn, sensitive );
1852 static void addressbook_menuitem_set_sensitive( AddressObject *obj, GtkCMCTreeNode *node ) {
1853 gboolean canEdit = FALSE;
1854 gboolean canDelete = TRUE;
1855 gboolean canAdd = FALSE;
1856 gboolean canEditTr = TRUE;
1857 gboolean editAddress = FALSE;
1858 gboolean canExport = TRUE;
1859 AddressTypeControlItem *atci = NULL;
1860 AddressDataSource *ds = NULL;
1861 AddressInterface *iface = NULL;
1863 if( obj == NULL ) return;
1864 if( obj->type == ADDR_INTERFACE ) {
1865 AdapterInterface *adapter = ADAPTER_INTERFACE(obj);
1866 iface = adapter->interface;
1868 if( iface->haveLibrary ) {
1869 /* Enable appropriate File / New command */
1870 atci = adapter->atci;
1871 cm_menu_set_sensitive_full(addrbook.ui_manager, atci->menuCommand, TRUE );
1874 canEditTr = canExport = FALSE;
1876 else if( obj->type == ADDR_DATASOURCE ) {
1877 AdapterDSource *ads = ADAPTER_DSOURCE(obj);
1878 ds = ads->dataSource;
1879 iface = ds->interface;
1880 if( ! iface->readOnly ) {
1881 canAdd = canEdit = editAddress = canDelete = TRUE;
1883 if( ! iface->haveLibrary ) {
1884 canAdd = canEdit = editAddress = canExport = canDelete = FALSE;
1887 else if( obj->type == ADDR_ITEM_FOLDER ) {
1888 ds = addressbook_find_datasource( addrbook.treeSelected );
1890 iface = ds->interface;
1891 if( iface->readOnly ) {
1896 canAdd = editAddress = TRUE;
1900 else if( obj->type == ADDR_ITEM_GROUP ) {
1901 ds = addressbook_find_datasource( addrbook.treeSelected );
1903 iface = ds->interface;
1904 if( ! iface->readOnly ) {
1910 if( addrbook.listSelected == NULL )
1914 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/NewAddress", editAddress );
1915 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/NewGroup", canAdd );
1916 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Book/NewFolder", canAdd );
1917 gtk_widget_set_sensitive( addrbook.reg_btn, editAddress );
1920 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Edit", canEdit );
1921 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Delete", canDelete );
1922 gtk_widget_set_sensitive( addrbook.edit_btn, canEdit );
1923 gtk_widget_set_sensitive( addrbook.del_btn, canDelete );
1925 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Book/EditBook", canEditTr );
1926 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Book/DeleteBook", canEditTr );
1929 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Tools/ExportHTML", canExport );
1930 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Tools/ExportLDIF", canExport );
1934 * Address book tree callback function that responds to selection of tree
1937 * \param ctree Tree widget.
1938 * \param node Node that was selected.
1939 * \param column Column number where selected occurred.
1940 * \param data Pointer to user data.
1942 static void addressbook_tree_selected(GtkCMCTree *ctree, GtkCMCTreeNode *node,
1943 gint column, gpointer data)
1945 AddressObject *obj = NULL;
1946 AdapterDSource *ads = NULL;
1947 AddressDataSource *ds = NULL;
1948 ItemFolder *rootFolder = NULL;
1949 AddressObjectType aot;
1951 addrbook.treeSelected = node;
1952 addrbook.listSelected = NULL;
1953 addressbook_status_show( "" );
1954 if( addrbook.entry != NULL ) gtk_entry_set_text(GTK_ENTRY(addrbook.entry), "");
1956 if( node ) obj = gtk_cmctree_node_get_row_data( ctree, node );
1958 addressbook_set_clist(NULL, TRUE);
1961 addrbook.opened = node;
1963 if( obj->type == ADDR_DATASOURCE ) {
1964 /* Read from file */
1965 static gboolean tVal = TRUE;
1967 ads = ADAPTER_DSOURCE(obj);
1968 if( ads == NULL ) return;
1969 ds = ads->dataSource;
1970 if( ds == NULL ) return;
1972 if( addrindex_ds_get_modify_flag( ds ) ) {
1973 addrindex_ds_read_data( ds );
1976 if( ! addrindex_ds_get_read_flag( ds ) ) {
1977 addrindex_ds_read_data( ds );
1979 addressbook_ds_show_message( ds );
1981 if( ! addrindex_ds_get_access_flag( ds ) ) {
1982 /* Remove existing folders and groups */
1983 gtk_cmclist_freeze( GTK_CMCLIST(ctree) );
1984 addressbook_tree_remove_children( ctree, node );
1985 gtk_cmclist_thaw( GTK_CMCLIST(ctree) );
1987 /* Load folders into the tree */
1988 rootFolder = addrindex_ds_get_root_folder( ds );
1989 if( ds && ds->type == ADDR_IF_JPILOT ) {
1990 aot = ADDR_CATEGORY;
1992 else if( ds && ds->type == ADDR_IF_LDAP ) {
1993 aot = ADDR_LDAP_QUERY;
1996 aot = ADDR_ITEM_FOLDER;
1998 addressbook_node_add_folder( node, ds, rootFolder, aot );
1999 addrindex_ds_set_access_flag( ds, &tVal );
2000 gtk_cmctree_expand( ctree, node );
2003 addressbook_set_clist(NULL, TRUE);
2006 /* Update address list */
2007 g_signal_handlers_block_by_func
2009 G_CALLBACK(addressbook_tree_selected), NULL);
2010 addressbook_set_clist( obj, FALSE );
2011 g_signal_handlers_unblock_by_func
2013 G_CALLBACK(addressbook_tree_selected), NULL);
2014 if (!prefs_common.addressbook_use_editaddress_dialog)
2015 addressbook_edit_person_invalidate(NULL, NULL, NULL);
2017 /* Setup main menu selections */
2018 addressbook_menubar_set_sensitive( FALSE );
2019 addressbook_menuitem_set_sensitive( obj, node );
2020 addressbook_list_select_clear();
2021 addressbook_list_menu_setup();
2026 * Setup address list popup menu items. Items are enabled or disabled as
2029 static void addressbook_list_menu_setup( void ) {
2030 GtkCMCTree *clist = NULL;
2031 AddressObject *pobj = NULL;
2032 AddressObject *obj = NULL;
2033 AdapterDSource *ads = NULL;
2034 AddressInterface *iface = NULL;
2035 AddressDataSource *ds = NULL;
2036 gboolean canEdit = FALSE;
2037 gboolean canDelete = FALSE;
2038 gboolean canCut = FALSE;
2039 gboolean canCopy = FALSE;
2040 gboolean canPaste = FALSE;
2041 gboolean canBrowse = FALSE;
2043 pobj = gtk_cmctree_node_get_row_data( GTK_CMCTREE(addrbook.ctree), addrbook.treeSelected );
2044 if( pobj == NULL ) return;
2046 clist = GTK_CMCTREE(addrbook.clist);
2047 obj = gtk_cmctree_node_get_row_data( clist, addrbook.listSelected );
2048 if( obj == NULL ) canEdit = FALSE;
2050 menu_set_insensitive_all( GTK_MENU_SHELL(addrbook.list_popup) );
2051 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/SelectAll", TRUE );
2053 if( pobj->type == ADDR_DATASOURCE ) {
2054 /* Parent object is a data source */
2055 ads = ADAPTER_DSOURCE(pobj);
2056 ds = ads->dataSource;
2059 iface = ds->interface;
2062 if( ! iface->readOnly ) {
2063 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/NewAddress", TRUE );
2064 if (iface->type != ADDR_IF_LDAP)
2065 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/NewGroup", TRUE );
2066 gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
2069 canDelete = canEdit;
2072 else if( pobj->type != ADDR_INTERFACE ) {
2073 /* Parent object is not an interface */
2074 ds = addressbook_find_datasource( addrbook.treeSelected );
2077 iface = ds->interface;
2080 if( ! iface->readOnly ) {
2081 /* Folder or group */
2082 if( pobj->type == ADDR_ITEM_FOLDER || pobj->type == ADDR_ITEM_GROUP ) {
2083 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/NewAddress", TRUE );
2084 gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
2085 if( obj ) canEdit = TRUE;
2088 if( pobj->type == ADDR_ITEM_FOLDER ) {
2089 if (iface->type != ADDR_IF_LDAP)
2090 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/NewGroup", TRUE );
2091 if( obj ) canEdit = TRUE;
2093 canDelete = canEdit;
2095 if( iface->type == ADDR_IF_LDAP ) {
2096 if( obj ) canBrowse = TRUE;
2103 /* Enable cut and paste */
2104 if( ! addrclip_is_empty( _clipBoard_ ) )
2106 if( ! addrselect_test_empty( _addressSelect_ ) )
2108 /* Enable copy if something is selected */
2109 if( ! addrselect_test_empty( _addressSelect_ ) )
2113 /* Disable edit or browse if more than one row selected */
2114 if( GTK_CMCLIST(clist)->selection && GTK_CMCLIST(clist)->selection->next ) {
2119 /* Forbid write changes when read-only */
2120 if( iface && iface->readOnly ) {
2126 /* Now go finalize menu items */
2127 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/Edit", canEdit );
2128 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/Delete", canDelete );
2130 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/Cut", canCut );
2131 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/Copy", canCopy );
2132 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/Paste", canPaste );
2134 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/Mailto", canCopy );
2136 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Cut", canCut );
2137 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Copy", canCopy );
2138 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Paste", canPaste );
2140 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Edit", canEdit );
2141 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Delete", canDelete );
2142 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Mailto", canCopy );
2144 gtk_widget_set_sensitive( addrbook.edit_btn, canEdit );
2145 gtk_widget_set_sensitive( addrbook.del_btn, canDelete );
2148 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/BrowseEntry", canBrowse );
2152 static void addressbook_select_row_tree (GtkCMCTree *ctree,
2153 GtkCMCTreeNode *node,
2160 * Add list of items into tree node below specified tree node.
2161 * \param treeNode Tree node.
2162 * \param ds Data source.
2163 * \param listItems List of items.
2165 static void addressbook_treenode_add_list(
2166 GtkCMCTreeNode *treeNode, AddressDataSource *ds, GList *listItems )
2172 AddrItemObject *aio;
2176 if( ADDRESS_OBJECT_TYPE(aio) == ITEMTYPE_GROUP ) {
2179 group = ( ItemGroup * ) aio;
2180 nn = addressbook_node_add_group( treeNode, ds, group );
2182 else if( ADDRESS_OBJECT_TYPE(aio) == ITEMTYPE_FOLDER ) {
2185 folder = ( ItemFolder * ) aio;
2186 nn = addressbook_node_add_folder(
2187 treeNode, ds, folder, ADDR_ITEM_FOLDER );
2189 node = g_list_next( node );
2193 static void addressbook_select_all_cb( GtkAction *action, gpointer data ) {
2194 gtk_cmclist_select_all(GTK_CMCLIST(addrbook.clist));
2198 * Cut from address list widget.
2200 static void addressbook_clip_cut_cb( GtkAction *action, gpointer data ) {
2201 _clipBoard_->cutFlag = TRUE;
2202 addrclip_clear( _clipBoard_ );
2203 addrclip_add( _clipBoard_, _addressSelect_ );
2204 /* addrclip_list_show( _clipBoard_, stdout ); */
2208 * Copy from address list widget.
2210 static void addressbook_clip_copy_cb(GtkAction *action, gpointer data) {
2211 _clipBoard_->cutFlag = FALSE;
2212 addrclip_clear( _clipBoard_ );
2213 addrclip_add( _clipBoard_, _addressSelect_ );
2214 /* addrclip_list_show( _clipBoard_, stdout ); */
2218 * Paste clipboard into address list widget.
2220 static void addressbook_clip_paste_cb( GtkAction *action, gpointer data ) {
2221 GtkCMCTree *ctree = GTK_CMCTREE( addrbook.ctree );
2222 AddressObject *pobj = NULL;
2223 AddressDataSource *ds = NULL;
2224 AddressBookFile *abf = NULL;
2225 ItemFolder *folder = NULL;
2226 GList *folderGroup = NULL;
2228 ds = addressbook_find_datasource( GTK_CMCTREE_NODE(addrbook.treeSelected) );
2229 if( ds == NULL ) return;
2230 if( addrindex_ds_get_readonly( ds ) ) {
2231 alertpanel_error( _("Cannot paste. Target address book is readonly.") );
2235 pobj = gtk_cmctree_node_get_row_data( ctree, addrbook.treeSelected );
2237 if( pobj->type == ADDR_ITEM_FOLDER ) {
2238 folder = ADAPTER_FOLDER(pobj)->itemFolder;
2240 else if( pobj->type == ADDR_ITEM_GROUP ) {
2241 alertpanel_error( _("Cannot paste into an address group.") );
2246 /* Get an address book */
2247 abf = addressbook_get_book_file();
2248 if( abf == NULL ) return;
2250 if( _clipBoard_->cutFlag ) {
2252 folderGroup = addrclip_paste_cut( _clipBoard_, abf, folder );
2254 /* Remove all groups and folders in clipboard from tree node */
2255 addressbook_treenode_remove_item();
2257 /* Remove all "cut" items */
2258 addrclip_delete_item( _clipBoard_ );
2260 /* Clear clipboard - cut items??? */
2261 addrclip_clear( _clipBoard_ );
2265 folderGroup = addrclip_paste_copy( _clipBoard_, abf, folder );
2268 /* addrclip_list_show( _clipBoard_, stdout ); */
2270 /* Update tree by inserting node for each folder or group */
2271 addressbook_treenode_add_list(
2272 addrbook.treeSelected, ds, folderGroup );
2273 gtk_cmctree_expand( ctree, addrbook.treeSelected );
2274 g_list_free( folderGroup );
2278 /* Display items pasted */
2279 gtk_sctree_select( GTK_SCTREE(ctree), addrbook.opened );
2280 addressbook_set_clist(
2281 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook.ctree),
2289 * Add current treenode object to clipboard. Note that widget only allows
2290 * one entry from the tree list to be selected.
2292 static void addressbook_treenode_to_clipboard( void ) {
2293 AddressObject *obj = NULL;
2294 AddressDataSource *ds = NULL;
2295 AddrSelectItem *item;
2296 GtkCMCTree *ctree = GTK_CMCTREE( addrbook.ctree );
2297 GtkCMCTreeNode *node;
2299 node = addrbook.treeSelected;
2300 if( node == NULL ) return;
2301 obj = gtk_cmctree_node_get_row_data( ctree, node );
2302 if( obj == NULL ) return;
2304 ds = addressbook_find_datasource( node );
2305 if( ds == NULL ) return;
2308 if( obj->type == ADDR_ITEM_FOLDER ) {
2309 AdapterFolder *adapter = ADAPTER_FOLDER(obj);
2310 ItemFolder *folder = adapter->itemFolder;
2312 item = addrselect_create_node( obj );
2313 item->uid = g_strdup( ADDRITEM_ID(folder) );
2315 else if( obj->type == ADDR_ITEM_GROUP ) {
2316 AdapterGroup *adapter = ADAPTER_GROUP(obj);
2317 ItemGroup *group = adapter->itemGroup;
2319 item = addrselect_create_node( obj );
2320 item->uid = g_strdup( ADDRITEM_ID(group) );
2322 else if( obj->type == ADDR_DATASOURCE ) {
2324 item = addrselect_create_node( obj );
2329 /* Clear existing list and add item into list */
2332 addressbook_list_select_clear();
2333 cacheID = addrindex_get_cache_id( _addressIndex_, ds );
2334 addrselect_list_add( _addressSelect_, item, cacheID );
2340 * Cut from tree widget.
2342 static void addressbook_treenode_cut_cb( GtkAction *action, gpointer data ) {
2343 _clipBoard_->cutFlag = TRUE;
2344 addressbook_treenode_to_clipboard();
2345 addrclip_clear( _clipBoard_ );
2346 addrclip_add( _clipBoard_, _addressSelect_ );
2347 /* addrclip_list_show( _clipBoard_, stdout ); */
2351 * Copy from tree widget.
2353 static void addressbook_treenode_copy_cb( GtkAction *action, gpointer data ) {
2354 _clipBoard_->cutFlag = FALSE;
2355 addressbook_treenode_to_clipboard();
2356 addrclip_clear( _clipBoard_ );
2357 addrclip_add( _clipBoard_, _addressSelect_ );
2358 /* addrclip_list_show( _clipBoard_, stdout ); */
2362 * Paste clipboard into address tree widget.
2364 static void addressbook_treenode_paste_cb( GtkAction *action, gpointer data ) {
2365 addressbook_clip_paste_cb(NULL,NULL);
2369 * Clear selected entries in clipboard.
2371 static void addressbook_list_select_clear( void ) {
2372 addrselect_list_clear( _addressSelect_ );
2376 * Add specified address item to selected address list.
2377 * \param aio Address item object.
2378 * \param ds Datasource.
2380 static void addressbook_list_select_add( AddrItemObject *aio, AddressDataSource *ds ) {
2383 if( ds == NULL ) return;
2384 cacheID = addrindex_get_cache_id( _addressIndex_, ds );
2385 addrselect_list_add_obj( _addressSelect_, aio, cacheID );
2390 * Remove specified address item from selected address list.
2391 * \param aio Address item object.
2393 static void addressbook_list_select_remove( AddrItemObject *aio ) {
2394 addrselect_list_remove( _addressSelect_, aio );
2398 * Invoke EMail compose window with addresses in selected address list.
2400 static void addressbook_mail_to_cb( GtkAction *action, gpointer data ) {
2403 if( ! addrselect_test_empty( _addressSelect_ ) ) {
2404 listAddress = addrselect_build_list( _addressSelect_ );
2405 compose_new_with_list( NULL, listAddress );
2406 mgu_free_dlist( listAddress );
2411 static void addressbook_list_row_selected( GtkCMCTree *clist,
2412 GtkCMCTreeNode *node,
2416 GtkEntry *entry = GTK_ENTRY(addrbook.entry);
2417 AddrItemObject *aio = NULL;
2418 AddressObject *pobj = NULL;
2419 AdapterDSource *ads = NULL;
2420 AddressDataSource *ds = NULL;
2422 gtk_entry_set_text( entry, "" );
2423 addrbook.listSelected = node;
2425 pobj = gtk_cmctree_node_get_row_data( GTK_CMCTREE(addrbook.ctree), addrbook.treeSelected );
2426 if( pobj == NULL ) return;
2428 if( pobj->type == ADDR_DATASOURCE ) {
2429 ads = ADAPTER_DSOURCE(pobj);
2430 ds = ads->dataSource;
2432 else if( pobj->type != ADDR_INTERFACE ) {
2433 ds = addressbook_find_datasource( addrbook.treeSelected );
2436 aio = gtk_cmctree_node_get_row_data( clist, node );
2438 /* g_print( "list select: %d : '%s'\n", aio->type, aio->name ); */
2439 addressbook_list_select_add( aio, ds );
2442 addressbook_list_menu_setup();
2444 if (!addrbook.target_compose && !prefs_common.addressbook_use_editaddress_dialog) {
2445 AddressObject *obj = gtk_cmctree_node_get_row_data( clist, addrbook.listSelected );
2447 if (obj && obj->type != ADDR_ITEM_GROUP)
2448 addressbook_edit_address(NULL, 0, NULL, FALSE);
2452 static void addressbook_list_row_unselected( GtkCMCTree *ctree,
2453 GtkCMCTreeNode *node,
2457 AddrItemObject *aio;
2459 aio = gtk_cmctree_node_get_row_data( ctree, node );
2461 /* g_print( "list unselect: %d : '%s'\n", aio->type, aio->name ); */
2462 addressbook_list_select_remove( aio );
2465 if (!prefs_common.addressbook_use_editaddress_dialog)
2466 addressbook_edit_person_invalidate(NULL, NULL, NULL);
2469 static gboolean addressbook_list_button_pressed(GtkWidget *widget,
2470 GdkEventButton *event,
2473 if( ! event ) return FALSE;
2475 addressbook_list_menu_setup();
2477 if( event->button == 3 ) {
2478 gtk_menu_popup( GTK_MENU(addrbook.list_popup), NULL, NULL, NULL, NULL,
2479 event->button, event->time );
2480 } else if (event->button == 1) {
2481 if (event->type == GDK_2BUTTON_PRESS) {
2482 if (prefs_common.add_address_by_click &&
2483 addrbook.target_compose)
2484 addressbook_to_clicked(NULL, GINT_TO_POINTER(COMPOSE_TO));
2486 if (prefs_common.addressbook_use_editaddress_dialog)
2487 addressbook_edit_address_cb(NULL, NULL);
2489 GtkCMCTree *clist = GTK_CMCTREE(addrbook.clist);
2490 AddressObject *obj = gtk_cmctree_node_get_row_data( clist, addrbook.listSelected );
2491 if( obj && obj->type == ADDR_ITEM_GROUP )
2492 addressbook_edit_address_cb(NULL, NULL);
2500 static gboolean addressbook_list_button_released(GtkWidget *widget,
2501 GdkEventButton *event,
2507 static gboolean addressbook_tree_button_pressed(GtkWidget *ctree,
2508 GdkEventButton *event,
2511 GtkCMCList *clist = GTK_CMCLIST(ctree);
2513 AddressObject *obj = NULL;
2514 AdapterDSource *ads = NULL;
2515 AddressInterface *iface = NULL;
2516 AddressDataSource *ds = NULL;
2517 gboolean canEdit = FALSE;
2518 gboolean canDelete = FALSE;
2519 gboolean canCut = FALSE;
2520 gboolean canCopy = FALSE;
2521 gboolean canPaste = FALSE;
2522 gboolean canTreeCut = FALSE;
2523 gboolean canTreeCopy = FALSE;
2524 gboolean canTreePaste = FALSE;
2525 gboolean canLookup = FALSE;
2526 GtkCMCTreeNode *node = NULL;
2528 if( ! event ) return FALSE;
2529 /* if( ! event || event->type != GDK_BUTTON_PRESS) return FALSE;*/
2531 if (event->button == 1) {
2532 if (event->type == GDK_2BUTTON_PRESS) {
2533 if( gtk_cmclist_get_selection_info( clist, event->x, event->y, &row, &column ) ) {
2534 gtkut_clist_set_focus_row(clist, row);
2535 obj = gtk_cmclist_get_row_data( clist, row );
2540 if (obj->type == ADDR_ITEM_GROUP) {
2542 addressbook_treenode_edit_cb(NULL, NULL);
2544 /* expand pr collapse */
2545 node = gtk_cmctree_node_nth(GTK_CMCTREE(ctree), row);
2546 gtk_cmctree_toggle_expansion(GTK_CMCTREE(ctree), node);
2552 addressbook_menubar_set_sensitive( FALSE );
2554 if( gtk_cmclist_get_selection_info( clist, event->x, event->y, &row, &column ) ) {
2555 gtkut_clist_set_focus_row(clist, row);
2556 obj = gtk_cmclist_get_row_data( clist, row );
2559 menu_set_insensitive_all(GTK_MENU_SHELL(addrbook.tree_popup));
2563 node = gtk_cmctree_node_nth(GTK_CMCTREE(clist), row);
2565 if( ! addrclip_is_empty( _clipBoard_ ) )
2566 canTreePaste = TRUE;
2568 if (obj->type == ADDR_INTERFACE) {
2569 AdapterInterface *adapter = ADAPTER_INTERFACE(obj);
2572 iface = adapter->interface;
2575 if( !iface->readOnly ) {
2576 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABTreePopup/NewBook", TRUE );
2577 gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
2579 if( iface->externalQuery )
2582 if (obj->type == ADDR_DATASOURCE) {
2583 ads = ADAPTER_DSOURCE(obj);
2584 ds = ads->dataSource;
2587 iface = ds->interface;
2590 if( !iface->readOnly ) {
2592 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABTreePopup/NewFolder", TRUE );
2593 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABTreePopup/NewGroup", TRUE );
2594 gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
2598 if( iface->externalQuery )
2601 else if (obj->type == ADDR_ITEM_FOLDER) {
2602 ds = addressbook_find_datasource( node );
2605 iface = ds->interface;
2608 if( !iface->readOnly ) {
2612 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABTreePopup/NewFolder", TRUE );
2613 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABTreePopup/NewGroup", TRUE );
2614 gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
2618 if( iface->externalQuery ) {
2619 /* Enable deletion of LDAP folder */
2624 else if (obj->type == ADDR_ITEM_GROUP) {
2625 ds = addressbook_find_datasource( node );
2628 iface = ds->interface;
2631 if( ! iface->readOnly ) {
2634 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/NewAddress", TRUE );
2635 gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
2639 if( canEdit && !addrselect_test_empty( _addressSelect_ ) )
2641 if( ! addrselect_test_empty( _addressSelect_ ) )
2643 if( ! addrclip_is_empty( _clipBoard_ ) )
2646 /* Forbid write changes when read-only */
2647 if( iface && iface->readOnly ) {
2649 canTreePaste = FALSE;
2657 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABTreePopup/EditBook", canEdit );
2658 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABTreePopup/DeleteBook", canDelete );
2659 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABTreePopup/Cut", canTreeCut );
2660 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABTreePopup/Copy", canTreeCopy );
2661 cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABTreePopup/Paste", canTreePaste );
2663 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Book/EditBook", canEdit );
2664 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Book/DeleteBook", canEdit );
2665 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Cut", canCut );
2666 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Copy", canCopy );
2667 cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Paste", canPaste );
2669 addressbook_show_buttons(addrbook.target_compose == NULL, canLookup,
2670 addrbook.target_compose != NULL);
2672 if( event->button == 3 )
2673 gtk_menu_popup(GTK_MENU(addrbook.tree_popup), NULL, NULL, NULL, NULL,
2674 event->button, event->time);
2679 static gboolean addressbook_tree_button_released(GtkWidget *ctree,
2680 GdkEventButton *event,
2683 gtkut_ctree_set_focus_row(GTK_CMCTREE(addrbook.ctree), addrbook.opened);
2687 static void addressbook_new_folder_cb(GtkAction *action, gpointer data)
2689 GtkCMCTree *ctree = GTK_CMCTREE(addrbook.ctree);
2690 AddressObject *obj = NULL;
2691 AddressDataSource *ds = NULL;
2692 AddressBookFile *abf = NULL;
2693 ItemFolder *parentFolder = NULL;
2694 ItemFolder *folder = NULL;
2696 if( ! addrbook.treeSelected ) return;
2697 obj = gtk_cmctree_node_get_row_data( ctree, addrbook.treeSelected );
2698 if( obj == NULL ) return;
2699 ds = addressbook_find_datasource( addrbook.treeSelected );
2700 if( ds == NULL ) return;
2702 if( obj->type == ADDR_DATASOURCE ) {
2703 if( ADAPTER_DSOURCE(obj)->subType != ADDR_BOOK ) return;
2705 else if( obj->type == ADDR_ITEM_FOLDER ) {
2706 parentFolder = ADAPTER_FOLDER(obj)->itemFolder;
2712 abf = ds->rawDataSource;
2713 if( abf == NULL ) return;
2714 folder = addressbook_edit_folder( abf, parentFolder, NULL );
2717 nn = addressbook_node_add_folder(
2718 addrbook.treeSelected, ds, folder, ADDR_ITEM_FOLDER );
2719 gtk_cmctree_expand( ctree, addrbook.treeSelected );
2720 if( addrbook.treeSelected == addrbook.opened )
2721 addressbook_set_clist(obj, TRUE);
2725 static void addressbook_new_group_cb(GtkAction *action, gpointer data)
2727 GtkCMCTree *ctree = GTK_CMCTREE(addrbook.ctree);
2728 AddressObject *obj = NULL;
2729 AddressDataSource *ds = NULL;
2730 AddressBookFile *abf = NULL;
2731 ItemFolder *parentFolder = NULL;
2732 ItemGroup *group = NULL;
2734 if( ! addrbook.treeSelected ) return;
2735 obj = gtk_cmctree_node_get_row_data(ctree, addrbook.treeSelected);
2736 if( obj == NULL ) return;
2737 ds = addressbook_find_datasource( addrbook.treeSelected );
2738 if( ds == NULL ) return;
2740 if( obj->type == ADDR_DATASOURCE ) {
2741 if( ADAPTER_DSOURCE(obj)->subType != ADDR_BOOK ) return;
2743 else if( obj->type == ADDR_ITEM_FOLDER ) {
2744 parentFolder = ADAPTER_FOLDER(obj)->itemFolder;
2750 abf = ds->rawDataSource;
2751 if( abf == NULL ) return;
2752 group = addressbook_edit_group( abf, parentFolder, NULL );
2755 nn = addressbook_node_add_group( addrbook.treeSelected, ds, group );
2756 gtk_cmctree_expand( ctree, addrbook.treeSelected );
2757 if( addrbook.treeSelected == addrbook.opened )
2758 addressbook_set_clist(obj, TRUE);
2762 static void addressbook_change_node_name(GtkCMCTreeNode *node, const gchar *name)
2764 GtkCMCTree *ctree = GTK_CMCTREE(addrbook.ctree);
2767 GdkPixmap *pix_cl, *pix_op;
2768 GdkBitmap *mask_cl, *mask_op;
2769 gboolean is_leaf, expanded;
2771 gtk_cmctree_get_node_info(ctree, node, text, &spacing,
2772 &pix_cl, &mask_cl, &pix_op, &mask_op,
2773 &is_leaf, &expanded);
2774 gtk_sctree_set_node_info(ctree, node, name, spacing,
2775 pix_cl, mask_cl, pix_op, mask_op,
2781 * \param obj Address object to edit.
2782 * \param node Node in tree.
2783 * \return New name of data source.
2785 static gchar *addressbook_edit_datasource( AddressObject *obj, GtkCMCTreeNode *node ) {
2786 gchar *newName = NULL;
2787 AddressDataSource *ds = NULL;
2788 AddressInterface *iface = NULL;
2789 AdapterDSource *ads = NULL;
2791 ds = addressbook_find_datasource( node );
2792 if( ds == NULL ) return NULL;
2793 iface = ds->interface;
2794 if( ! iface->haveLibrary ) return NULL;
2796 /* Read data from data source */
2797 if( addrindex_ds_get_modify_flag( ds ) ) {
2798 addrindex_ds_read_data( ds );
2801 if( ! addrindex_ds_get_read_flag( ds ) ) {
2802 addrindex_ds_read_data( ds );
2806 ads = ADAPTER_DSOURCE(obj);
2807 if( ads->subType == ADDR_BOOK ) {
2808 if( addressbook_edit_book( _addressIndex_, ads ) == NULL ) return NULL;
2810 else if( ads->subType == ADDR_VCARD ) {
2811 if( addressbook_edit_vcard( _addressIndex_, ads ) == NULL ) return NULL;
2814 else if( ads->subType == ADDR_JPILOT ) {
2815 if( addressbook_edit_jpilot( _addressIndex_, ads ) == NULL ) return NULL;
2819 else if( ads->subType == ADDR_LDAP ) {
2820 if( addressbook_edit_ldap( _addressIndex_, ads ) == NULL ) return NULL;
2826 newName = obj->name;
2831 * Edit an object that is in the address tree area.
2833 static void addressbook_treenode_edit_cb(GtkAction *action, gpointer data)
2835 GtkCMCTree *ctree = GTK_CMCTREE(addrbook.ctree);
2837 AddressDataSource *ds = NULL;
2838 AddressBookFile *abf = NULL;
2839 GtkCMCTreeNode *node = NULL, *parentNode = NULL;
2842 if( ! addrbook.treeSelected ) return;
2843 node = addrbook.treeSelected;
2844 if( GTK_CMCTREE_ROW(node)->level == 1 ) return;
2845 obj = gtk_cmctree_node_get_row_data( ctree, node );
2846 if( obj == NULL ) return;
2847 parentNode = GTK_CMCTREE_ROW(node)->parent;
2849 ds = addressbook_find_datasource( node );
2850 if( ds == NULL ) return;
2852 if( obj->type == ADDR_DATASOURCE ) {
2853 name = addressbook_edit_datasource( obj, node );
2854 if( name == NULL ) return;
2857 abf = ds->rawDataSource;
2858 if( abf == NULL ) return;
2859 if( obj->type == ADDR_ITEM_FOLDER ) {
2860 AdapterFolder *adapter = ADAPTER_FOLDER(obj);
2861 ItemFolder *item = adapter->itemFolder;
2862 ItemFolder *parentFolder = NULL;
2863 parentFolder = ( ItemFolder * ) ADDRITEM_PARENT(item);
2864 if( addressbook_edit_folder( abf, parentFolder, item ) == NULL ) return;
2865 name = ADDRITEM_NAME(item);
2867 else if( obj->type == ADDR_ITEM_GROUP ) {
2868 AdapterGroup *adapter = ADAPTER_GROUP(obj);
2869 ItemGroup *item = adapter->itemGroup;
2870 ItemFolder *parentFolder = NULL;
2871 parentFolder = ( ItemFolder * ) ADDRITEM_PARENT(item);
2872 if( addressbook_edit_group( abf, parentFolder, item ) == NULL ) return;
2873 name = ADDRITEM_NAME(item);
2876 if( name && parentNode ) {
2877 /* Update node in tree view */
2878 addressbook_change_node_name( node, name );
2879 gtk_sctree_sort_node(ctree, parentNode);
2880 gtk_cmctree_expand( ctree, node );
2881 gtk_sctree_select( GTK_SCTREE( ctree), node );
2888 ADDRTREE_DEL_FOLDER_ONLY,
2889 ADDRTREE_DEL_FOLDER_ADDR
2893 * Delete an item from the tree widget.
2894 * \param data Data passed in.
2895 * \param action Action.
2896 * \param widget Widget issuing callback.
2898 static void addressbook_treenode_delete_cb(GtkAction *action, gpointer data)
2900 GtkCMCTree *ctree = GTK_CMCTREE(addrbook.ctree);
2901 GtkCMCTreeNode *node = NULL;
2905 AddrBookBase *adbase;
2906 AddressCache *cache;
2907 AdapterDSource *ads = NULL;
2908 AddressInterface *iface = NULL;
2909 AddressDataSource *ds = NULL;
2910 gboolean remFlag = FALSE;
2911 TreeItemDelType delType;
2913 if( ! addrbook.treeSelected ) return;
2914 node = addrbook.treeSelected;
2915 if( GTK_CMCTREE_ROW(node)->level == 1 ) return;
2917 obj = gtk_cmctree_node_get_row_data( ctree, node );
2918 g_return_if_fail(obj != NULL);
2920 if( obj->type == ADDR_DATASOURCE ) {
2921 ads = ADAPTER_DSOURCE(obj);
2922 if( ads == NULL ) return;
2923 ds = ads->dataSource;
2924 if( ds == NULL ) return;
2927 /* Must be folder or something else */
2928 ds = addressbook_find_datasource( node );
2929 if( ds == NULL ) return;
2931 /* Only allow deletion from non-readOnly */
2932 iface = ds->interface;
2933 if( iface->readOnly ) {
2934 /* Allow deletion of query results */
2935 if( ! iface->externalQuery ) return;
2939 /* Confirm deletion */
2940 delType = ADDRTREE_DEL_NONE;
2941 if( obj->type == ADDR_ITEM_FOLDER ) {
2942 if( iface->externalQuery ) {
2943 message = g_strdup_printf( _(
2944 "Do you want to delete the query " \
2945 "results and addresses in '%s' ?" ),
2947 aval = alertpanel( _("Delete"), message,
2948 GTK_STOCK_CANCEL, "+"GTK_STOCK_DELETE, NULL );
2950 if( aval == G_ALERTALTERNATE ) {
2951 delType = ADDRTREE_DEL_FOLDER_ADDR;
2955 message = g_strdup_printf
2956 ( _( "Do you want to delete '%s' ? "
2957 "If you delete the folder only, the addresses it contains will be moved into the parent folder." ),
2959 aval = alertpanel( _("Delete folder"), message,
2960 GTK_STOCK_CANCEL, _("+Delete _folder only"), _("Delete folder and _addresses"));
2962 if( aval == G_ALERTALTERNATE ) {
2963 delType = ADDRTREE_DEL_FOLDER_ONLY;
2965 else if( aval == G_ALERTOTHER ) {
2966 delType = ADDRTREE_DEL_FOLDER_ADDR;
2970 else if( obj->type == ADDR_ITEM_GROUP ) {
2971 message = g_strdup_printf(_("Do you want to delete '%s'?\n"
2972 "The addresses it contains will not be lost."), obj->name);
2973 aval = alertpanel(_("Delete"), message, GTK_STOCK_CANCEL,
2974 "+" GTK_STOCK_DELETE, NULL);
2976 if( aval == G_ALERTALTERNATE ) delType = ADDRTREE_DEL_FOLDER_ONLY;
2978 message = g_strdup_printf(_("Do you want to delete '%s'?\n"
2979 "The addresses it contains will be lost."), obj->name);
2980 aval = alertpanel(_("Delete"), message, GTK_STOCK_CANCEL,
2981 "+" GTK_STOCK_DELETE, NULL);
2983 if( aval == G_ALERTALTERNATE ) delType = ADDRTREE_DEL_DATA;
2985 if( delType == ADDRTREE_DEL_NONE ) return;
2987 /* Proceed with deletion */
2988 if( obj->type == ADDR_DATASOURCE ) {
2989 /* Remove node from tree */
2990 gtk_cmctree_remove_node( ctree, node );
2992 /* Remove data source. */
2993 if( addrindex_index_remove_datasource( _addressIndex_, ds ) ) {
2994 addrindex_free_datasource( ds );
2999 /* Get reference to cache */
3000 adbase = ( AddrBookBase * ) ds->rawDataSource;
3001 if( adbase == NULL ) return;
3002 cache = adbase->addressCache;
3004 /* Remove query results folder */
3005 if( iface->externalQuery ) {
3006 AdapterFolder *adapter = ADAPTER_FOLDER(obj);
3007 ItemFolder *folder = adapter->itemFolder;
3009 adapter->itemFolder = NULL;
3011 g_print( "remove folder for ::%s::\n", obj->name );
3012 g_print( " folder name ::%s::\n", ADDRITEM_NAME(folder) );
3013 g_print( "-------------- remove results\n" );
3015 addrindex_remove_results( ds, folder );
3016 /* g_print( "-------------- remove node\n" ); */
3017 gtk_cmctree_remove_node( ctree, node );
3021 /* Code below is valid for regular address book deletion */
3022 if( obj->type == ADDR_ITEM_FOLDER ) {
3023 AdapterFolder *adapter = ADAPTER_FOLDER(obj);
3024 ItemFolder *item = adapter->itemFolder;
3026 if( delType == ADDRTREE_DEL_FOLDER_ONLY ) {
3027 /* Remove folder only */
3028 item = addrcache_remove_folder( cache, item );
3030 addritem_free_item_folder( item );
3031 addressbook_move_nodes_up( ctree, node );
3035 else if( delType == ADDRTREE_DEL_FOLDER_ADDR ) {
3036 /* Remove folder and addresses */
3037 item = addrcache_remove_folder_delete( cache, item );
3039 addritem_free_item_folder( item );
3044 else if( obj->type == ADDR_ITEM_GROUP ) {
3045 AdapterGroup *adapter = ADAPTER_GROUP(obj);
3046 ItemGroup *item = adapter->itemGroup;
3048 item = addrcache_remove_group( cache, item );
3050 addritem_free_item_group( item );
3057 gtk_cmctree_remove_node(ctree, node );
3061 static void addressbook_new_address_from_book_post_cb( ItemPerson *person )
3063 if( person && addrbook.treeSelected == addrbook.opened ) {
3064 person->status = ADD_ENTRY;
3065 gtk_cmclist_unselect_all( GTK_CMCLIST(addrbook.clist) );
3066 addressbook_folder_refresh_one_person(
3067 GTK_CMCTREE(addrbook.clist), person );
3069 addressbook_address_list_set_focus();
3072 static void addressbook_new_address_from_folder_post_cb( ItemPerson *person )
3074 if( person && addrbook.treeSelected == addrbook.opened) {
3075 person->status = ADD_ENTRY;
3076 gtk_sctree_select( GTK_SCTREE(addrbook.ctree), addrbook.opened );
3077 addressbook_set_clist(
3078 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook.ctree),
3082 addressbook_address_list_set_focus();
3086 * Label (a format string) that is used to name each folder.
3088 static gchar *_queryFolderLabel_ = N_( "Search '%s'" );
3091 * Search ctree widget callback function.
3092 * \param pA Pointer to node.
3093 * \param pB Pointer to data item being sought.
3094 * \return Zero (0) if folder found.
3096 static int addressbook_treenode_find_folder_cb( gconstpointer pA, gconstpointer pB ) {
3099 aoA = ( AddressObject * ) pA;
3100 if( aoA->type == ADDR_ITEM_FOLDER ) {
3101 ItemFolder *folder, *fld;
3103 fld = ADAPTER_FOLDER(aoA)->itemFolder;
3104 folder = ( ItemFolder * ) pB;
3105 if( fld == folder ) return 0; /* Found folder */
3110 static ItemFolder * addressbook_setup_subf(
3111 AddressDataSource *ds, gchar *title,
3112 GtkCMCTreeNode *pNode )
3114 AddrBookBase *adbase;
3115 AddressCache *cache;
3118 GtkCMCTreeNode *nNode;
3120 AddressObjectType aoType = ADDR_NONE;
3123 if( *title == '\0' || strlen( title ) < 1 ) return NULL;
3125 if( ds && ds->type == ADDR_IF_LDAP ) {
3127 aoType = ADDR_LDAP_QUERY;
3134 ctree = GTK_CMCTREE(addrbook.ctree);
3135 /* Get reference to address cache */
3136 adbase = ( AddrBookBase * ) ds->rawDataSource;
3137 cache = adbase->addressCache;
3139 if ((children = addrcache_get_list_folder(cache)) != NULL) {
3140 GList *cur = children;
3141 for (; cur; cur = cur->next) {
3142 ItemFolder *child = (ItemFolder *) cur->data;
3143 if (!strcmp2(ADDRITEM_NAME(child), title)) {
3144 nNode = gtk_cmctree_find_by_row_data_custom(
3146 addressbook_treenode_find_folder_cb );
3148 addrindex_remove_results( ds, child );
3149 while( child->listPerson ) {
3150 ItemPerson *item = ( ItemPerson * ) child->listPerson->data;
3151 item = addrcache_remove_person( cache, item );
3153 addritem_free_item_person( item );
3157 gtk_sctree_select( GTK_SCTREE(ctree), nNode );
3158 addrbook.treeSelected = nNode;
3165 /* Create a folder */
3166 folder = addrcache_add_new_folder( cache, NULL );
3167 name = g_strdup_printf( "%s", title );
3168 addritem_folder_set_name( folder, name );
3169 addritem_folder_set_remarks( folder, "" );
3172 /* Now let's see the folder */
3173 nNode = addressbook_node_add_folder( pNode, ds, folder, aoType );
3174 gtk_cmctree_expand( ctree, pNode );
3176 gtk_sctree_select( GTK_SCTREE(ctree), nNode );
3177 addrbook.treeSelected = nNode;
3183 static void addressbook_new_address_cb( GtkAction *action, gpointer data ) {
3184 AddressObject *pobj = NULL;
3185 AddressDataSource *ds = NULL;
3186 AddressBookFile *abf = NULL;
3187 debug_print("adding address\n");
3188 pobj = gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook.ctree), addrbook.treeSelected);
3189 if( pobj == NULL ) {
3190 debug_print("no row data\n");
3193 ds = addressbook_find_datasource( GTK_CMCTREE_NODE(addrbook.treeSelected) );
3195 debug_print("no datasource\n");
3199 abf = ds->rawDataSource;
3201 g_print("no addressbook file\n");
3205 if( pobj->type == ADDR_DATASOURCE ) {
3206 if (ADAPTER_DSOURCE(pobj)->subType == ADDR_BOOK ||
3207 ADAPTER_DSOURCE(pobj)->subType == ADDR_LDAP) {
3209 ItemFolder *folder = NULL;
3211 if (abf && abf->type == ADDR_IF_LDAP) {
3212 GtkCMCTreeNode *parentNode;
3213 ds = addressbook_find_datasource( GTK_CMCTREE_NODE( addrbook.treeSelected ) );
3214 if( ds == NULL ) return;
3216 /* We must have a datasource that is an external interface */
3217 if( ! ds->interface->haveLibrary ) return;
3218 if( ! ds->interface->externalQuery ) return;
3220 if( pobj->type == ADDR_ITEM_FOLDER ) {
3221 parentNode = GTK_CMCTREE_ROW(GTK_CMCTREE_NODE( addrbook.treeSelected ) )->parent;
3224 parentNode = GTK_CMCTREE_NODE( addrbook.treeSelected );
3226 folder = addressbook_setup_subf( ds, _("New Contacts"), parentNode );
3228 pobj = gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook.ctree), addrbook.treeSelected);
3229 ds = addressbook_find_datasource( GTK_CMCTREE_NODE(addrbook.treeSelected) );
3230 abf = ds->rawDataSource;
3233 person = addressbook_edit_person( abf, folder, NULL, FALSE,
3234 addrbook.editaddress_vbox,
3235 addressbook_new_address_from_book_post_cb,
3238 if (abf && abf->type == ADDR_IF_LDAP) {