2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2006 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 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 #include <glib/gi18n.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <gtk/gtkwindow.h>
30 #include <gtk/gtksignal.h>
31 #include <gtk/gtkvbox.h>
32 #include <gtk/gtkscrolledwindow.h>
33 #include <gtk/gtkhpaned.h>
34 #include <gtk/gtkhbox.h>
35 #include <gtk/gtklabel.h>
36 #include <gtk/gtkentry.h>
37 #include <gtk/gtkctree.h>
38 #include <gtk/gtkclist.h>
39 #include <gtk/gtktable.h>
40 #include <gtk/gtkhbbox.h>
41 #include <gtk/gtkbutton.h>
42 #include <gtk/gtkmenu.h>
43 #include <gtk/gtkmenuitem.h>
44 #include <gtk/gtkitemfactory.h>
49 #include "addressbook.h"
50 #include "manage_window.h"
51 #include "prefs_common.h"
52 #include "alertpanel.h"
53 #include "inputdialog.h"
55 #include "stock_pixmap.h"
57 #include "prefs_gtk.h"
63 #include "addr_compl.h"
66 #include "addressitem.h"
68 #include "addrcache.h"
70 #include "addrindex.h"
71 #include "addressadd.h"
72 #include "addressbook_foldersel.h"
74 #include "editvcard.h"
75 #include "editgroup.h"
76 #include "editaddress.h"
78 #include "importldif.h"
79 #include "importmutt.h"
80 #include "importpine.h"
85 #include "editjpilot.h"
90 #include "ldapserver.h"
93 #define ADDRESSBOOK_LDAP_BUSYMSG "Busy"
96 #include "addrquery.h"
97 #include "addrselect.h"
99 #include "addrgather.h"
100 #include "adbookbase.h"
101 #include "exphtmldlg.h"
102 #include "expldifdlg.h"
103 #include "browseldap.h"
109 } AddressIndexColumns
;
117 } AddressListColumns
;
120 AddressBookFile
*book
;
128 AddressDataSource
*book
;
132 static gchar
*list_titles
[] = { N_("Name"),
136 #define COL_NAME_WIDTH 164
137 #define COL_ADDRESS_WIDTH 156
139 #define COL_FOLDER_WIDTH 170
140 #define ADDRESSBOOK_WIDTH 640
141 #define ADDRESSBOOK_HEIGHT 360
143 #define ADDRESSBOOK_MSGBUF_SIZE 2048
145 static GdkPixmap
*folderxpm
;
146 static GdkBitmap
*folderxpmmask
;
147 static GdkPixmap
*folderopenxpm
;
148 static GdkBitmap
*folderopenxpmmask
;
149 static GdkPixmap
*groupxpm
;
150 static GdkBitmap
*groupxpmmask
;
151 static GdkPixmap
*interfacexpm
;
152 static GdkBitmap
*interfacexpmmask
;
153 static GdkPixmap
*bookxpm
;
154 static GdkBitmap
*bookxpmmask
;
155 static GdkPixmap
*addressxpm
;
156 static GdkBitmap
*addressxpmmask
;
157 static GdkPixmap
*vcardxpm
;
158 static GdkBitmap
*vcardxpmmask
;
159 static GdkPixmap
*jpilotxpm
;
160 static GdkBitmap
*jpilotxpmmask
;
161 static GdkPixmap
*categoryxpm
;
162 static GdkBitmap
*categoryxpmmask
;
163 static GdkPixmap
*ldapxpm
;
164 static GdkBitmap
*ldapxpmmask
;
165 static GdkPixmap
*addrsearchxpm
;
166 static GdkPixmap
*addrsearchxpmmask
;
169 static gchar addressbook_msgbuf
[ ADDRESSBOOK_MSGBUF_SIZE
];
171 /* Address list selection */
172 static AddrSelectList
*_addressSelect_
= NULL
;
173 static AddressClipboard
*_clipBoard_
= NULL
;
175 /* Address index file and interfaces */
176 static AddressIndex
*_addressIndex_
= NULL
;
177 static GList
*_addressInterfaceList_
= NULL
;
178 static GList
*_addressIFaceSelection_
= NULL
;
179 #define ADDRESSBOOK_IFACE_SELECTION "1/y,3/y,4/y,2/n"
181 static AddressBook_win addrbook
;
183 static GHashTable
*_addressBookTypeHash_
= NULL
;
184 static GList
*_addressBookTypeList_
= NULL
;
186 static void addressbook_create (void);
187 static gint
addressbook_close (void);
188 static void addressbook_button_set_sensitive (void);
190 static gboolean address_index_has_focus
= FALSE
;
191 static gboolean address_list_has_focus
= FALSE
;
193 /* callback functions */
194 static void addressbook_del_clicked (GtkButton
*button
,
196 static void addressbook_reg_clicked (GtkButton
*button
,
198 static void addressbook_to_clicked (GtkButton
*button
,
200 static void addressbook_lup_clicked (GtkButton
*button
,
202 static void addressbook_close_clicked (GtkButton
*button
,
205 static void addressbook_tree_selected (GtkCTree
*ctree
,
209 static void addressbook_select_row_tree (GtkCTree
*ctree
,
213 static void addressbook_list_row_selected (GtkCTree
*clist
,
217 static void addressbook_list_row_unselected (GtkCTree
*clist
,
221 static void addressbook_person_expand_node (GtkCTree
*ctree
,
224 static void addressbook_person_collapse_node (GtkCTree
*ctree
,
228 static gboolean
addressbook_list_button_pressed (GtkWidget
*widget
,
229 GdkEventButton
*event
,
231 static gboolean
addressbook_list_button_released(GtkWidget
*widget
,
232 GdkEventButton
*event
,
234 static gboolean
addressbook_tree_button_pressed (GtkWidget
*ctree
,
235 GdkEventButton
*event
,
237 static gboolean
addressbook_tree_button_released(GtkWidget
*ctree
,
238 GdkEventButton
*event
,
241 static void addressbook_new_folder_cb (gpointer data
,
244 static void addressbook_new_group_cb (gpointer data
,
247 static void addressbook_treenode_edit_cb (gpointer data
,
250 static void addressbook_treenode_delete_cb (gpointer data
,
254 static void addressbook_change_node_name (GtkCTreeNode
*node
,
257 static void addressbook_new_address_cb (gpointer data
,
260 static void addressbook_edit_address_cb (gpointer data
,
263 static void addressbook_delete_address_cb (gpointer data
,
267 static void close_cb (gpointer data
,
270 static void addressbook_file_save_cb (gpointer data
,
274 /* Data source edit stuff */
275 static void addressbook_new_book_cb (gpointer data
,
278 static void addressbook_new_vcard_cb (gpointer data
,
283 static void addressbook_new_jpilot_cb (gpointer data
,
289 static void addressbook_new_ldap_cb (gpointer data
,
294 static void addressbook_set_clist (AddressObject
*obj
,
297 static void addressbook_load_tree (void);
298 void addressbook_read_file (void);
300 static GtkCTreeNode
*addressbook_add_object (GtkCTreeNode
*node
,
302 static void addressbook_treenode_remove_item ( void );
304 static AddressDataSource
*addressbook_find_datasource
305 (GtkCTreeNode
*node
);
307 static AddressBookFile
*addressbook_get_book_file(void);
309 static GtkCTreeNode
*addressbook_node_add_folder
311 AddressDataSource
*ds
,
312 ItemFolder
*itemFolder
,
313 AddressObjectType otype
);
314 static GtkCTreeNode
*addressbook_node_add_group (GtkCTreeNode
*node
,
315 AddressDataSource
*ds
,
316 ItemGroup
*itemGroup
);
317 static void addressbook_tree_remove_children (GtkCTree
*ctree
,
318 GtkCTreeNode
*parent
);
319 static void addressbook_move_nodes_up (GtkCTree
*ctree
,
321 static GtkCTreeNode
*addressbook_find_group_node (GtkCTreeNode
*parent
,
323 static gboolean
addressbook_entry_key_pressed (GtkWidget
*widget
,
326 static gint
addressbook_treenode_compare_func (GtkCList
*clist
,
329 static void addressbook_folder_load_one_person (GtkCTree
*clist
,
331 AddressTypeControlItem
*atci
,
332 AddressTypeControlItem
*atciMail
);
333 static void addressbook_folder_refresh_one_person(GtkCTree
*clist
,
335 static void addressbook_folder_remove_one_person(GtkCTree
*clist
,
337 static void addressbook_folder_remove_node (GtkCTree
*clist
,
340 /* LUT's and IF stuff */
341 static void addressbook_free_treenode ( gpointer data
);
342 AddressTypeControlItem
*addrbookctl_lookup (gint ot
);
343 AddressTypeControlItem
*addrbookctl_lookup_iface(AddressIfType ifType
);
345 void addrbookctl_build_map (GtkWidget
*window
);
346 void addrbookctl_build_iflist (void);
347 AdapterInterface
*addrbookctl_find_interface (AddressIfType ifType
);
348 void addrbookctl_build_ifselect (void);
350 static void addrbookctl_free_interface (AdapterInterface
*adapter
);
351 static void addrbookctl_free_datasource (AdapterDSource
*adapter
);
352 static void addrbookctl_free_folder (AdapterFolder
*adapter
);
353 static void addrbookctl_free_group (AdapterGroup
*adapter
);
355 static void addressbook_list_select_clear ( void );
356 static void addressbook_list_select_add ( AddrItemObject
*aio
,
357 AddressDataSource
*ds
);
358 static void addressbook_list_select_remove ( AddrItemObject
*aio
);
360 static void addressbook_import_ldif_cb ( void );
361 static void addressbook_import_mutt_cb ( void );
362 static void addressbook_import_pine_cb ( void );
363 static void addressbook_export_html_cb ( void );
364 static void addressbook_export_ldif_cb ( void );
365 static void addressbook_select_all_cb ( void );
366 static void addressbook_clip_cut_cb ( void );
367 static void addressbook_clip_copy_cb ( void );
368 static void addressbook_clip_paste_cb ( void );
369 static void addressbook_treenode_cut_cb ( void );
370 static void addressbook_treenode_copy_cb ( void );
371 static void addressbook_treenode_paste_cb ( void );
373 static void addressbook_mail_to_cb ( void );
376 static void addressbook_browse_entry_cb ( void );
378 static void addressbook_edit_clicked(GtkButton
*button
, gpointer data
);
380 static void addressbook_start_drag(GtkWidget
*widget
, gint button
,
383 static void addressbook_drag_data_get(GtkWidget
*widget
,
384 GdkDragContext
*drag_context
,
385 GtkSelectionData
*selection_data
,
389 static gboolean
addressbook_drag_motion_cb(GtkWidget
*widget
,
390 GdkDragContext
*context
,
395 static void addressbook_drag_leave_cb(GtkWidget
*widget
,
396 GdkDragContext
*context
,
399 static void addressbook_drag_received_cb(GtkWidget
*widget
,
400 GdkDragContext
*drag_context
,
403 GtkSelectionData
*data
,
407 static void addressbook_list_menu_setup( void );
409 static GtkTargetEntry addressbook_drag_types
[] =
411 {"claws-mail/internal", GTK_TARGET_SAME_APP
, TARGET_DUMMY
}
414 static GtkTargetList
*addressbook_target_list
= NULL
;
417 static GtkItemFactoryEntry addressbook_entries
[] =
419 {N_("/_Book"), NULL
, NULL
, 0, "<Branch>"},
420 {N_("/_Book/New _Book"), "<control>B", addressbook_new_book_cb
, 0, NULL
},
421 {N_("/_Book/New _Folder"), "<control>R", addressbook_new_folder_cb
, 0, NULL
},
422 {N_("/_Book/New _vCard"), "<control><shift>D", addressbook_new_vcard_cb
, 0, NULL
},
424 {N_("/_Book/New _JPilot"), "<control>J", addressbook_new_jpilot_cb
, 0, NULL
},
427 {N_("/_Book/New LDAP _Server"), "<control><shift>S", addressbook_new_ldap_cb
, 0, NULL
},
429 {N_("/_Book/---"), NULL
, NULL
, 0, "<Separator>"},
430 {N_("/_Book/_Edit book"), NULL
, addressbook_treenode_edit_cb
, 0, NULL
},
431 {N_("/_Book/_Delete book"), NULL
, addressbook_treenode_delete_cb
, 0, NULL
},
432 {N_("/_Book/---"), NULL
, NULL
, 0, "<Separator>"},
433 {N_("/_Book/_Save"), "<control>S", addressbook_file_save_cb
, 0, NULL
},
434 {N_("/_Book/_Close"), "<control>W", close_cb
, 0, NULL
},
435 {N_("/_Address"), NULL
, NULL
, 0, "<Branch>"},
436 {N_("/_Address/_Select all"), "<control>A", addressbook_select_all_cb
, 0, NULL
},
437 {N_("/_Address/---"), NULL
, NULL
, 0, "<Separator>"},
438 {N_("/_Address/C_ut"), "<control>X", addressbook_clip_cut_cb
, 0, NULL
},
439 {N_("/_Address/_Copy"), "<control>C", addressbook_clip_copy_cb
, 0, NULL
},
440 {N_("/_Address/_Paste"), "<control>V", addressbook_clip_paste_cb
, 0, NULL
},
441 {N_("/_Address/---"), NULL
, NULL
, 0, "<Separator>"},
442 {N_("/_Address/_Edit"), "<control>Return",addressbook_edit_address_cb
, 0, NULL
},
443 {N_("/_Address/_Delete"), "<control>D", addressbook_delete_address_cb
, 0, NULL
},
444 {N_("/_Address/---"), NULL
, NULL
, 0, "<Separator>"},
445 {N_("/_Address/New _Address"), "<control>N", addressbook_new_address_cb
, 0, NULL
},
446 {N_("/_Address/New _Group"), "<control>G", addressbook_new_group_cb
, 0, NULL
},
447 {N_("/_Address/---"), NULL
, NULL
, 0, "<Separator>"},
448 {N_("/_Address/_Mail To"), NULL
, addressbook_mail_to_cb
, 0, NULL
},
449 {N_("/_Tools"), NULL
, NULL
, 0, "<Branch>"},
450 {N_("/_Tools/Import _LDIF file..."), NULL
, addressbook_import_ldif_cb
, 0, NULL
},
451 {N_("/_Tools/Import M_utt file..."), NULL
, addressbook_import_mutt_cb
, 0, NULL
},
452 {N_("/_Tools/Import _Pine file..."), NULL
, addressbook_import_pine_cb
, 0, NULL
},
453 {N_("/_Tools/---"), NULL
, NULL
, 0, "<Separator>"},
454 {N_("/_Tools/Export _HTML..."), NULL
, addressbook_export_html_cb
, 0, NULL
},
455 {N_("/_Tools/Export LDI_F..."), NULL
, addressbook_export_ldif_cb
, 0, NULL
},
456 {N_("/_Help"), NULL
, NULL
, 0, "<Branch>"},
457 {N_("/_Help/_About"), NULL
, about_show
, 0, NULL
}
460 static GtkItemFactoryEntry addressbook_tree_popup_entries
[] =
462 {N_("/_Edit"), NULL
, addressbook_treenode_edit_cb
, 0, NULL
},
463 {N_("/_Delete"), NULL
, addressbook_treenode_delete_cb
, 0, NULL
},
464 {"/---", NULL
, NULL
, 0, "<Separator>"},
465 {N_("/New _Book"), NULL
, addressbook_new_book_cb
, 0, NULL
},
466 {N_("/New _Folder"), NULL
, addressbook_new_folder_cb
, 0, NULL
},
467 {N_("/New _Group"), NULL
, addressbook_new_group_cb
, 0, NULL
},
468 {"/---", NULL
, NULL
, 0, "<Separator>"},
469 {N_("/C_ut"), NULL
, addressbook_treenode_cut_cb
, 0, NULL
},
470 {N_("/_Copy"), NULL
, addressbook_treenode_copy_cb
, 0, NULL
},
471 {N_("/_Paste"), NULL
, addressbook_treenode_paste_cb
, 0, NULL
}
474 static GtkItemFactoryEntry addressbook_list_popup_entries
[] =
476 {N_("/_Select all"), NULL
, addressbook_select_all_cb
, 0, NULL
},
477 {"/---", NULL
, NULL
, 0, "<Separator>"},
478 {N_("/_Edit"), NULL
, addressbook_edit_address_cb
, 0, NULL
},
479 {N_("/_Delete"), NULL
, addressbook_delete_address_cb
, 0, NULL
},
480 {"/---", NULL
, NULL
, 0, "<Separator>"},
481 {N_("/New _Address"), NULL
, addressbook_new_address_cb
, 0, NULL
},
482 {N_("/New _Group"), NULL
, addressbook_new_group_cb
, 0, NULL
},
483 {"/---", NULL
, NULL
, 0, "<Separator>"},
484 {N_("/C_ut"), NULL
, addressbook_clip_cut_cb
, 0, NULL
},
485 {N_("/_Copy"), NULL
, addressbook_clip_copy_cb
, 0, NULL
},
486 {N_("/_Paste"), NULL
, addressbook_clip_paste_cb
, 0, NULL
},
487 {"/---", NULL
, NULL
, 0, "<Separator>"},
488 /* {N_("/Pa_ste Address"), NULL, addressbook_clip_paste_address_cb, 0, NULL},*/
489 {N_("/_Mail To"), NULL
, addressbook_mail_to_cb
, 0, NULL
},
491 {N_("/_Browse Entry"), NULL
, addressbook_browse_entry_cb
, 0, NULL
},
496 * Structure of error message table.
498 typedef struct _ErrMsgTableEntry ErrMsgTableEntry
;
499 struct _ErrMsgTableEntry
{
504 static gchar
*_errMsgUnknown_
= N_( "Unknown" );
507 * Lookup table of error messages for general errors. Note that a NULL
508 * description signifies the end of the table.
510 static ErrMsgTableEntry _lutErrorsGeneral_
[] = {
511 { MGU_SUCCESS
, N_("Success") },
512 { MGU_BAD_ARGS
, N_("Bad arguments") },
513 { MGU_NO_FILE
, N_("File not specified") },
514 { MGU_OPEN_FILE
, N_("Error opening file") },
515 { MGU_ERROR_READ
, N_("Error reading file") },
516 { MGU_EOF
, N_("End of file encountered") },
517 { MGU_OO_MEMORY
, N_("Error allocating memory") },
518 { MGU_BAD_FORMAT
, N_("Bad file format") },
519 { MGU_ERROR_WRITE
, N_("Error writing to file") },
520 { MGU_OPEN_DIRECTORY
, N_("Error opening directory") },
521 { MGU_NO_PATH
, N_("No path specified") },
527 * Lookup table of error messages for LDAP errors.
529 static ErrMsgTableEntry _lutErrorsLDAP_
[] = {
530 { LDAPRC_SUCCESS
, N_("Success") },
531 { LDAPRC_CONNECT
, N_("Error connecting to LDAP server") },
532 { LDAPRC_INIT
, N_("Error initializing LDAP") },
533 { LDAPRC_BIND
, N_("Error binding to LDAP server") },
534 { LDAPRC_SEARCH
, N_("Error searching LDAP database") },
535 { LDAPRC_TIMEOUT
, N_("Timeout performing LDAP operation") },
536 { LDAPRC_CRITERIA
, N_("Error in LDAP search criteria") },
537 { LDAPRC_NOENTRIES
, N_("No LDAP entries found for search criteria") },
538 { LDAPRC_STOP_FLAG
, N_("LDAP search terminated on request") },
539 { LDAPRC_TLS
, N_("Error starting TLS connection") },
545 * Lookup message for specified error code.
546 * \param lut Lookup table.
547 * \param code Code to lookup.
548 * \return Description associated to code.
550 static gchar
*addressbook_err2string( ErrMsgTableEntry lut
[], gint code
) {
552 ErrMsgTableEntry entry
;
555 for( i
= 0; ; i
++ ) {
557 if( entry
.description
== NULL
) break;
558 if( entry
.code
== code
) {
559 desc
= entry
.description
;
564 desc
= _errMsgUnknown_
;
569 static gboolean lastCanLookup
= FALSE
;
571 void addressbook_show_buttons(gboolean add_and_delete
, gboolean lookup
, gboolean mail_ops
)
573 if (add_and_delete
) {
574 gtk_widget_show(addrbook
.edit_btn
);
575 gtk_widget_show(addrbook
.del_btn
);
576 gtk_widget_show(addrbook
.reg_btn
);
578 gtk_widget_hide(addrbook
.edit_btn
);
579 gtk_widget_hide(addrbook
.del_btn
);
580 gtk_widget_hide(addrbook
.reg_btn
);
584 gtk_widget_show(addrbook
.lup_btn
);
585 gtk_widget_show(addrbook
.entry
);
586 gtk_widget_show(addrbook
.label
);
588 gtk_widget_hide(addrbook
.lup_btn
);
589 gtk_widget_hide(addrbook
.entry
);
590 gtk_widget_hide(addrbook
.label
);
593 lastCanLookup
= lookup
;
596 gtk_widget_show(addrbook
.to_btn
);
597 gtk_widget_show(addrbook
.cc_btn
);
598 gtk_widget_show(addrbook
.bcc_btn
);
600 gtk_widget_hide(addrbook
.to_btn
);
601 gtk_widget_hide(addrbook
.cc_btn
);
602 gtk_widget_hide(addrbook
.bcc_btn
);
606 void addressbook_open(Compose
*target
)
608 /* Initialize all static members */
609 if( _clipBoard_
== NULL
) {
610 _clipBoard_
= addrclip_create();
612 if( _addressIndex_
!= NULL
) {
613 addrclip_set_index( _clipBoard_
, _addressIndex_
);
615 if( _addressSelect_
== NULL
) {
616 _addressSelect_
= addrselect_list_create();
618 if (!addrbook
.window
) {
619 addressbook_read_file();
620 addressbook_create();
621 addressbook_load_tree();
622 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
),
623 GTK_CTREE_NODE(GTK_CLIST(addrbook
.ctree
)->row_list
));
626 gtk_widget_hide(addrbook
.window
);
629 gtk_widget_show_all(addrbook
.window
);
630 if (!prefs_common
.addressbook_use_editaddress_dialog
)
631 addressbook_edit_person_widgetset_hide();
633 address_completion_start(addrbook
.window
);
635 addressbook_show_buttons(target
== NULL
, lastCanLookup
, target
!= NULL
);
636 addressbook_set_target_compose(target
);
640 * Destroy addressbook.
642 void addressbook_destroy( void ) {
643 /* Free up address stuff */
644 if( _addressSelect_
!= NULL
) {
645 addrselect_list_free( _addressSelect_
);
647 if( _clipBoard_
!= NULL
) {
648 addrclip_free( _clipBoard_
);
650 if( _addressIndex_
!= NULL
) {
651 addrindex_free_index( _addressIndex_
);
652 addrindex_teardown();
654 _addressSelect_
= NULL
;
656 _addressIndex_
= NULL
;
659 void addressbook_set_target_compose(Compose
*target
)
661 addrbook
.target_compose
= target
;
662 addressbook_button_set_sensitive();
665 Compose
*addressbook_get_target_compose(void)
667 return addrbook
.target_compose
;
671 * Refresh addressbook and save to file(s).
673 void addressbook_refresh( void )
675 if (addrbook
.window
) {
676 if (addrbook
.treeSelected
) {
677 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
),
678 addrbook
.treeSelected
);
679 addressbook_set_clist(
680 gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
),
681 addrbook
.treeSelected
),
686 addressbook_export_to_file();
689 static gboolean
key_pressed(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
691 if (event
&& event
->keyval
== GDK_Escape
)
693 else if (event
&& event
->keyval
== GDK_Delete
) {
694 /* TODO: enable deletion when focus is in ctree (needs implementation in _del_clicked() */
695 if ( /* address_index_has_focus || */ address_list_has_focus
)
696 addressbook_del_clicked(NULL
, NULL
);
702 *\brief Save Gtk object size to prefs dataset
704 static void addressbook_size_allocate_cb(GtkWidget
*widget
,
705 GtkAllocation
*allocation
)
707 g_return_if_fail(allocation
!= NULL
);
709 prefs_common
.addressbookwin_width
= allocation
->width
;
710 prefs_common
.addressbookwin_height
= allocation
->height
;
713 static gint sort_column_number
= 0;
714 static GtkSortType sort_column_type
= GTK_SORT_ASCENDING
;
716 static gint
list_case_sort(
717 GtkCList
*clist
, gconstpointer ptr1
, gconstpointer ptr2
)
719 GtkCListRow
*row1
= (GtkCListRow
*) ptr1
;
720 GtkCListRow
*row2
= (GtkCListRow
*) ptr2
;
721 gchar
*name1
= NULL
, *name2
= NULL
;
722 AddrItemObject
*aio1
= ((GtkCListRow
*)ptr1
)->data
;
723 AddrItemObject
*aio2
= ((GtkCListRow
*)ptr2
)->data
;
725 if( aio1
->type
== aio2
->type
) {
727 name1
= GTK_CELL_TEXT (row1
->cell
[sort_column_number
])->text
;
729 name2
= GTK_CELL_TEXT (row2
->cell
[sort_column_number
])->text
;
730 if( ! name1
) return ( name2
!= NULL
);
731 if( ! name2
) return -1;
732 return strcasecmp( name1
, name2
);
734 /* Order groups before person */
735 if( aio1
->type
== ITEMTYPE_GROUP
) {
736 return (sort_column_type
==GTK_SORT_ASCENDING
) ? -1:+1;
737 } else if( aio2
->type
== ITEMTYPE_GROUP
) {
738 return (sort_column_type
==GTK_SORT_ASCENDING
) ? +1:-1;
744 static void addressbook_sort_list(GtkCList
*clist
, const gint col
,
745 const GtkSortType sort_type
)
748 GtkWidget
*hbox
, *label
, *arrow
;
750 sort_column_number
= col
;
751 sort_column_type
= sort_type
;
752 gtk_clist_set_compare_func(clist
, list_case_sort
);
753 gtk_clist_set_sort_type(clist
, sort_type
);
754 gtk_clist_set_sort_column(clist
, col
);
756 gtk_clist_freeze(clist
);
757 gtk_clist_sort(clist
);
759 for(pos
= 0 ; pos
< N_LIST_COLS
; pos
++) {
760 hbox
= gtk_hbox_new(FALSE
, 4);
761 label
= gtk_label_new(gettext(list_titles
[pos
]));
762 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
765 arrow
= gtk_arrow_new(sort_type
== GTK_SORT_ASCENDING
?
766 GTK_ARROW_DOWN
: GTK_ARROW_UP
, GTK_SHADOW_IN
);
767 gtk_box_pack_end(GTK_BOX(hbox
), arrow
, FALSE
, FALSE
, 0);
770 gtk_widget_show_all(hbox
);
771 gtk_clist_set_column_widget(clist
, pos
, hbox
);
774 gtk_clist_thaw(clist
);
777 static void addressbook_name_clicked(GtkWidget
*button
, GtkCList
*clist
)
779 static GtkSortType sort_type
= GTK_SORT_ASCENDING
;
781 sort_type
= (sort_type
== GTK_SORT_ASCENDING
) ? GTK_SORT_DESCENDING
:
783 addressbook_sort_list(clist
, COL_NAME
, sort_type
);
786 static void addressbook_address_clicked(GtkWidget
*button
, GtkCList
*clist
)
788 static GtkSortType sort_type
= GTK_SORT_ASCENDING
;
790 sort_type
= (sort_type
== GTK_SORT_ASCENDING
) ? GTK_SORT_DESCENDING
:
792 addressbook_sort_list(clist
, COL_ADDRESS
, sort_type
);
795 static void addressbook_remarks_clicked(GtkWidget
*button
, GtkCList
*clist
)
797 static GtkSortType sort_type
= GTK_SORT_ASCENDING
;
799 sort_type
= (sort_type
== GTK_SORT_ASCENDING
) ? GTK_SORT_DESCENDING
:
801 addressbook_sort_list(clist
, COL_REMARKS
, sort_type
);
804 static void addressbook_address_index_focus_evt_in(GtkWidget
*widget
, GdkEventFocus
*event
,
807 address_index_has_focus
= TRUE
;
810 static void addressbook_address_index_focus_evt_out(GtkWidget
*widget
, GdkEventFocus
*event
,
813 address_index_has_focus
= FALSE
;
816 static void addressbook_address_list_focus_evt_in(GtkWidget
*widget
, GdkEventFocus
*event
,
819 address_list_has_focus
= TRUE
;
822 static void addressbook_address_list_focus_evt_out(GtkWidget
*widget
, GdkEventFocus
*event
,
825 address_list_has_focus
= FALSE
;
829 * Create the address book widgets. The address book contains two CTree widgets: the
830 * address index tree on the left and the address list on the right.
832 * The address index tree displays a hierarchy of interfaces and groups. Each node in
833 * this tree is linked to an address Adapter. Adapters have been created for interfaces,
834 * data sources and folder objects.
836 * The address list displays group, person and email objects. These items are linked
837 * directly to ItemGroup, ItemPerson and ItemEMail objects inside the address book data
840 * In the tradition of MVC architecture, the data stores have been separated from the
841 * GUI components. The addrindex.c file provides the interface to all data stores.
843 static void addressbook_create(void)
849 GtkWidget
*ctree_swin
;
851 GtkWidget
*editaddress_vbox
;
852 GtkWidget
*clist_vbox
;
853 GtkWidget
*clist_swin
;
860 GtkWidget
*statusbar
;
871 GtkWidget
*close_btn
;
872 GtkWidget
*tree_popup
;
873 GtkWidget
*list_popup
;
874 GtkItemFactory
*tree_factory
;
875 GtkItemFactory
*list_factory
;
876 GtkItemFactory
*menu_factory
;
880 gchar
*index_titles
[N_INDEX_COLS
];
884 static GdkGeometry geometry
;
886 debug_print("Creating addressbook window...\n");
888 index_titles
[COL_SOURCES
] = _("Sources");
890 /* Address book window */
891 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
892 gtk_window_set_title(GTK_WINDOW(window
), _("Address book"));
893 gtk_window_set_resizable(GTK_WINDOW(window
), TRUE
);
894 gtk_widget_realize(window
);
896 g_signal_connect(G_OBJECT(window
), "delete_event",
897 G_CALLBACK(addressbook_close
), NULL
);
898 g_signal_connect(G_OBJECT(window
), "size_allocate",
899 G_CALLBACK(addressbook_size_allocate_cb
), NULL
);
900 g_signal_connect(G_OBJECT(window
), "key_press_event",
901 G_CALLBACK(key_pressed
), NULL
);
902 MANAGE_WINDOW_SIGNALS_CONNECT(window
);
904 vbox
= gtk_vbox_new(FALSE
, 0);
905 gtk_container_add(GTK_CONTAINER(window
), vbox
);
908 n_entries
= sizeof(addressbook_entries
) /
909 sizeof(addressbook_entries
[0]);
910 menubar
= menubar_create(window
, addressbook_entries
, n_entries
,
911 "<AddressBook>", NULL
);
912 gtk_box_pack_start(GTK_BOX(vbox
), menubar
, FALSE
, TRUE
, 0);
913 menu_factory
= gtk_item_factory_from_widget(menubar
);
915 vbox2
= gtk_vbox_new(FALSE
, BORDER_WIDTH
);
916 gtk_container_set_border_width(GTK_CONTAINER(vbox2
), BORDER_WIDTH
);
917 gtk_box_pack_start(GTK_BOX(vbox
), vbox2
, TRUE
, TRUE
, 0);
919 ctree_swin
= gtk_scrolled_window_new(NULL
, NULL
);
920 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ctree_swin
),
921 GTK_POLICY_AUTOMATIC
,
922 GTK_POLICY_AUTOMATIC
);
923 gtk_widget_set_size_request(ctree_swin
, COL_FOLDER_WIDTH
+ 20, -1);
926 ctree
= gtk_sctree_new_with_titles(N_INDEX_COLS
, 0, index_titles
);
927 gtk_container_add(GTK_CONTAINER(ctree_swin
), ctree
);
928 gtk_clist_set_selection_mode(GTK_CLIST(ctree
), GTK_SELECTION_BROWSE
);
929 gtk_clist_set_column_width(GTK_CLIST(ctree
), 0, COL_FOLDER_WIDTH
);
930 gtk_ctree_set_line_style(GTK_CTREE(ctree
), GTK_CTREE_LINES_DOTTED
);
931 gtk_ctree_set_expander_style(GTK_CTREE(ctree
),
932 GTK_CTREE_EXPANDER_SQUARE
);
933 gtk_ctree_set_indent(GTK_CTREE(ctree
), CTREE_INDENT
);
934 gtk_clist_set_compare_func(GTK_CLIST(ctree
),
935 addressbook_treenode_compare_func
);
937 g_signal_connect(G_OBJECT(ctree
), "tree_select_row",
938 G_CALLBACK(addressbook_tree_selected
), NULL
);
939 g_signal_connect(G_OBJECT(ctree
), "button_press_event",
940 G_CALLBACK(addressbook_tree_button_pressed
),
942 g_signal_connect(G_OBJECT(ctree
), "button_release_event",
943 G_CALLBACK(addressbook_tree_button_released
),
946 g_signal_connect(G_OBJECT(ctree
), "select_row",
947 G_CALLBACK(addressbook_select_row_tree
), NULL
);
949 gtk_drag_dest_set(ctree
, GTK_DEST_DEFAULT_ALL
& ~GTK_DEST_DEFAULT_HIGHLIGHT
,
950 addressbook_drag_types
, 1,
951 GDK_ACTION_MOVE
| GDK_ACTION_COPY
| GDK_ACTION_DEFAULT
);
952 g_signal_connect(G_OBJECT(ctree
), "drag_motion",
953 G_CALLBACK(addressbook_drag_motion_cb
),
955 g_signal_connect(G_OBJECT(ctree
), "drag_leave",
956 G_CALLBACK(addressbook_drag_leave_cb
),
958 g_signal_connect(G_OBJECT(ctree
), "drag_data_received",
959 G_CALLBACK(addressbook_drag_received_cb
),
961 g_signal_connect(G_OBJECT(ctree
), "focus_in_event",
962 G_CALLBACK(addressbook_address_index_focus_evt_in
), NULL
);
963 g_signal_connect(G_OBJECT(ctree
), "focus_out_event",
964 G_CALLBACK(addressbook_address_index_focus_evt_out
), NULL
);
966 clist_vbox
= gtk_vbox_new(FALSE
, 4);
968 clist_swin
= gtk_scrolled_window_new(NULL
, NULL
);
969 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin
),
970 GTK_POLICY_AUTOMATIC
,
971 GTK_POLICY_AUTOMATIC
);
972 gtk_box_pack_start(GTK_BOX(clist_vbox
), clist_swin
, TRUE
, TRUE
, 0);
975 clist
= gtk_sctree_new_with_titles(N_LIST_COLS
, 0, list_titles
);
976 gtk_container_add(GTK_CONTAINER(clist_swin
), clist
);
977 gtk_clist_set_selection_mode(GTK_CLIST(clist
), GTK_SELECTION_EXTENDED
);
978 gtk_ctree_set_line_style(GTK_CTREE(clist
), GTK_CTREE_LINES_NONE
);
979 gtk_ctree_set_expander_style(GTK_CTREE(clist
), GTK_CTREE_EXPANDER_SQUARE
);
980 gtk_ctree_set_indent(GTK_CTREE(clist
), CTREE_INDENT
);
981 gtk_clist_set_column_width(GTK_CLIST(clist
), COL_NAME
,
983 gtk_clist_set_column_width(GTK_CLIST(clist
), COL_ADDRESS
,
985 gtk_widget_set_size_request(clist
, -1, 80);
987 addressbook_sort_list(GTK_CLIST(clist
), COL_NAME
, GTK_SORT_ASCENDING
);
988 g_signal_connect(G_OBJECT(GTK_CLIST(clist
)->column
[COL_NAME
].button
),
989 "clicked", G_CALLBACK(addressbook_name_clicked
), clist
);
990 g_signal_connect(G_OBJECT(GTK_CLIST(clist
)->column
[COL_ADDRESS
].button
),
991 "clicked", G_CALLBACK(addressbook_address_clicked
), clist
);
992 g_signal_connect(G_OBJECT(GTK_CLIST(clist
)->column
[COL_REMARKS
].button
),
993 "clicked", G_CALLBACK(addressbook_remarks_clicked
), clist
);
994 g_signal_connect(G_OBJECT(clist
), "focus_in_event",
995 G_CALLBACK(addressbook_address_list_focus_evt_in
), NULL
);
996 g_signal_connect(G_OBJECT(clist
), "focus_out_event",
997 G_CALLBACK(addressbook_address_list_focus_evt_out
), NULL
);
999 for (i
= 0; i
< N_LIST_COLS
; i
++)
1000 GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist
)->column
[i
].button
,
1003 g_signal_connect(G_OBJECT(clist
), "tree_select_row",
1004 G_CALLBACK(addressbook_list_row_selected
), NULL
);
1005 g_signal_connect(G_OBJECT(clist
), "tree_unselect_row",
1006 G_CALLBACK(addressbook_list_row_unselected
), NULL
);
1007 g_signal_connect(G_OBJECT(clist
), "button_press_event",
1008 G_CALLBACK(addressbook_list_button_pressed
),
1010 g_signal_connect(G_OBJECT(clist
), "button_release_event",
1011 G_CALLBACK(addressbook_list_button_released
),
1013 g_signal_connect(G_OBJECT(clist
), "tree_expand",
1014 G_CALLBACK(addressbook_person_expand_node
), NULL
);
1015 g_signal_connect(G_OBJECT(clist
), "tree_collapse",
1016 G_CALLBACK(addressbook_person_collapse_node
), NULL
);
1017 g_signal_connect(G_OBJECT(clist
), "start_drag",
1018 G_CALLBACK(addressbook_start_drag
), NULL
);
1019 g_signal_connect(G_OBJECT(clist
), "drag_data_get",
1020 G_CALLBACK(addressbook_drag_data_get
), NULL
);
1021 hbox
= gtk_hbox_new(FALSE
, 4);
1022 gtk_box_pack_start(GTK_BOX(clist_vbox
), hbox
, FALSE
, FALSE
, 0);
1024 label
= gtk_label_new(_("Lookup name:"));
1025 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
1027 entry
= gtk_entry_new();
1028 gtk_box_pack_start(GTK_BOX(hbox
), entry
, TRUE
, TRUE
, 0);
1030 address_completion_register_entry(GTK_ENTRY(entry
), FALSE
);
1032 g_signal_connect(G_OBJECT(entry
), "key_press_event",
1033 G_CALLBACK(addressbook_entry_key_pressed
),
1036 if (!prefs_common
.addressbook_use_editaddress_dialog
) {
1037 editaddress_vbox
= gtk_vbox_new(FALSE
, 4);
1038 vpaned
= gtk_vpaned_new();
1039 gtk_paned_pack1(GTK_PANED(vpaned
), clist_vbox
, FALSE
, FALSE
);
1040 gtk_paned_pack2(GTK_PANED(vpaned
), editaddress_vbox
, TRUE
, FALSE
);
1043 editaddress_vbox
= NULL
;
1045 hpaned
= gtk_hpaned_new();
1046 gtk_box_pack_start(GTK_BOX(vbox2
), hpaned
, TRUE
, TRUE
, 0);
1047 gtk_paned_pack1(GTK_PANED(hpaned
), ctree_swin
, FALSE
, FALSE
);
1048 if (prefs_common
.addressbook_use_editaddress_dialog
)
1049 gtk_paned_pack2(GTK_PANED(hpaned
), clist_vbox
, TRUE
, FALSE
);
1051 gtk_paned_pack2(GTK_PANED(hpaned
), vpaned
, TRUE
, FALSE
);
1054 hsbox
= gtk_hbox_new(FALSE
, 0);
1055 gtk_box_pack_end(GTK_BOX(vbox
), hsbox
, FALSE
, FALSE
, BORDER_WIDTH
);
1056 statusbar
= gtk_statusbar_new();
1057 gtk_box_pack_start(GTK_BOX(hsbox
), statusbar
, TRUE
, TRUE
, BORDER_WIDTH
);
1060 hbbox
= gtk_hbutton_box_new();
1061 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox
), GTK_BUTTONBOX_END
);
1062 gtk_box_set_spacing(GTK_BOX(hbbox
), 2);
1063 gtk_container_set_border_width(GTK_CONTAINER(hbbox
), 4);
1064 gtk_box_pack_end(GTK_BOX(vbox
), hbbox
, FALSE
, FALSE
, 0);
1066 gtkut_stock_button_add_help(hbbox
, &help_btn
);
1068 edit_btn
= gtk_button_new_from_stock(GTK_STOCK_EDIT
);
1069 GTK_WIDGET_SET_FLAGS(edit_btn
, GTK_CAN_DEFAULT
);
1070 gtk_box_pack_start(GTK_BOX(hbbox
), edit_btn
, TRUE
, TRUE
, 0);
1071 del_btn
= gtk_button_new_from_stock(GTK_STOCK_DELETE
);
1072 GTK_WIDGET_SET_FLAGS(del_btn
, GTK_CAN_DEFAULT
);
1073 gtk_box_pack_start(GTK_BOX(hbbox
), del_btn
, TRUE
, TRUE
, 0);
1074 reg_btn
= gtk_button_new_from_stock(GTK_STOCK_NEW
);
1075 GTK_WIDGET_SET_FLAGS(reg_btn
, GTK_CAN_DEFAULT
);
1076 gtk_box_pack_start(GTK_BOX(hbbox
), reg_btn
, TRUE
, TRUE
, 0);
1079 lup_btn
= gtk_button_new_from_stock(GTK_STOCK_FIND
);
1080 GTK_WIDGET_SET_FLAGS(lup_btn
, GTK_CAN_DEFAULT
);
1081 gtk_box_pack_start(GTK_BOX(hbox
), lup_btn
, TRUE
, TRUE
, 0);
1083 g_signal_connect(G_OBJECT(help_btn
), "clicked",
1084 G_CALLBACK(manual_open_with_anchor_cb
),
1085 MANUAL_ANCHOR_ADDRBOOK
);
1087 g_signal_connect(G_OBJECT(edit_btn
), "clicked",
1088 G_CALLBACK(addressbook_edit_clicked
), NULL
);
1089 g_signal_connect(G_OBJECT(del_btn
), "clicked",
1090 G_CALLBACK(addressbook_del_clicked
), NULL
);
1091 g_signal_connect(G_OBJECT(reg_btn
), "clicked",
1092 G_CALLBACK(addressbook_reg_clicked
), NULL
);
1093 g_signal_connect(G_OBJECT(lup_btn
), "clicked",
1094 G_CALLBACK(addressbook_lup_clicked
), NULL
);
1096 to_btn
= gtk_button_new_with_label
1097 (prefs_common
.trans_hdr
? _("To:") : "To:");
1098 GTK_WIDGET_SET_FLAGS(to_btn
, GTK_CAN_DEFAULT
);
1099 gtk_box_pack_start(GTK_BOX(hbbox
), to_btn
, TRUE
, TRUE
, 0);
1100 cc_btn
= gtk_button_new_with_label
1101 (prefs_common
.trans_hdr
? _("Cc:") : "Cc:");
1102 GTK_WIDGET_SET_FLAGS(cc_btn
, GTK_CAN_DEFAULT
);
1103 gtk_box_pack_start(GTK_BOX(hbbox
), cc_btn
, TRUE
, TRUE
, 0);
1104 bcc_btn
= gtk_button_new_with_label
1105 (prefs_common
.trans_hdr
? _("Bcc:") : "Bcc:");
1106 GTK_WIDGET_SET_FLAGS(bcc_btn
, GTK_CAN_DEFAULT
);
1107 gtk_box_pack_start(GTK_BOX(hbbox
), bcc_btn
, TRUE
, TRUE
, 0);
1109 close_btn
= gtk_button_new_from_stock(GTK_STOCK_CLOSE
);
1110 GTK_WIDGET_SET_FLAGS(close_btn
, GTK_CAN_DEFAULT
);
1111 gtk_box_pack_start(GTK_BOX(hbbox
), close_btn
, TRUE
, TRUE
, 0);
1113 g_signal_connect(G_OBJECT(to_btn
), "clicked",
1114 G_CALLBACK(addressbook_to_clicked
),
1115 GINT_TO_POINTER(COMPOSE_TO
));
1116 g_signal_connect(G_OBJECT(cc_btn
), "clicked",
1117 G_CALLBACK(addressbook_to_clicked
),
1118 GINT_TO_POINTER(COMPOSE_CC
));
1119 g_signal_connect(G_OBJECT(bcc_btn
), "clicked",
1120 G_CALLBACK(addressbook_to_clicked
),
1121 GINT_TO_POINTER(COMPOSE_BCC
));
1122 g_signal_connect(G_OBJECT(close_btn
), "clicked",
1123 G_CALLBACK(addressbook_close_clicked
), NULL
);
1125 /* Build icons for interface */
1126 stock_pixmap_gdk( window
, STOCK_PIXMAP_INTERFACE
,
1127 &interfacexpm
, &interfacexpmmask
);
1129 /* Build control tables */
1130 addrbookctl_build_map(window
);
1131 addrbookctl_build_iflist();
1132 addrbookctl_build_ifselect();
1134 addrbook
.clist
= NULL
;
1136 /* Add each interface into the tree as a root level folder */
1137 nodeIf
= _addressInterfaceList_
;
1139 AdapterInterface
*adapter
= nodeIf
->data
;
1140 AddressInterface
*iface
= adapter
->interface
;
1141 nodeIf
= g_list_next(nodeIf
);
1143 if(iface
->useInterface
) {
1144 AddressTypeControlItem
*atci
= adapter
->atci
;
1145 text
= atci
->displayName
;
1147 gtk_sctree_insert_node( GTK_CTREE(ctree
),
1148 NULL
, NULL
, &text
, FOLDER_SPACING
,
1149 interfacexpm
, interfacexpmmask
,
1150 interfacexpm
, interfacexpmmask
,
1152 menu_set_sensitive( menu_factory
, atci
->menuCommand
, adapter
->haveLibrary
);
1153 gtk_ctree_node_set_row_data_full(
1154 GTK_CTREE(ctree
), adapter
->treeNode
, adapter
,
1155 addressbook_free_treenode
);
1160 n_entries
= sizeof(addressbook_tree_popup_entries
) /
1161 sizeof(addressbook_tree_popup_entries
[0]);
1162 tree_popup
= menu_create_items(addressbook_tree_popup_entries
,
1164 "<AddressBookTree>", &tree_factory
,
1166 n_entries
= sizeof(addressbook_list_popup_entries
) /
1167 sizeof(addressbook_list_popup_entries
[0]);
1168 list_popup
= menu_create_items(addressbook_list_popup_entries
,
1170 "<AddressBookList>", &list_factory
,
1173 addrbook
.window
= window
;
1174 addrbook
.menubar
= menubar
;
1175 addrbook
.ctree
= ctree
;
1178 addrbook
.editaddress_vbox
= editaddress_vbox
;
1179 addrbook
.clist
= clist
;
1180 addrbook
.label
= label
;
1181 addrbook
.entry
= entry
;
1182 addrbook
.statusbar
= statusbar
;
1183 addrbook
.status_cid
= gtk_statusbar_get_context_id(
1184 GTK_STATUSBAR(statusbar
), "Addressbook Window" );
1186 addrbook
.help_btn
= help_btn
;
1187 addrbook
.edit_btn
= edit_btn
;
1188 addrbook
.del_btn
= del_btn
;
1189 addrbook
.reg_btn
= reg_btn
;
1190 addrbook
.lup_btn
= lup_btn
;
1191 addrbook
.to_btn
= to_btn
;
1192 addrbook
.cc_btn
= cc_btn
;
1193 addrbook
.bcc_btn
= bcc_btn
;
1195 addrbook
.tree_popup
= tree_popup
;
1196 addrbook
.list_popup
= list_popup
;
1197 addrbook
.tree_factory
= tree_factory
;
1198 addrbook
.list_factory
= list_factory
;
1199 addrbook
.menu_factory
= menu_factory
;
1201 addrbook
.listSelected
= NULL
;
1203 if (!geometry
.min_height
) {
1204 geometry
.min_width
= ADDRESSBOOK_WIDTH
;
1205 geometry
.min_height
= ADDRESSBOOK_HEIGHT
;
1208 gtk_window_set_geometry_hints(GTK_WINDOW(window
), NULL
, &geometry
,
1210 gtk_widget_set_size_request(window
, prefs_common
.addressbookwin_width
,
1211 prefs_common
.addressbookwin_height
);
1213 gtk_widget_show_all(window
);
1217 * Close address book window and save to file(s).
1219 static gint
addressbook_close( void ) {
1220 address_completion_end(addrbook
.window
);
1221 if (!prefs_common
.addressbook_use_editaddress_dialog
)
1222 addressbook_edit_person_invalidate(NULL
, NULL
, NULL
);
1223 gtk_widget_hide(addrbook
.window
);
1224 addressbook_export_to_file();
1229 * Display message in status line.
1230 * \param msg Message to display.
1232 static void addressbook_status_show( gchar
*msg
) {
1233 if( addrbook
.statusbar
!= NULL
) {
1235 GTK_STATUSBAR(addrbook
.statusbar
),
1236 addrbook
.status_cid
);
1239 GTK_STATUSBAR(addrbook
.statusbar
),
1240 addrbook
.status_cid
, msg
);
1245 static void addressbook_ds_status_message( AddressDataSource
*ds
, gchar
*msg
) {
1246 *addressbook_msgbuf
= '\0';
1250 name
= addrindex_ds_get_name( ds
);
1251 g_snprintf( addressbook_msgbuf
, sizeof(addressbook_msgbuf
),
1252 "%s: %s", name
, msg
);
1255 g_snprintf( addressbook_msgbuf
, sizeof(addressbook_msgbuf
),
1258 addressbook_status_show( addressbook_msgbuf
);
1261 static void addressbook_ds_show_message( AddressDataSource
*ds
) {
1265 *addressbook_msgbuf
= '\0';
1267 name
= addrindex_ds_get_name( ds
);
1268 retVal
= addrindex_ds_get_status_code( ds
);
1269 if( retVal
== MGU_SUCCESS
) {
1270 g_snprintf( addressbook_msgbuf
,
1271 sizeof(addressbook_msgbuf
), "%s", name
);
1274 desc
= addressbook_err2string( _lutErrorsGeneral_
, retVal
);
1275 g_snprintf( addressbook_msgbuf
,
1276 sizeof(addressbook_msgbuf
), "%s: %s", name
, desc
);
1279 addressbook_status_show( addressbook_msgbuf
);
1282 static void addressbook_button_set_sensitive(void)
1284 gboolean to_sens
= FALSE
;
1285 gboolean cc_sens
= FALSE
;
1286 gboolean bcc_sens
= FALSE
;
1288 if (!addrbook
.window
) return;
1290 if (addrbook
.target_compose
) {
1294 if (addrbook
.target_compose
->use_bcc
)
1299 gtk_widget_set_sensitive(addrbook
.to_btn
, to_sens
);
1300 gtk_widget_set_sensitive(addrbook
.cc_btn
, cc_sens
);
1301 gtk_widget_set_sensitive(addrbook
.bcc_btn
, bcc_sens
);
1304 static void addressbook_edit_clicked(GtkButton
*button
, gpointer data
)
1306 addressbook_edit_address_cb(NULL
, 0, NULL
);
1310 * Delete one or more objects from address list.
1312 static void addressbook_del_clicked(GtkButton
*button
, gpointer data
)
1314 GtkCTree
*clist
= GTK_CTREE(addrbook
.clist
);
1315 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
1316 AddressObject
*pobj
;
1317 AdapterDSource
*ads
= NULL
;
1318 GtkCTreeNode
*nodeList
;
1321 AddressBookFile
*abf
= NULL
;
1322 AddressDataSource
*ds
= NULL
;
1323 AddressInterface
*iface
;
1324 AddrItemObject
*aio
;
1325 AddrSelectItem
*item
;
1327 gboolean refreshList
= FALSE
;
1329 pobj
= gtk_ctree_node_get_row_data(ctree
, addrbook
.opened
);
1330 g_return_if_fail(pobj
!= NULL
);
1332 /* Test whether anything selected for deletion */
1333 nodeList
= addrbook
.listSelected
;
1335 aio
= gtk_ctree_node_get_row_data( clist
, nodeList
);
1336 if( aio
== NULL
) return;
1337 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
1338 if( ds
== NULL
) return;
1340 /* Test for read only */
1341 iface
= ds
->interface
;
1342 if( iface
->readOnly
) {
1343 alertpanel( _("Delete address(es)"),
1344 _("This address data is readonly and cannot be deleted."),
1345 GTK_STOCK_CLOSE
, NULL
, NULL
);
1349 /* Test whether Ok to proceed */
1351 if( pobj
->type
== ADDR_DATASOURCE
) {
1352 ads
= ADAPTER_DSOURCE(pobj
);
1353 if( ads
->subType
== ADDR_BOOK
) procFlag
= TRUE
;
1355 else if( pobj
->type
== ADDR_ITEM_FOLDER
) {
1358 else if( pobj
->type
== ADDR_ITEM_GROUP
) {
1361 if( ! procFlag
) return;
1362 abf
= ds
->rawDataSource
;
1363 if( abf
== NULL
) return;
1366 /* Process deletions */
1367 if( pobj
->type
== ADDR_DATASOURCE
|| pobj
->type
== ADDR_ITEM_FOLDER
) {
1368 gboolean group_delete
= TRUE
;
1369 /* Items inside folders */
1370 list
= addrselect_get_list( _addressSelect_
);
1371 /* Confirm deletion */
1375 node
= g_list_next( node
);
1376 aio
= ( AddrItemObject
* ) item
->addressItem
;
1377 if( aio
->type
== ADDR_ITEM_PERSON
|| aio
->type
== ADDR_ITEM_EMAIL
) {
1378 group_delete
= FALSE
;
1383 aval
= alertpanel( _("Delete group"),
1384 _("Really delete the group(s)?\n"
1385 "The addresses it contains will not be lost."),
1386 GTK_STOCK_CANCEL
, "+"GTK_STOCK_DELETE
, NULL
);
1387 if( aval
!= G_ALERTALTERNATE
) return;
1389 aval
= alertpanel( _("Delete address(es)"),
1390 _("Really delete the address(es)?"),
1391 GTK_STOCK_CANCEL
, "+"GTK_STOCK_DELETE
, NULL
);
1392 if( aval
!= G_ALERTALTERNATE
) return;
1398 node
= g_list_next( node
);
1399 aio
= ( AddrItemObject
* ) item
->addressItem
;
1400 if( aio
->type
== ADDR_ITEM_GROUP
) {
1401 ItemGroup
*item
= ( ItemGroup
* ) aio
;
1402 GtkCTreeNode
*nd
= NULL
;
1404 nd
= addressbook_find_group_node( addrbook
.opened
, item
);
1405 item
= addrbook_remove_group( abf
, item
);
1407 addritem_free_item_group( item
);
1409 /* Remove group from parent node */
1410 gtk_ctree_remove_node( ctree
, nd
);
1413 else if( aio
->type
== ADDR_ITEM_PERSON
) {
1414 ItemPerson
*item
= ( ItemPerson
* ) aio
;
1415 addressbook_folder_remove_one_person( clist
, item
);
1416 if (pobj
->type
== ADDR_ITEM_FOLDER
)
1417 addritem_folder_remove_person(ADAPTER_FOLDER(pobj
)->itemFolder
, item
);
1418 item
= addrbook_remove_person( abf
, item
);
1420 addritem_free_item_person( item
);
1423 else if( aio
->type
== ADDR_ITEM_EMAIL
) {
1424 ItemEMail
*item
= ( ItemEMail
* ) aio
;
1425 ItemPerson
*person
= ( ItemPerson
* ) ADDRITEM_PARENT(item
);
1426 item
= addrbook_person_remove_email( abf
, person
, item
);
1428 addrcache_remove_email(abf
->addressCache
, item
);
1429 addritem_free_item_email( item
);
1431 addressbook_folder_refresh_one_person( clist
, person
);
1434 g_list_free( list
);
1435 addressbook_list_select_clear();
1437 gtk_sctree_select( GTK_SCTREE(ctree
), addrbook
.opened
);
1438 addressbook_set_clist(
1439 gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
),
1443 addrbook_set_dirty(abf
, TRUE
);
1444 addressbook_export_to_file();
1445 addressbook_list_menu_setup();
1448 else if( pobj
->type
== ADDR_ITEM_GROUP
) {
1449 /* Items inside groups */
1450 list
= addrselect_get_list( _addressSelect_
);
1454 node
= g_list_next( node
);
1455 aio
= ( AddrItemObject
* ) item
->addressItem
;
1456 if( aio
->type
== ADDR_ITEM_EMAIL
) {
1457 ItemEMail
*item
= ( ItemEMail
* ) aio
;
1458 ItemPerson
*person
= ( ItemPerson
* ) ADDRITEM_PARENT(item
);
1459 item
= addrbook_person_remove_email( abf
, person
, item
);
1461 addritem_free_item_email( item
);
1465 g_list_free( list
);
1466 addressbook_list_select_clear();
1467 gtk_sctree_select( GTK_SCTREE(ctree
), addrbook
.opened
);
1468 addressbook_set_clist(
1469 gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
),
1473 addrbook_set_dirty(abf
, TRUE
);
1474 addressbook_export_to_file();
1475 addressbook_list_menu_setup();
1479 gtk_ctree_node_set_row_data( clist
, nodeList
, NULL
);
1480 gtk_ctree_remove_node( clist
, nodeList
);
1484 static void addressbook_reg_clicked(GtkButton
*button
, gpointer data
)
1486 addressbook_new_address_cb( NULL
, 0, NULL
);
1489 gchar
*addressbook_format_address( AddrItemObject
* aio
) {
1492 gchar
*address
= NULL
;
1494 if( aio
->type
== ADDR_ITEM_EMAIL
) {
1495 ItemPerson
*person
= NULL
;
1496 ItemEMail
*email
= ( ItemEMail
* ) aio
;
1498 person
= ( ItemPerson
* ) ADDRITEM_PARENT(email
);
1499 if( email
->address
) {
1500 if( ADDRITEM_NAME(email
) ) {
1501 name
= ADDRITEM_NAME(email
);
1502 if( *name
== '\0' ) {
1503 name
= ADDRITEM_NAME(person
);
1506 else if( ADDRITEM_NAME(person
) ) {
1507 name
= ADDRITEM_NAME(person
);
1510 buf
= g_strdup( email
->address
);
1512 address
= email
->address
;
1515 else if( aio
->type
== ADDR_ITEM_PERSON
) {
1516 ItemPerson
*person
= ( ItemPerson
* ) aio
;
1517 GList
*node
= person
->listEMail
;
1519 name
= ADDRITEM_NAME(person
);
1521 ItemEMail
*email
= ( ItemEMail
* ) node
->data
;
1522 address
= email
->address
;
1526 if( name
&& name
[0] != '\0' ) {
1527 if( strchr_with_skip_quote( name
, '"', ',' ) )
1528 buf
= g_strdup_printf( "\"%s\" <%s>", name
, address
);
1530 buf
= g_strdup_printf( "%s <%s>", name
, address
);
1533 buf
= g_strdup( address
);
1540 static void addressbook_to_clicked(GtkButton
*button
, gpointer data
)
1544 AddrSelectItem
*item
;
1545 AddrItemObject
*aio
;
1548 compose
= addrbook
.target_compose
;
1549 if( ! compose
) return;
1551 /* Nothing selected, but maybe there is something in text entry */
1552 addr
= (char *)gtk_entry_get_text( GTK_ENTRY( addrbook
.entry
) );
1554 compose_entry_append(
1555 compose
, addr
, (ComposeEntryType
)data
);
1558 /* Select from address list */
1559 list
= addrselect_get_list( _addressSelect_
);
1564 node
= g_list_next( node
);
1565 aio
= item
->addressItem
;
1566 if( aio
->type
== ADDR_ITEM_PERSON
||
1567 aio
->type
== ADDR_ITEM_EMAIL
) {
1568 addr
= addressbook_format_address( aio
);
1569 compose_entry_append(
1570 compose
, addr
, (ComposeEntryType
) data
);
1573 else if( aio
->type
== ADDR_ITEM_GROUP
) {
1574 ItemGroup
*group
= ( ItemGroup
* ) aio
;
1575 GList
*nodeMail
= group
->listEMail
;
1577 ItemEMail
*email
= nodeMail
->data
;
1579 addr
= addressbook_format_address(
1580 ( AddrItemObject
* ) email
);
1581 compose_entry_append(
1582 compose
, addr
, (ComposeEntryType
) data
);
1584 nodeMail
= g_list_next( nodeMail
);
1589 AddressObject
*obj
= NULL
;
1591 obj
= gtk_ctree_node_get_row_data( GTK_CTREE(addrbook
.ctree
), addrbook
.treeSelected
);
1593 if( obj
&& obj
->type
== ADDR_ITEM_GROUP
) {
1594 ItemGroup
*itemGroup
= ADAPTER_GROUP(obj
)->itemGroup
;
1595 GList
*nodeMail
= itemGroup
->listEMail
;
1597 ItemEMail
*email
= nodeMail
->data
;
1599 addr
= addressbook_format_address(
1600 ( AddrItemObject
* ) email
);
1601 compose_entry_append(
1602 compose
, addr
, (ComposeEntryType
) data
);
1604 nodeMail
= g_list_next( nodeMail
);
1608 g_list_free( list
);
1611 static void addressbook_menubar_set_sensitive( gboolean sensitive
) {
1612 menu_set_sensitive( addrbook
.menu_factory
, "/Book/Edit book", sensitive
);
1613 menu_set_sensitive( addrbook
.menu_factory
, "/Book/Delete book", sensitive
);
1614 menu_set_sensitive( addrbook
.menu_factory
, "/Book/New Folder", sensitive
);
1616 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Select all", TRUE
);
1617 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Cut", sensitive
);
1618 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Copy", sensitive
);
1619 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Paste", sensitive
);
1621 menu_set_sensitive( addrbook
.menu_factory
, "/Address/New Address", sensitive
);
1622 menu_set_sensitive( addrbook
.menu_factory
, "/Address/New Group", sensitive
);
1623 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Mail To", sensitive
);
1624 gtk_widget_set_sensitive( addrbook
.reg_btn
, sensitive
);
1625 gtk_widget_set_sensitive( addrbook
.edit_btn
, sensitive
);
1626 gtk_widget_set_sensitive( addrbook
.del_btn
, sensitive
);
1629 static void addressbook_menuitem_set_sensitive( AddressObject
*obj
, GtkCTreeNode
*node
) {
1630 gboolean canEdit
= FALSE
;
1631 gboolean canDelete
= TRUE
;
1632 gboolean canAdd
= FALSE
;
1633 gboolean canEditTr
= TRUE
;
1634 gboolean editAddress
= FALSE
;
1635 gboolean canExport
= TRUE
;
1636 AddressTypeControlItem
*atci
= NULL
;
1637 AddressDataSource
*ds
= NULL
;
1638 AddressInterface
*iface
= NULL
;
1640 if( obj
== NULL
) return;
1641 if( obj
->type
== ADDR_INTERFACE
) {
1642 AdapterInterface
*adapter
= ADAPTER_INTERFACE(obj
);
1643 iface
= adapter
->interface
;
1645 if( iface
->haveLibrary
) {
1646 /* Enable appropriate File / New command */
1647 atci
= adapter
->atci
;
1648 menu_set_sensitive( addrbook
.menu_factory
, atci
->menuCommand
, TRUE
);
1651 canEditTr
= canExport
= FALSE
;
1653 else if( obj
->type
== ADDR_DATASOURCE
) {
1654 AdapterDSource
*ads
= ADAPTER_DSOURCE(obj
);
1655 ds
= ads
->dataSource
;
1656 iface
= ds
->interface
;
1657 if( ! iface
->readOnly
) {
1658 canAdd
= canEdit
= editAddress
= canDelete
= TRUE
;
1660 if( ! iface
->haveLibrary
) {
1661 canAdd
= canEdit
= editAddress
= canExport
= canDelete
= FALSE
;
1664 else if( obj
->type
== ADDR_ITEM_FOLDER
) {
1665 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
1667 iface
= ds
->interface
;
1668 if( iface
->readOnly
) {
1673 canAdd
= editAddress
= TRUE
;
1677 else if( obj
->type
== ADDR_ITEM_GROUP
) {
1678 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
1680 iface
= ds
->interface
;
1681 if( ! iface
->readOnly
) {
1687 if( addrbook
.listSelected
== NULL
) canEdit
= FALSE
;
1690 menu_set_sensitive( addrbook
.menu_factory
, "/Address/New Address", editAddress
);
1691 menu_set_sensitive( addrbook
.menu_factory
, "/Address/New Group", canAdd
);
1692 menu_set_sensitive( addrbook
.menu_factory
, "/Book/New Folder", canAdd
);
1693 gtk_widget_set_sensitive( addrbook
.reg_btn
, editAddress
);
1696 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Edit", canEdit
);
1697 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Delete", canDelete
);
1698 gtk_widget_set_sensitive( addrbook
.edit_btn
, canEdit
);
1699 gtk_widget_set_sensitive( addrbook
.del_btn
, canDelete
);
1701 menu_set_sensitive( addrbook
.menu_factory
, "/Book/Edit book", canEditTr
);
1702 menu_set_sensitive( addrbook
.menu_factory
, "/Book/Delete book", canEditTr
);
1705 menu_set_sensitive( addrbook
.menu_factory
, "/Tools/Export HTML...", canExport
);
1706 menu_set_sensitive( addrbook
.menu_factory
, "/Tools/Export LDIF...", canExport
);
1709 static void addressbook_list_menu_setup( void );
1712 * Address book tree callback function that responds to selection of tree
1715 * \param ctree Tree widget.
1716 * \param node Node that was selected.
1717 * \param column Column number where selected occurred.
1718 * \param data Pointer to user data.
1720 static void addressbook_tree_selected(GtkCTree
*ctree
, GtkCTreeNode
*node
,
1721 gint column
, gpointer data
)
1723 AddressObject
*obj
= NULL
;
1724 AdapterDSource
*ads
= NULL
;
1725 AddressDataSource
*ds
= NULL
;
1726 ItemFolder
*rootFolder
= NULL
;
1727 AddressObjectType aot
;
1729 addrbook
.treeSelected
= node
;
1730 addrbook
.listSelected
= NULL
;
1731 addressbook_status_show( "" );
1732 if( addrbook
.entry
!= NULL
) gtk_entry_set_text(GTK_ENTRY(addrbook
.entry
), "");
1734 if( node
) obj
= gtk_ctree_node_get_row_data( ctree
, node
);
1736 addressbook_set_clist(NULL
, TRUE
);
1739 addrbook
.opened
= node
;
1741 if( obj
->type
== ADDR_DATASOURCE
) {
1742 /* Read from file */
1743 static gboolean tVal
= TRUE
;
1745 ads
= ADAPTER_DSOURCE(obj
);
1746 if( ads
== NULL
) return;
1747 ds
= ads
->dataSource
;
1748 if( ds
== NULL
) return;
1750 if( addrindex_ds_get_modify_flag( ds
) ) {
1751 addrindex_ds_read_data( ds
);
1754 if( ! addrindex_ds_get_read_flag( ds
) ) {
1755 addrindex_ds_read_data( ds
);
1757 addressbook_ds_show_message( ds
);
1759 if( ! addrindex_ds_get_access_flag( ds
) ) {
1760 /* Remove existing folders and groups */
1761 gtk_clist_freeze( GTK_CLIST(ctree
) );
1762 addressbook_tree_remove_children( ctree
, node
);
1763 gtk_clist_thaw( GTK_CLIST(ctree
) );
1765 /* Load folders into the tree */
1766 rootFolder
= addrindex_ds_get_root_folder( ds
);
1767 if( ds
->type
== ADDR_IF_JPILOT
) {
1768 aot
= ADDR_CATEGORY
;
1770 else if( ds
->type
== ADDR_IF_LDAP
) {
1771 aot
= ADDR_LDAP_QUERY
;
1774 aot
= ADDR_ITEM_FOLDER
;
1776 addressbook_node_add_folder( node
, ds
, rootFolder
, aot
);
1777 addrindex_ds_set_access_flag( ds
, &tVal
);
1778 gtk_ctree_expand( ctree
, node
);
1781 addressbook_set_clist(NULL
, TRUE
);
1784 /* Update address list */
1785 g_signal_handlers_block_by_func
1787 G_CALLBACK(addressbook_tree_selected
), NULL
);
1788 addressbook_set_clist( obj
, FALSE
);
1789 g_signal_handlers_unblock_by_func
1791 G_CALLBACK(addressbook_tree_selected
), NULL
);
1792 if (!prefs_common
.addressbook_use_editaddress_dialog
)
1793 addressbook_edit_person_invalidate(NULL
, NULL
, NULL
);
1795 /* Setup main menu selections */
1796 addressbook_menubar_set_sensitive( FALSE
);
1797 addressbook_list_menu_setup();
1798 addressbook_menuitem_set_sensitive( obj
, node
);
1800 addressbook_list_select_clear();
1801 addressbook_list_menu_setup();
1806 * Setup address list popup menu items. Items are enabled or disabled as
1809 static void addressbook_list_menu_setup( void ) {
1810 GtkCTree
*clist
= NULL
;
1811 AddressObject
*pobj
= NULL
;
1812 AddressObject
*obj
= NULL
;
1813 AdapterDSource
*ads
= NULL
;
1814 AddressInterface
*iface
= NULL
;
1815 AddressDataSource
*ds
= NULL
;
1816 gboolean canEdit
= FALSE
;
1817 gboolean canDelete
= FALSE
;
1818 gboolean canCut
= FALSE
;
1819 gboolean canCopy
= FALSE
;
1820 gboolean canPaste
= FALSE
;
1821 gboolean canBrowse
= FALSE
;
1823 pobj
= gtk_ctree_node_get_row_data( GTK_CTREE(addrbook
.ctree
), addrbook
.treeSelected
);
1824 if( pobj
== NULL
) return;
1826 clist
= GTK_CTREE(addrbook
.clist
);
1827 obj
= gtk_ctree_node_get_row_data( clist
, addrbook
.listSelected
);
1828 if( obj
== NULL
) canEdit
= FALSE
;
1830 menu_set_insensitive_all( GTK_MENU_SHELL(addrbook
.list_popup
) );
1831 menu_set_sensitive( addrbook
.list_factory
, "/Select all", TRUE
);
1833 if( pobj
->type
== ADDR_DATASOURCE
) {
1834 /* Parent object is a data source */
1835 ads
= ADAPTER_DSOURCE(pobj
);
1836 ds
= ads
->dataSource
;
1837 iface
= ds
->interface
;
1838 if( ! iface
->readOnly
) {
1839 menu_set_sensitive( addrbook
.list_factory
, "/New Address", TRUE
);
1840 menu_set_sensitive( addrbook
.list_factory
, "/New Group", TRUE
);
1841 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
1842 if( ! addrclip_is_empty( _clipBoard_
) ) canPaste
= TRUE
;
1843 if( ! addrselect_test_empty( _addressSelect_
) ) canCut
= TRUE
;
1844 if( obj
) canEdit
= TRUE
;
1846 canDelete
= canEdit
;
1848 else if( pobj
->type
!= ADDR_INTERFACE
) {
1849 /* Parent object is not an interface */
1850 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
1851 iface
= ds
->interface
;
1852 if( ! iface
->readOnly
) {
1853 /* Folder or group */
1854 if( pobj
->type
== ADDR_ITEM_FOLDER
|| pobj
->type
== ADDR_ITEM_GROUP
) {
1855 menu_set_sensitive( addrbook
.list_factory
, "/New Address", TRUE
);
1856 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
1857 if( obj
) canEdit
= TRUE
;
1860 if( pobj
->type
== ADDR_ITEM_FOLDER
) {
1861 menu_set_sensitive( addrbook
.list_factory
, "/New Group", TRUE
);
1862 if( obj
) canEdit
= TRUE
;
1864 if( ! addrclip_is_empty( _clipBoard_
) ) canPaste
= TRUE
;
1865 if( ! addrselect_test_empty( _addressSelect_
) ) canCut
= TRUE
;
1866 canDelete
= canEdit
;
1868 if( iface
->type
== ADDR_IF_LDAP
) {
1869 if( obj
) canBrowse
= TRUE
;
1874 if( ! addrselect_test_empty( _addressSelect_
) ) canCopy
= TRUE
;
1876 /* Disable edit or browse if more than one row selected */
1877 if( GTK_CLIST(clist
)->selection
&& GTK_CLIST(clist
)->selection
->next
) {
1882 /* Now go finalize menu items */
1883 menu_set_sensitive( addrbook
.list_factory
, "/Edit", canEdit
);
1884 menu_set_sensitive( addrbook
.list_factory
, "/Delete", canDelete
);
1886 menu_set_sensitive( addrbook
.list_factory
, "/Cut", canCut
);
1887 menu_set_sensitive( addrbook
.list_factory
, "/Copy", canCopy
);
1888 menu_set_sensitive( addrbook
.list_factory
, "/Paste", canPaste
);
1889 /* menu_set_sensitive( addrbook.list_factory, "/Paste Address", canPaste );*/
1891 menu_set_sensitive( addrbook
.list_factory
, "/Mail To", canCopy
);
1893 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Cut", canCut
);
1894 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Copy", canCopy
);
1895 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Paste", canPaste
);
1896 /* menu_set_sensitive( addrbook.menu_factory, "/Edit/Paste Address", canPaste );*/
1898 menu_set_sensitive( addrbook
.tree_factory
, "/Cut", canCut
);
1899 menu_set_sensitive( addrbook
.tree_factory
, "/Copy", canCopy
);
1900 menu_set_sensitive( addrbook
.tree_factory
, "/Paste", canPaste
);
1902 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Edit", canEdit
);
1903 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Delete", canDelete
);
1904 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Mail To", canCopy
);
1906 gtk_widget_set_sensitive( addrbook
.edit_btn
, canEdit
);
1907 gtk_widget_set_sensitive( addrbook
.del_btn
, canDelete
);
1910 menu_set_sensitive( addrbook
.list_factory
, "/Browse Entry", canBrowse
);
1914 static void addressbook_select_row_tree (GtkCTree
*ctree
,
1922 * Add list of items into tree node below specified tree node.
1923 * \param treeNode Tree node.
1924 * \param ds Data source.
1925 * \param listItems List of items.
1927 static void addressbook_treenode_add_list(
1928 GtkCTreeNode
*treeNode
, AddressDataSource
*ds
, GList
*listItems
)
1934 AddrItemObject
*aio
;
1938 if( ADDRESS_OBJECT_TYPE(aio
) == ITEMTYPE_GROUP
) {
1941 group
= ( ItemGroup
* ) aio
;
1942 nn
= addressbook_node_add_group( treeNode
, ds
, group
);
1944 else if( ADDRESS_OBJECT_TYPE(aio
) == ITEMTYPE_FOLDER
) {
1947 folder
= ( ItemFolder
* ) aio
;
1948 nn
= addressbook_node_add_folder(
1949 treeNode
, ds
, folder
, ADDR_ITEM_FOLDER
);
1951 node
= g_list_next( node
);
1955 static void addressbook_select_all_cb( void ) {
1956 gtk_clist_select_all(GTK_CLIST(addrbook
.clist
));
1960 * Cut from address list widget.
1962 static void addressbook_clip_cut_cb( void ) {
1963 _clipBoard_
->cutFlag
= TRUE
;
1964 addrclip_clear( _clipBoard_
);
1965 addrclip_add( _clipBoard_
, _addressSelect_
);
1966 /* addrclip_list_show( _clipBoard_, stdout ); */
1970 * Copy from address list widget.
1972 static void addressbook_clip_copy_cb( void ) {
1973 _clipBoard_
->cutFlag
= FALSE
;
1974 addrclip_clear( _clipBoard_
);
1975 addrclip_add( _clipBoard_
, _addressSelect_
);
1976 /* addrclip_list_show( _clipBoard_, stdout ); */
1980 * Paste clipboard into address list widget.
1982 static void addressbook_clip_paste_cb( void ) {
1983 GtkCTree
*ctree
= GTK_CTREE( addrbook
.ctree
);
1984 AddressObject
*pobj
= NULL
;
1985 AddressDataSource
*ds
= NULL
;
1986 AddressBookFile
*abf
= NULL
;
1987 ItemFolder
*folder
= NULL
;
1988 GList
*folderGroup
= NULL
;
1990 ds
= addressbook_find_datasource( GTK_CTREE_NODE(addrbook
.treeSelected
) );
1991 if( ds
== NULL
) return;
1992 if( addrindex_ds_get_readonly( ds
) ) {
1993 addressbook_ds_status_message(
1994 ds
, _( "Cannot paste. Target address book is readonly." ) );
1998 pobj
= gtk_ctree_node_get_row_data( ctree
, addrbook
.treeSelected
);
2000 if( pobj
->type
== ADDR_ITEM_FOLDER
) {
2001 folder
= ADAPTER_FOLDER(pobj
)->itemFolder
;
2003 else if( pobj
->type
== ADDR_ITEM_GROUP
) {
2004 addressbook_ds_status_message(
2005 ds
, _( "Cannot paste into an address group." ) );
2010 /* Get an address book */
2011 abf
= addressbook_get_book_file();
2012 if( abf
== NULL
) return;
2014 if( _clipBoard_
->cutFlag
) {
2016 folderGroup
= addrclip_paste_cut( _clipBoard_
, abf
, folder
);
2018 /* Remove all groups and folders in clipboard from tree node */
2019 addressbook_treenode_remove_item();
2021 /* Remove all "cut" items */
2022 addrclip_delete_item( _clipBoard_
);
2024 /* Clear clipboard - cut items??? */
2025 addrclip_clear( _clipBoard_
);
2029 folderGroup
= addrclip_paste_copy( _clipBoard_
, abf
, folder
);
2032 /* addrclip_list_show( _clipBoard_, stdout ); */
2034 /* Update tree by inserting node for each folder or group */
2035 addressbook_treenode_add_list(
2036 addrbook
.treeSelected
, ds
, folderGroup
);
2037 gtk_ctree_expand( ctree
, addrbook
.treeSelected
);
2038 g_list_free( folderGroup
);
2042 /* Display items pasted */
2043 gtk_sctree_select( GTK_SCTREE(ctree
), addrbook
.opened
);
2044 addressbook_set_clist(
2045 gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
),
2053 * Add current treenode object to clipboard. Note that widget only allows
2054 * one entry from the tree list to be selected.
2056 static void addressbook_treenode_to_clipboard( void ) {
2057 AddressObject
*obj
= NULL
;
2058 AddressDataSource
*ds
= NULL
;
2059 AddrSelectItem
*item
;
2060 GtkCTree
*ctree
= GTK_CTREE( addrbook
.ctree
);
2063 node
= addrbook
.treeSelected
;
2064 if( node
== NULL
) return;
2065 obj
= gtk_ctree_node_get_row_data( ctree
, node
);
2066 if( obj
== NULL
) return;
2068 ds
= addressbook_find_datasource( node
);
2069 if( ds
== NULL
) return;
2072 if( obj
->type
== ADDR_ITEM_FOLDER
) {
2073 AdapterFolder
*adapter
= ADAPTER_FOLDER(obj
);
2074 ItemFolder
*folder
= adapter
->itemFolder
;
2076 item
= addrselect_create_node( obj
);
2077 item
->uid
= g_strdup( ADDRITEM_ID(folder
) );
2079 else if( obj
->type
== ADDR_ITEM_GROUP
) {
2080 AdapterGroup
*adapter
= ADAPTER_GROUP(obj
);
2081 ItemGroup
*group
= adapter
->itemGroup
;
2083 item
= addrselect_create_node( obj
);
2084 item
->uid
= g_strdup( ADDRITEM_ID(group
) );
2086 else if( obj
->type
== ADDR_DATASOURCE
) {
2088 item
= addrselect_create_node( obj
);
2093 /* Clear existing list and add item into list */
2096 addressbook_list_select_clear();
2097 cacheID
= addrindex_get_cache_id( _addressIndex_
, ds
);
2098 addrselect_list_add( _addressSelect_
, item
, cacheID
);
2104 * Cut from tree widget.
2106 static void addressbook_treenode_cut_cb( void ) {
2107 _clipBoard_
->cutFlag
= TRUE
;
2108 addressbook_treenode_to_clipboard();
2109 addrclip_clear( _clipBoard_
);
2110 addrclip_add( _clipBoard_
, _addressSelect_
);
2111 /* addrclip_list_show( _clipBoard_, stdout ); */
2115 * Copy from tree widget.
2117 static void addressbook_treenode_copy_cb( void ) {
2118 _clipBoard_
->cutFlag
= FALSE
;
2119 addressbook_treenode_to_clipboard();
2120 addrclip_clear( _clipBoard_
);
2121 addrclip_add( _clipBoard_
, _addressSelect_
);
2122 /* addrclip_list_show( _clipBoard_, stdout ); */
2126 * Paste clipboard into address tree widget.
2128 static void addressbook_treenode_paste_cb( void ) {
2129 addressbook_clip_paste_cb();
2133 * Clear selected entries in clipboard.
2135 static void addressbook_list_select_clear( void ) {
2136 addrselect_list_clear( _addressSelect_
);
2140 * Add specified address item to selected address list.
2141 * \param aio Address item object.
2142 * \param ds Datasource.
2144 static void addressbook_list_select_add( AddrItemObject
*aio
, AddressDataSource
*ds
) {
2147 if( ds
== NULL
) return;
2148 cacheID
= addrindex_get_cache_id( _addressIndex_
, ds
);
2149 addrselect_list_add_obj( _addressSelect_
, aio
, cacheID
);
2154 * Remove specified address item from selected address list.
2155 * \param aio Address item object.
2157 static void addressbook_list_select_remove( AddrItemObject
*aio
) {
2158 addrselect_list_remove( _addressSelect_
, aio
);
2162 * Invoke EMail compose window with addresses in selected address list.
2164 static void addressbook_mail_to_cb( void ) {
2167 if( ! addrselect_test_empty( _addressSelect_
) ) {
2168 listAddress
= addrselect_build_list( _addressSelect_
);
2169 compose_new_with_list( NULL
, listAddress
);
2170 mgu_free_dlist( listAddress
);
2175 static void addressbook_list_row_selected( GtkCTree
*clist
,
2180 GtkEntry
*entry
= GTK_ENTRY(addrbook
.entry
);
2181 AddrItemObject
*aio
= NULL
;
2182 AddressObject
*pobj
= NULL
;
2183 AdapterDSource
*ads
= NULL
;
2184 AddressDataSource
*ds
= NULL
;
2186 gtk_entry_set_text( entry
, "" );
2187 addrbook
.listSelected
= node
;
2189 pobj
= gtk_ctree_node_get_row_data( GTK_CTREE(addrbook
.ctree
), addrbook
.treeSelected
);
2190 if( pobj
== NULL
) return;
2192 if( pobj
->type
== ADDR_DATASOURCE
) {
2193 ads
= ADAPTER_DSOURCE(pobj
);
2194 ds
= ads
->dataSource
;
2196 else if( pobj
->type
!= ADDR_INTERFACE
) {
2197 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
2200 aio
= gtk_ctree_node_get_row_data( clist
, node
);
2202 /* printf( "list select: %d : '%s'\n", aio->type, aio->name ); */
2203 addressbook_list_select_add( aio
, ds
);
2206 addressbook_list_menu_setup();
2208 if (!addrbook
.target_compose
&& !prefs_common
.addressbook_use_editaddress_dialog
)
2209 addressbook_edit_address_cb(NULL
, 0, NULL
);
2212 static void addressbook_list_row_unselected( GtkCTree
*ctree
,
2217 AddrItemObject
*aio
;
2219 aio
= gtk_ctree_node_get_row_data( ctree
, node
);
2221 /* printf( "list unselect: %d : '%s'\n", aio->type, aio->name ); */
2222 addressbook_list_select_remove( aio
);
2225 if (!prefs_common
.addressbook_use_editaddress_dialog
)
2226 addressbook_edit_person_invalidate(NULL
, NULL
, NULL
);
2229 /* from gdkevents.c */
2230 #define DOUBLE_CLICK_TIME 250
2232 static gboolean
addressbook_list_button_pressed(GtkWidget
*widget
,
2233 GdkEventButton
*event
,
2236 static guint32 lasttime
= 0;
2237 if( ! event
) return FALSE
;
2239 addressbook_list_menu_setup();
2241 if( event
->button
== 3 ) {
2242 gtk_menu_popup( GTK_MENU(addrbook
.list_popup
), NULL
, NULL
, NULL
, NULL
,
2243 event
->button
, event
->time
);
2244 } else if (event
->button
== 1) {
2245 if (event
->time
- lasttime
< DOUBLE_CLICK_TIME
) {
2246 if (prefs_common
.add_address_by_click
&&
2247 addrbook
.target_compose
)
2248 addressbook_to_clicked(NULL
, GINT_TO_POINTER(COMPOSE_TO
));
2250 if (prefs_common
.addressbook_use_editaddress_dialog
)
2251 addressbook_edit_address_cb(NULL
, 0, NULL
);
2255 lasttime
= event
->time
;
2261 static gboolean
addressbook_list_button_released(GtkWidget
*widget
,
2262 GdkEventButton
*event
,
2268 static gboolean
addressbook_tree_button_pressed(GtkWidget
*ctree
,
2269 GdkEventButton
*event
,
2272 GtkCList
*clist
= GTK_CLIST(ctree
);
2274 AddressObject
*obj
= NULL
;
2275 AdapterDSource
*ads
= NULL
;
2276 AddressInterface
*iface
= NULL
;
2277 AddressDataSource
*ds
= NULL
;
2278 gboolean canEdit
= FALSE
;
2279 gboolean canDelete
= FALSE
;
2280 gboolean canCut
= FALSE
;
2281 gboolean canCopy
= FALSE
;
2282 gboolean canPaste
= FALSE
;
2283 gboolean canTreeCut
= FALSE
;
2284 gboolean canTreeCopy
= FALSE
;
2285 gboolean canTreePaste
= FALSE
;
2286 gboolean canLookup
= FALSE
;
2287 GtkCTreeNode
*node
= NULL
;
2289 if( ! event
) return FALSE
;
2290 addressbook_menubar_set_sensitive( FALSE
);
2292 if( gtk_clist_get_selection_info( clist
, event
->x
, event
->y
, &row
, &column
) ) {
2293 gtkut_clist_set_focus_row(clist
, row
);
2294 obj
= gtk_clist_get_row_data( clist
, row
);
2297 menu_set_insensitive_all(GTK_MENU_SHELL(addrbook
.tree_popup
));
2299 if( obj
== NULL
) return FALSE
;
2300 node
= gtk_ctree_node_nth(GTK_CTREE(clist
), row
);
2302 if( ! addrclip_is_empty( _clipBoard_
) ) {
2303 canTreePaste
= TRUE
;
2306 if (obj
->type
== ADDR_INTERFACE
) {
2307 AdapterInterface
*adapter
= ADAPTER_INTERFACE(obj
);
2308 iface
= adapter
->interface
;
2311 canTreeCopy
= FALSE
;
2312 if( iface
->readOnly
) {
2313 canTreePaste
= FALSE
;
2316 menu_set_sensitive( addrbook
.tree_factory
, "/New Book", TRUE
);
2317 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
2319 if( iface
->externalQuery
) canLookup
= TRUE
;
2321 if (obj
->type
== ADDR_DATASOURCE
) {
2322 ads
= ADAPTER_DSOURCE(obj
);
2323 ds
= ads
->dataSource
;
2326 iface
= ds
->interface
;
2331 if( iface
->readOnly
) {
2332 canTreePaste
= FALSE
;
2335 menu_set_sensitive( addrbook
.tree_factory
, "/New Folder", TRUE
);
2336 menu_set_sensitive( addrbook
.tree_factory
, "/New Group", TRUE
);
2337 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
2340 if( iface
->externalQuery
) canLookup
= TRUE
;
2342 else if (obj
->type
== ADDR_ITEM_FOLDER
) {
2343 ds
= addressbook_find_datasource( node
);
2347 iface
= ds
->interface
;
2350 if( iface
->readOnly
) {
2351 canTreePaste
= FALSE
;
2357 menu_set_sensitive( addrbook
.tree_factory
, "/New Folder", TRUE
);
2358 menu_set_sensitive( addrbook
.tree_factory
, "/New Group", TRUE
);
2359 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
2363 if( iface
->externalQuery
) {
2364 /* Enable deletion of LDAP folder */
2369 else if (obj
->type
== ADDR_ITEM_GROUP
) {
2370 ds
= addressbook_find_datasource( node
);
2373 iface
= ds
->interface
;
2376 if( ! iface
->readOnly
) {
2379 menu_set_sensitive( addrbook
.list_factory
, "/New Address", TRUE
);
2380 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
2383 else if (obj
->type
== ADDR_INTERFACE
) {
2384 canTreePaste
= FALSE
;
2388 if( ! addrselect_test_empty( _addressSelect_
) ) canCut
= TRUE
;
2390 if( ! addrselect_test_empty( _addressSelect_
) ) canCopy
= TRUE
;
2391 if( ! addrclip_is_empty( _clipBoard_
) ) canPaste
= TRUE
;
2395 menu_set_sensitive( addrbook
.tree_factory
, "/Edit", canEdit
);
2396 menu_set_sensitive( addrbook
.tree_factory
, "/Delete", canDelete
);
2397 menu_set_sensitive( addrbook
.tree_factory
, "/Cut", canTreeCut
);
2398 menu_set_sensitive( addrbook
.tree_factory
, "/Copy", canTreeCopy
);
2399 menu_set_sensitive( addrbook
.tree_factory
, "/Paste", canTreePaste
);
2401 menu_set_sensitive( addrbook
.menu_factory
, "/Book/Edit book", canEdit
);
2402 menu_set_sensitive( addrbook
.menu_factory
, "/Book/Delete book", canEdit
);
2403 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Cut", canCut
);
2404 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Copy", canCopy
);
2405 menu_set_sensitive( addrbook
.menu_factory
, "/Address/Paste", canPaste
);
2406 /* menu_set_sensitive( addrbook.menu_factory, "/Edit/Paste Address", canPaste );*/
2408 addressbook_show_buttons(addrbook
.target_compose
== NULL
, canLookup
, addrbook
.target_compose
!= NULL
);
2409 if( event
->button
== 3 ) {
2410 gtk_menu_popup(GTK_MENU(addrbook
.tree_popup
), NULL
, NULL
, NULL
, NULL
,
2411 event
->button
, event
->time
);
2417 static gboolean
addressbook_tree_button_released(GtkWidget
*ctree
,
2418 GdkEventButton
*event
,
2421 gtkut_ctree_set_focus_row(GTK_CTREE(addrbook
.ctree
), addrbook
.opened
);
2425 static void addressbook_new_folder_cb(gpointer data
, guint action
,
2428 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
2429 AddressObject
*obj
= NULL
;
2430 AddressDataSource
*ds
= NULL
;
2431 AddressBookFile
*abf
= NULL
;
2432 ItemFolder
*parentFolder
= NULL
;
2433 ItemFolder
*folder
= NULL
;
2435 if( ! addrbook
.treeSelected
) return;
2436 obj
= gtk_ctree_node_get_row_data( ctree
, addrbook
.treeSelected
);
2437 if( obj
== NULL
) return;
2438 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
2439 if( ds
== NULL
) return;
2441 if( obj
->type
== ADDR_DATASOURCE
) {
2442 if( ADAPTER_DSOURCE(obj
)->subType
!= ADDR_BOOK
) return;
2444 else if( obj
->type
== ADDR_ITEM_FOLDER
) {
2445 parentFolder
= ADAPTER_FOLDER(obj
)->itemFolder
;
2451 abf
= ds
->rawDataSource
;
2452 if( abf
== NULL
) return;
2453 folder
= addressbook_edit_folder( abf
, parentFolder
, NULL
);
2456 nn
= addressbook_node_add_folder(
2457 addrbook
.treeSelected
, ds
, folder
, ADDR_ITEM_FOLDER
);
2458 gtk_ctree_expand( ctree
, addrbook
.treeSelected
);
2459 if( addrbook
.treeSelected
== addrbook
.opened
)
2460 addressbook_set_clist(obj
, TRUE
);
2465 static void addressbook_new_group_cb(gpointer data
, guint action
,
2468 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
2469 AddressObject
*obj
= NULL
;
2470 AddressDataSource
*ds
= NULL
;
2471 AddressBookFile
*abf
= NULL
;
2472 ItemFolder
*parentFolder
= NULL
;
2473 ItemGroup
*group
= NULL
;
2475 if( ! addrbook
.treeSelected
) return;
2476 obj
= gtk_ctree_node_get_row_data(ctree
, addrbook
.treeSelected
);
2477 if( obj
== NULL
) return;
2478 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
2479 if( ds
== NULL
) return;
2481 if( obj
->type
== ADDR_DATASOURCE
) {
2482 if( ADAPTER_DSOURCE(obj
)->subType
!= ADDR_BOOK
) return;
2484 else if( obj
->type
== ADDR_ITEM_FOLDER
) {
2485 parentFolder
= ADAPTER_FOLDER(obj
)->itemFolder
;
2491 abf
= ds
->rawDataSource
;
2492 if( abf
== NULL
) return;
2493 group
= addressbook_edit_group( abf
, parentFolder
, NULL
);
2496 nn
= addressbook_node_add_group( addrbook
.treeSelected
, ds
, group
);
2497 gtk_ctree_expand( ctree
, addrbook
.treeSelected
);
2498 if( addrbook
.treeSelected
== addrbook
.opened
)
2499 addressbook_set_clist(obj
, TRUE
);
2504 static void addressbook_change_node_name(GtkCTreeNode
*node
, const gchar
*name
)
2506 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
2509 GdkPixmap
*pix_cl
, *pix_op
;
2510 GdkBitmap
*mask_cl
, *mask_op
;
2511 gboolean is_leaf
, expanded
;
2513 gtk_ctree_get_node_info(ctree
, node
, text
, &spacing
,
2514 &pix_cl
, &mask_cl
, &pix_op
, &mask_op
,
2515 &is_leaf
, &expanded
);
2516 gtk_sctree_set_node_info(ctree
, node
, name
, spacing
,
2517 pix_cl
, mask_cl
, pix_op
, mask_op
,
2523 * \param obj Address object to edit.
2524 * \param node Node in tree.
2525 * \return New name of data source.
2527 static gchar
*addressbook_edit_datasource( AddressObject
*obj
, GtkCTreeNode
*node
) {
2528 gchar
*newName
= NULL
;
2529 AddressDataSource
*ds
= NULL
;
2530 AddressInterface
*iface
= NULL
;
2531 AdapterDSource
*ads
= NULL
;
2533 ds
= addressbook_find_datasource( node
);
2534 if( ds
== NULL
) return NULL
;
2535 iface
= ds
->interface
;
2536 if( ! iface
->haveLibrary
) return NULL
;
2538 /* Read data from data source */
2539 if( addrindex_ds_get_modify_flag( ds
) ) {
2540 addrindex_ds_read_data( ds
);
2543 if( ! addrindex_ds_get_read_flag( ds
) ) {
2544 addrindex_ds_read_data( ds
);
2548 ads
= ADAPTER_DSOURCE(obj
);
2549 if( ads
->subType
== ADDR_BOOK
) {
2550 if( addressbook_edit_book( _addressIndex_
, ads
) == NULL
) return NULL
;
2552 else if( ads
->subType
== ADDR_VCARD
) {
2553 if( addressbook_edit_vcard( _addressIndex_
, ads
) == NULL
) return NULL
;
2556 else if( ads
->subType
== ADDR_JPILOT
) {
2557 if( addressbook_edit_jpilot( _addressIndex_
, ads
) == NULL
) return NULL
;
2561 else if( ads
->subType
== ADDR_LDAP
) {
2562 if( addressbook_edit_ldap( _addressIndex_
, ads
) == NULL
) return NULL
;
2568 newName
= obj
->name
;
2573 * Edit an object that is in the address tree area.
2575 static void addressbook_treenode_edit_cb(gpointer data
, guint action
,
2578 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
2580 AddressDataSource
*ds
= NULL
;
2581 AddressBookFile
*abf
= NULL
;
2582 GtkCTreeNode
*node
= NULL
, *parentNode
= NULL
;
2585 if( ! addrbook
.treeSelected
) return;
2586 node
= addrbook
.treeSelected
;
2587 if( GTK_CTREE_ROW(node
)->level
== 1 ) return;
2588 obj
= gtk_ctree_node_get_row_data( ctree
, node
);
2589 if( obj
== NULL
) return;
2590 parentNode
= GTK_CTREE_ROW(node
)->parent
;
2592 ds
= addressbook_find_datasource( node
);
2593 if( ds
== NULL
) return;
2595 if( obj
->type
== ADDR_DATASOURCE
) {
2596 name
= addressbook_edit_datasource( obj
, node
);
2597 if( name
== NULL
) return;
2600 abf
= ds
->rawDataSource
;
2601 if( abf
== NULL
) return;
2602 if( obj
->type
== ADDR_ITEM_FOLDER
) {
2603 AdapterFolder
*adapter
= ADAPTER_FOLDER(obj
);
2604 ItemFolder
*item
= adapter
->itemFolder
;
2605 ItemFolder
*parentFolder
= NULL
;
2606 parentFolder
= ( ItemFolder
* ) ADDRITEM_PARENT(item
);
2607 if( addressbook_edit_folder( abf
, parentFolder
, item
) == NULL
) return;
2608 name
= ADDRITEM_NAME(item
);
2610 else if( obj
->type
== ADDR_ITEM_GROUP
) {
2611 AdapterGroup
*adapter
= ADAPTER_GROUP(obj
);
2612 ItemGroup
*item
= adapter
->itemGroup
;
2613 ItemFolder
*parentFolder
= NULL
;
2614 parentFolder
= ( ItemFolder
* ) ADDRITEM_PARENT(item
);
2615 if( addressbook_edit_group( abf
, parentFolder
, item
) == NULL
) return;
2616 name
= ADDRITEM_NAME(item
);
2619 if( name
&& parentNode
) {
2620 /* Update node in tree view */
2621 addressbook_change_node_name( node
, name
);
2622 gtk_sctree_sort_node(ctree
, parentNode
);
2623 gtk_ctree_expand( ctree
, node
);
2624 gtk_sctree_select( GTK_SCTREE( ctree
), node
);
2631 ADDRTREE_DEL_FOLDER_ONLY
,
2632 ADDRTREE_DEL_FOLDER_ADDR
2636 * Delete an item from the tree widget.
2637 * \param data Data passed in.
2638 * \param action Action.
2639 * \param widget Widget issuing callback.
2641 static void addressbook_treenode_delete_cb(
2642 gpointer data
, guint action
, GtkWidget
*widget
)
2644 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
2645 GtkCTreeNode
*node
= NULL
;
2649 AddrBookBase
*adbase
;
2650 AddressCache
*cache
;
2651 AdapterDSource
*ads
= NULL
;
2652 AddressInterface
*iface
= NULL
;
2653 AddressDataSource
*ds
= NULL
;
2654 gboolean remFlag
= FALSE
;
2655 TreeItemDelType delType
;
2657 if( ! addrbook
.treeSelected
) return;
2658 node
= addrbook
.treeSelected
;
2659 if( GTK_CTREE_ROW(node
)->level
== 1 ) return;
2661 obj
= gtk_ctree_node_get_row_data( ctree
, node
);
2662 g_return_if_fail(obj
!= NULL
);
2664 if( obj
->type
== ADDR_DATASOURCE
) {
2665 ads
= ADAPTER_DSOURCE(obj
);
2666 if( ads
== NULL
) return;
2667 ds
= ads
->dataSource
;
2668 if( ds
== NULL
) return;
2671 /* Must be folder or something else */
2672 ds
= addressbook_find_datasource( node
);
2673 if( ds
== NULL
) return;
2675 /* Only allow deletion from non-readOnly */
2676 iface
= ds
->interface
;
2677 if( iface
->readOnly
) {
2678 /* Allow deletion of query results */
2679 if( ! iface
->externalQuery
) return;
2683 /* Confirm deletion */
2684 delType
= ADDRTREE_DEL_NONE
;
2685 if( obj
->type
== ADDR_ITEM_FOLDER
) {
2686 if( iface
->externalQuery
) {
2687 message
= g_strdup_printf( _(
2688 "Do you want to delete the query " \
2689 "results and addresses in '%s' ?" ),
2691 aval
= alertpanel( _("Delete"), message
,
2692 GTK_STOCK_CANCEL
, "+"GTK_STOCK_DELETE
, NULL
);
2694 if( aval
== G_ALERTALTERNATE
) {
2695 delType
= ADDRTREE_DEL_FOLDER_ADDR
;
2699 message
= g_strdup_printf
2700 ( _( "Do you want to delete '%s' ?"
2701 "If you delete the folder only, the addresses it contains will be moved into the parent folder." ),
2703 aval
= alertpanel( _("Delete folder"), message
,
2704 GTK_STOCK_CANCEL
, _("+Delete _folder only"), _("Delete folder and _addresses"));
2706 if( aval
== G_ALERTALTERNATE
) {
2707 delType
= ADDRTREE_DEL_FOLDER_ONLY
;
2709 else if( aval
== G_ALERTOTHER
) {
2710 delType
= ADDRTREE_DEL_FOLDER_ADDR
;
2714 else if( obj
->type
== ADDR_ITEM_GROUP
) {
2715 message
= g_strdup_printf(_("Do you want to delete '%s'?\n"
2716 "The addresses it contains will not be lost."), obj
->name
);
2717 aval
= alertpanel(_("Delete"), message
, GTK_STOCK_CANCEL
,
2718 "+" GTK_STOCK_DELETE
, NULL
);
2720 if( aval
== G_ALERTALTERNATE
) delType
= ADDRTREE_DEL_FOLDER_ONLY
;
2722 message
= g_strdup_printf(_("Do you want to delete '%s'?\n"
2723 "The addresses it contains will be lost."), obj
->name
);
2724 aval
= alertpanel(_("Delete"), message
, GTK_STOCK_CANCEL
,
2725 "+" GTK_STOCK_DELETE
, NULL
);
2727 if( aval
== G_ALERTALTERNATE
) delType
= ADDRTREE_DEL_DATA
;
2729 if( delType
== ADDRTREE_DEL_NONE
) return;
2731 /* Proceed with deletion */
2732 if( obj
->type
== ADDR_DATASOURCE
) {
2733 /* Remove node from tree */
2734 gtk_ctree_remove_node( ctree
, node
);
2736 /* Remove data source. */
2737 if( addrindex_index_remove_datasource( _addressIndex_
, ds
) ) {
2738 addrindex_free_datasource( ds
);
2743 /* Get reference to cache */
2744 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
2745 if( adbase
== NULL
) return;
2746 cache
= adbase
->addressCache
;
2748 /* Remove query results folder */
2749 if( iface
->externalQuery
) {
2750 AdapterFolder
*adapter
= ADAPTER_FOLDER(obj
);
2751 ItemFolder
*folder
= adapter
->itemFolder
;
2753 adapter
->itemFolder
= NULL
;
2755 printf( "remove folder for ::%s::\n", obj->name );
2756 printf( " folder name ::%s::\n", ADDRITEM_NAME(folder) );
2757 printf( "-------------- remove results\n" );
2759 addrindex_remove_results( ds
, folder
);
2760 /* printf( "-------------- remove node\n" ); */
2761 gtk_ctree_remove_node( ctree
, node
);
2765 /* Code below is valid for regular address book deletion */
2766 if( obj
->type
== ADDR_ITEM_FOLDER
) {
2767 AdapterFolder
*adapter
= ADAPTER_FOLDER(obj
);
2768 ItemFolder
*item
= adapter
->itemFolder
;
2770 if( delType
== ADDRTREE_DEL_FOLDER_ONLY
) {
2771 /* Remove folder only */
2772 item
= addrcache_remove_folder( cache
, item
);
2774 addritem_free_item_folder( item
);
2775 addressbook_move_nodes_up( ctree
, node
);
2779 else if( delType
== ADDRTREE_DEL_FOLDER_ADDR
) {
2780 /* Remove folder and addresses */
2781 item
= addrcache_remove_folder_delete( cache
, item
);
2783 addritem_free_item_folder( item
);
2788 else if( obj
->type
== ADDR_ITEM_GROUP
) {
2789 AdapterGroup
*adapter
= ADAPTER_GROUP(obj
);
2790 ItemGroup
*item
= adapter
->itemGroup
;
2792 item
= addrcache_remove_group( cache
, item
);
2794 addritem_free_item_group( item
);
2801 gtk_ctree_remove_node(ctree
, node
);
2805 void addressbook_new_address_from_book_post_cb( ItemPerson
*person
)
2807 if( person
&& addrbook
.treeSelected
== addrbook
.opened
) {
2808 gtk_clist_unselect_all( GTK_CLIST(addrbook
.clist
) );
2809 addressbook_folder_refresh_one_person(
2810 GTK_CTREE(addrbook
.clist
), person
);
2812 addressbook_address_list_set_focus();
2815 void addressbook_new_address_from_folder_post_cb( ItemPerson
*person
)
2817 if( person
&& addrbook
.treeSelected
== addrbook
.opened
) {
2818 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), addrbook
.opened
);
2819 addressbook_set_clist(
2820 gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
),
2824 addressbook_address_list_set_focus();
2827 static void addressbook_new_address_cb( gpointer data
, guint action
, GtkWidget
*widget
) {
2828 AddressObject
*pobj
= NULL
;
2829 AddressDataSource
*ds
= NULL
;
2830 AddressBookFile
*abf
= NULL
;
2832 pobj
= gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
), addrbook
.treeSelected
);
2833 if( pobj
== NULL
) return;
2834 ds
= addressbook_find_datasource( GTK_CTREE_NODE(addrbook
.treeSelected
) );
2835 if( ds
== NULL
) return;
2837 abf
= ds
->rawDataSource
;
2838 if( abf
== NULL
) return;
2840 if( pobj
->type
== ADDR_DATASOURCE
) {
2841 if( ADAPTER_DSOURCE(pobj
)->subType
== ADDR_BOOK
) {
2843 ItemPerson
*person
= addressbook_edit_person( abf
, NULL
, NULL
, FALSE
,
2844 addrbook
.editaddress_vbox
,
2845 addressbook_new_address_from_book_post_cb
,
2847 if (prefs_common
.addressbook_use_editaddress_dialog
)
2848 addressbook_new_address_from_book_post_cb( person
);
2851 else if( pobj
->type
== ADDR_ITEM_FOLDER
) {
2853 ItemFolder
*folder
= ADAPTER_FOLDER(pobj
)->itemFolder
;
2854 ItemPerson
*person
= addressbook_edit_person( abf
, folder
, NULL
, FALSE
,
2855 addrbook
.editaddress_vbox
,
2856 addressbook_new_address_from_folder_post_cb
,
2858 if (prefs_common
.addressbook_use_editaddress_dialog
)
2859 addressbook_new_address_from_folder_post_cb( person
);
2861 else if( pobj
->type
== ADDR_ITEM_GROUP
) {
2862 /* New address in group */
2863 ItemGroup
*group
= ADAPTER_GROUP(pobj
)->itemGroup
;
2864 if( addressbook_edit_group( abf
, NULL
, group
) == NULL
) return;
2865 if (addrbook
.treeSelected
== addrbook
.opened
) {
2866 /* Change node name in tree. */
2867 addressbook_change_node_name( addrbook
.treeSelected
, ADDRITEM_NAME(group
) );
2868 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), addrbook
.opened
);
2869 addressbook_set_clist(
2870 gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
),
2878 * Search for specified child group node in address index tree.
2879 * \param parent Parent node.
2880 * \param group Group to find.
2882 static GtkCTreeNode
*addressbook_find_group_node( GtkCTreeNode
*parent
, ItemGroup
*group
) {
2883 GtkCTreeNode
*node
= NULL
;
2884 GtkCTreeRow
*currRow
;
2886 currRow
= GTK_CTREE_ROW( parent
);
2888 node
= currRow
->children
;
2892 obj
= gtk_ctree_node_get_row_data( GTK_CTREE(addrbook
.ctree
), node
);
2893 if( obj
->type
== ADDR_ITEM_GROUP
) {
2894 ItemGroup
*g
= ADAPTER_GROUP(obj
)->itemGroup
;
2895 if( g
== group
) return node
;
2897 currRow
= GTK_CTREE_ROW(node
);
2898 node
= currRow
->sibling
;
2904 static AddressBookFile
*addressbook_get_book_file() {
2905 AddressBookFile
*abf
= NULL
;
2906 AddressDataSource
*ds
= NULL
;
2908 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
2909 if( ds
== NULL
) return NULL
;
2910 if( ds
->type
== ADDR_IF_BOOK
) abf
= ds
->rawDataSource
;
2914 static void addressbook_tree_remove_children( GtkCTree
*ctree
, GtkCTreeNode
*parent
) {
2918 /* Remove existing folders and groups */
2919 row
= GTK_CTREE_ROW( parent
);
2921 while( (node
= row
->children
) ) {
2922 gtk_ctree_remove_node( ctree
, node
);
2927 static void addressbook_move_nodes_up( GtkCTree
*ctree
, GtkCTreeNode
*node
) {
2928 GtkCTreeNode
*parent
, *child
;
2929 GtkCTreeRow
*currRow
;
2930 currRow
= GTK_CTREE_ROW( node
);
2932 parent
= currRow
->parent
;
2933 while( (child
= currRow
->children
) ) {
2934 gtk_ctree_move( ctree
, child
, parent
, node
);
2936 gtk_sctree_sort_node( ctree
, parent
);
2940 void addressbook_edit_address_post_cb( ItemPerson
*person
)
2943 addressbook_folder_refresh_one_person( GTK_CTREE(addrbook
.clist
), person
);
2944 invalidate_address_completion();
2946 addressbook_address_list_set_focus();
2949 void addressbook_address_list_set_focus( void )
2951 if (!prefs_common
.addressbook_use_editaddress_dialog
)
2952 gtk_window_set_focus(GTK_WINDOW(addrbook
.window
), addrbook
.clist
);
2955 static void addressbook_edit_address_cb( gpointer data
, guint action
, GtkWidget
*widget
) {
2956 GtkCTree
*clist
= GTK_CTREE(addrbook
.clist
);
2958 AddressObject
*obj
= NULL
, *pobj
= NULL
;
2959 AddressDataSource
*ds
= NULL
;
2960 GtkCTreeNode
*node
= NULL
, *parentNode
= NULL
;
2962 AddressBookFile
*abf
= NULL
;
2964 if( addrbook
.listSelected
== NULL
) return;
2965 obj
= gtk_ctree_node_get_row_data( clist
, addrbook
.listSelected
);
2966 g_return_if_fail(obj
!= NULL
);
2968 ctree
= GTK_CTREE( addrbook
.ctree
);
2969 pobj
= gtk_ctree_node_get_row_data( ctree
, addrbook
.treeSelected
);
2970 node
= gtk_ctree_find_by_row_data( ctree
, addrbook
.treeSelected
, obj
);
2972 ds
= addressbook_find_datasource( GTK_CTREE_NODE(addrbook
.treeSelected
) );
2973 if( ds
== NULL
) return;
2975 abf
= addressbook_get_book_file();
2977 if( obj
->type
== ADDR_ITEM_EMAIL
) {
2978 ItemEMail
*email
= ( ItemEMail
* ) obj
;
2979 if( email
== NULL
) return;
2980 if( pobj
&& pobj
->type
== ADDR_ITEM_GROUP
) {
2981 /* Edit parent group */
2982 AdapterGroup
*adapter
= ADAPTER_GROUP(pobj
);
2983 ItemGroup
*itemGrp
= adapter
->itemGroup
;
2984 if( abf
== NULL
) return;
2985 if( addressbook_edit_group( abf
, NULL
, itemGrp
) == NULL
) return;
2986 name
= ADDRITEM_NAME(itemGrp
);
2987 node
= addrbook
.treeSelected
;
2988 parentNode
= GTK_CTREE_ROW(node
)->parent
;
2991 /* Edit person - email page */
2993 person
= ( ItemPerson
* ) ADDRITEM_PARENT(email
);
2994 if ( addressbook_edit_person( abf
, NULL
, person
, TRUE
, addrbook
.editaddress_vbox
,
2995 addressbook_edit_address_post_cb
,
2996 prefs_common
.addressbook_use_editaddress_dialog
?TRUE
:FALSE
)
2998 if (prefs_common
.addressbook_use_editaddress_dialog
)
2999 addressbook_edit_address_post_cb( person
);
3004 else if( obj
->type
== ADDR_ITEM_PERSON
) {
3005 /* Edit person - basic page */
3006 ItemPerson
*person
= ( ItemPerson
* ) obj
;
3007 if( addressbook_edit_person( abf
, NULL
, person
, FALSE
, addrbook
.editaddress_vbox
,
3008 addressbook_edit_address_post_cb
,
3009 prefs_common
.addressbook_use_editaddress_dialog
?TRUE
:FALSE
)
3011 if (prefs_common
.addressbook_use_editaddress_dialog
)
3012 addressbook_edit_address_post_cb( person
);
3016 else if( obj
->type
== ADDR_ITEM_GROUP
) {
3017 ItemGroup
*itemGrp
= ( ItemGroup
* ) obj
;
3018 if( addressbook_edit_group( abf
, NULL
, itemGrp
) == NULL
) return;
3019 parentNode
= addrbook
.treeSelected
;
3020 node
= addressbook_find_group_node( parentNode
, itemGrp
);
3021 name
= ADDRITEM_NAME(itemGrp
);
3022 invalidate_address_completion();
3028 /* Update tree node with node name */
3029 if( node
== NULL
) return;
3030 addressbook_change_node_name( node
, name
);
3031 gtk_sctree_sort_node( ctree
, parentNode
);
3032 gtk_sctree_select( GTK_SCTREE(ctree
), addrbook
.opened
);
3033 addressbook_set_clist(
3034 gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
),
3039 static void addressbook_delete_address_cb(gpointer data
, guint action
,
3042 gtk_clist_freeze(GTK_CLIST(addrbook
.clist
));
3043 addressbook_del_clicked(NULL
, NULL
);
3044 gtk_clist_thaw(GTK_CLIST(addrbook
.clist
));
3047 static void close_cb(gpointer data
, guint action
, GtkWidget
*widget
)
3049 addressbook_close();
3052 static void addressbook_file_save_cb( gpointer data
, guint action
, GtkWidget
*widget
) {
3053 addressbook_export_to_file();
3056 static void addressbook_person_expand_node( GtkCTree
*ctree
, GList
*node
, gpointer
*data
) {
3058 ItemPerson
*person
= gtk_ctree_node_get_row_data( ctree
, GTK_CTREE_NODE(node
) );
3059 if( person
) addritem_person_set_opened( person
, TRUE
);
3063 static void addressbook_person_collapse_node( GtkCTree
*ctree
, GList
*node
, gpointer
*data
) {
3065 ItemPerson
*person
= gtk_ctree_node_get_row_data( ctree
, GTK_CTREE_NODE(node
) );
3066 if( person
) addritem_person_set_opened( person
, FALSE
);
3070 static gchar
*addressbook_format_item_clist( ItemPerson
*person
, ItemEMail
*email
) {
3072 gchar
*eMailAlias
= ADDRITEM_NAME(email
);
3073 if( eMailAlias
&& *eMailAlias
!= '\0' ) {
3075 str
= g_strdup_printf( "%s - %s", ADDRITEM_NAME(person
), eMailAlias
);
3078 str
= g_strdup( eMailAlias
);
3084 static void addressbook_load_group( GtkCTree
*clist
, ItemGroup
*itemGroup
) {
3085 GList
*items
= itemGroup
->listEMail
;
3086 AddressTypeControlItem
*atci
= addrbookctl_lookup( ADDR_ITEM_EMAIL
);
3087 for( ; items
!= NULL
; items
= g_list_next( items
) ) {
3088 GtkCTreeNode
*nodeEMail
= NULL
;
3089 gchar
*text
[N_LIST_COLS
];
3090 ItemEMail
*email
= items
->data
;
3094 if( ! email
) continue;
3096 person
= ( ItemPerson
* ) ADDRITEM_PARENT(email
);
3097 str
= addressbook_format_item_clist( person
, email
);
3099 text
[COL_NAME
] = str
;
3102 text
[COL_NAME
] = ADDRITEM_NAME(person
);
3104 text
[COL_ADDRESS
] = email
->address
;
3105 text
[COL_REMARKS
] = email
->remarks
;
3106 nodeEMail
= gtk_sctree_insert_node(
3108 text
, FOLDER_SPACING
,
3109 atci
->iconXpm
, atci
->maskXpm
,
3110 atci
->iconXpmOpen
, atci
->maskXpmOpen
,
3112 gtk_ctree_node_set_row_data( clist
, nodeEMail
, email
);
3118 static void addressbook_folder_load_one_person(
3119 GtkCTree
*clist
, ItemPerson
*person
,
3120 AddressTypeControlItem
*atci
,
3121 AddressTypeControlItem
*atciMail
)
3123 GtkCTreeNode
*nodePerson
= NULL
;
3124 GtkCTreeNode
*nodeEMail
= NULL
;
3125 gchar
*text
[N_LIST_COLS
];
3126 gboolean flgFirst
= TRUE
, haveAddr
= FALSE
;
3129 if( person
== NULL
) return;
3131 text
[COL_NAME
] = "";
3132 node
= person
->listEMail
;
3134 ItemEMail
*email
= node
->data
;
3135 gchar
*eMailAddr
= NULL
;
3136 node
= g_list_next( node
);
3138 text
[COL_ADDRESS
] = email
->address
;
3139 text
[COL_REMARKS
] = email
->remarks
;
3140 eMailAddr
= ADDRITEM_NAME(email
);
3141 if( eMailAddr
&& *eMailAddr
== '\0' ) eMailAddr
= NULL
;
3143 /* First email belongs with person */
3144 gchar
*str
= addressbook_format_item_clist( person
, email
);
3146 text
[COL_NAME
] = str
;
3149 text
[COL_NAME
] = ADDRITEM_NAME(person
);
3151 nodePerson
= gtk_sctree_insert_node(
3153 text
, FOLDER_SPACING
,
3154 atci
->iconXpm
, atci
->maskXpm
,
3155 atci
->iconXpmOpen
, atci
->maskXpmOpen
,
3156 FALSE
, person
->isOpened
);
3159 gtk_ctree_node_set_row_data(clist
, nodePerson
, person
);
3162 /* Subsequent email is a child node of person */
3163 text
[COL_NAME
] = ADDRITEM_NAME(email
);
3164 nodeEMail
= gtk_sctree_insert_node(
3165 clist
, nodePerson
, NULL
,
3166 text
, FOLDER_SPACING
,
3167 atciMail
->iconXpm
, atciMail
->maskXpm
,
3168 atciMail
->iconXpmOpen
, atciMail
->maskXpmOpen
,
3170 gtk_ctree_node_set_row_data(clist
, nodeEMail
, email
);
3176 /* Have name without EMail */
3177 text
[COL_NAME
] = ADDRITEM_NAME(person
);
3178 text
[COL_ADDRESS
] = "";
3179 text
[COL_REMARKS
] = "";
3180 nodePerson
= gtk_sctree_insert_node(
3182 text
, FOLDER_SPACING
,
3183 atci
->iconXpm
, atci
->maskXpm
,
3184 atci
->iconXpmOpen
, atci
->maskXpmOpen
,
3185 FALSE
, person
->isOpened
);
3186 gtk_ctree_node_set_row_data(clist
, nodePerson
, person
);
3191 static void addressbook_folder_load_person( GtkCTree
*clist
, ItemFolder
*itemFolder
) {
3193 AddressTypeControlItem
*atci
= addrbookctl_lookup( ADDR_ITEM_PERSON
);
3194 AddressTypeControlItem
*atciMail
= addrbookctl_lookup( ADDR_ITEM_EMAIL
);
3196 if( atci
== NULL
) return;
3197 if( atciMail
== NULL
) return;
3199 /* Load email addresses */
3200 items
= addritem_folder_get_person_list( itemFolder
);
3201 for( ; items
!= NULL
; items
= g_list_next( items
) ) {
3202 addressbook_folder_load_one_person( clist
, items
->data
, atci
, atciMail
);
3204 /* Free up the list */
3205 mgu_clear_list( items
);
3206 g_list_free( items
);
3209 static void addressbook_folder_remove_node( GtkCTree
*clist
, GtkCTreeNode
*node
) {
3210 addrbook
.listSelected
= NULL
;
3211 gtk_ctree_remove_node( clist
, node
);
3212 addressbook_menubar_set_sensitive( FALSE
);
3213 addressbook_menuitem_set_sensitive(
3214 gtk_ctree_node_get_row_data(
3215 GTK_CTREE(clist
), addrbook
.treeSelected
),
3216 addrbook
.treeSelected
);
3219 static void addressbook_folder_refresh_one_person( GtkCTree
*clist
, ItemPerson
*person
) {
3220 AddressTypeControlItem
*atci
= addrbookctl_lookup( ADDR_ITEM_PERSON
);
3221 AddressTypeControlItem
*atciMail
= addrbookctl_lookup( ADDR_ITEM_EMAIL
);
3223 if( atci
== NULL
) return;
3224 if( atciMail
== NULL
) return;
3225 if( person
== NULL
) return;
3226 /* unload the person */
3228 node
= gtk_ctree_find_by_row_data( clist
, NULL
, person
);
3230 addressbook_folder_remove_node( clist
, node
);
3231 addressbook_folder_load_one_person( clist
, person
, atci
, atciMail
);
3232 gtk_sctree_sort_node( clist
, NULL
);
3233 node
= gtk_ctree_find_by_row_data( clist
, NULL
, person
);
3235 gtk_sctree_select( GTK_SCTREE(clist
), node
);
3236 if (!gtk_ctree_node_is_visible( clist
, node
) )
3237 gtk_ctree_node_moveto( clist
, node
, 0, 0, 0 );
3241 static void addressbook_folder_remove_one_person( GtkCTree
*clist
, ItemPerson
*person
) {
3245 if( person
== NULL
) return;
3246 node
= gtk_ctree_find_by_row_data( clist
, NULL
, person
);
3247 row
= gtk_clist_find_row_from_data( GTK_CLIST(clist
), person
);
3249 addressbook_folder_remove_node( clist
, node
);
3253 static void addressbook_folder_load_group( GtkCTree
*clist
, ItemFolder
*itemFolder
) {
3255 AddressTypeControlItem
*atci
= addrbookctl_lookup( ADDR_ITEM_GROUP
);
3257 /* Load any groups */
3258 if( ! atci
) return;
3259 items
= addritem_folder_get_group_list( itemFolder
);
3260 for( ; items
!= NULL
; items
= g_list_next( items
) ) {
3261 GtkCTreeNode
*nodeGroup
= NULL
;
3262 gchar
*text
[N_LIST_COLS
];
3263 ItemGroup
*group
= items
->data
;
3264 if( group
== NULL
) continue;
3265 text
[COL_NAME
] = ADDRITEM_NAME(group
);
3266 text
[COL_ADDRESS
] = "";
3267 text
[COL_REMARKS
] = "";
3268 nodeGroup
= gtk_sctree_insert_node(clist
, NULL
, NULL
,
3269 text
, FOLDER_SPACING
,
3270 atci
->iconXpm
, atci
->maskXpm
,
3271 atci
->iconXpmOpen
, atci
->maskXpmOpen
,
3273 gtk_ctree_node_set_row_data(clist
, nodeGroup
, group
);
3274 gtk_sctree_sort_node(clist
, NULL
);
3276 /* Free up the list */
3277 mgu_clear_list( items
);
3278 g_list_free( items
);
3282 * Search ctree widget callback function.
3283 * \param pA Pointer to node.
3284 * \param pB Pointer to data item being sought.
3285 * \return Zero (0) if group found.
3287 static int addressbook_treenode_find_group_cb( gconstpointer pA
, gconstpointer pB
) {
3290 aoA
= ( AddressObject
* ) pA
;
3291 if( aoA
->type
== ADDR_ITEM_GROUP
) {
3292 ItemGroup
*group
, *grp
;
3294 grp
= ADAPTER_GROUP(aoA
)->itemGroup
;
3295 group
= ( ItemGroup
* ) pB
;
3296 if( grp
== group
) return 0; /* Found group */
3302 * Search ctree widget callback function.
3303 * \param pA Pointer to node.
3304 * \param pB Pointer to data item being sought.
3305 * \return Zero (0) if folder found.
3307 static int addressbook_treenode_find_folder_cb( gconstpointer pA
, gconstpointer pB
) {
3310 aoA
= ( AddressObject
* ) pA
;
3311 if( aoA
->type
== ADDR_ITEM_FOLDER
) {
3312 ItemFolder
*folder
, *fld
;
3314 fld
= ADAPTER_FOLDER(aoA
)->itemFolder
;
3315 folder
= ( ItemFolder
* ) pB
;
3316 if( fld
== folder
) return 0; /* Found folder */
3322 * Remove folder and group nodes from tree widget for items contained ("cut")
3325 static void addressbook_treenode_remove_item( void ) {
3327 AddrSelectItem
*cutItem
;
3328 AddressCache
*cache
;
3329 AddrItemObject
*aio
;
3330 GtkCTree
*ctree
= GTK_CTREE( addrbook
.ctree
);
3333 node
= _clipBoard_
->objectList
;
3335 cutItem
= node
->data
;
3336 node
= g_list_next( node
);
3337 cache
= addrindex_get_cache(
3338 _clipBoard_
->addressIndex
, cutItem
->cacheID
);
3339 if( cache
== NULL
) continue;
3340 aio
= addrcache_get_object( cache
, cutItem
->uid
);
3343 if( ADDRITEM_TYPE(aio
) == ITEMTYPE_FOLDER
) {
3346 folder
= ( ItemFolder
* ) aio
;
3347 tn
= gtk_ctree_find_by_row_data_custom(
3348 ctree
, NULL
, folder
,
3349 addressbook_treenode_find_folder_cb
);
3351 else if( ADDRITEM_TYPE(aio
) == ITEMTYPE_GROUP
) {
3354 group
= ( ItemGroup
* ) aio
;
3355 tn
= gtk_ctree_find_by_row_data_custom(
3357 addressbook_treenode_find_group_cb
);
3361 /* Free up adapter and remove node. */
3362 gtk_ctree_remove_node( ctree
, tn
);
3369 * Find parent datasource for specified tree node.
3370 * \param node Node to test.
3371 * \return Data source, or NULL if not found.
3373 static AddressDataSource
*addressbook_find_datasource( GtkCTreeNode
*node
) {
3374 AddressDataSource
*ds
= NULL
;
3377 g_return_val_if_fail(addrbook
.ctree
!= NULL
, NULL
);
3380 if( GTK_CTREE_ROW(node
)->level
< 2 ) return NULL
;
3381 ao
= gtk_ctree_node_get_row_data( GTK_CTREE(addrbook
.ctree
), node
);
3383 /* printf( "ao->type = %d\n", ao->type ); */
3384 if( ao
->type
== ADDR_DATASOURCE
) {
3385 AdapterDSource
*ads
= ADAPTER_DSOURCE(ao
);
3386 /* printf( "found it\n" ); */
3387 ds
= ads
->dataSource
;
3391 node
= GTK_CTREE_ROW(node
)->parent
;
3397 * Load address list widget with children of specified object.
3398 * \param obj Parent object to be loaded.
3400 static void addressbook_set_clist( AddressObject
*obj
, gboolean refresh
) {
3401 GtkCTree
*ctreelist
= GTK_CTREE(addrbook
.clist
);
3402 GtkCList
*clist
= GTK_CLIST(addrbook
.clist
);
3403 AddressDataSource
*ds
= NULL
;
3404 AdapterDSource
*ads
= NULL
;
3405 static AddressObject
*last_obj
= NULL
;
3407 if (addrbook
.clist
== NULL
) {
3410 if (obj
== last_obj
&& !refresh
)
3415 gtk_clist_clear(clist
);
3419 if( obj
->type
== ADDR_INTERFACE
) {
3420 /* printf( "set_clist: loading datasource...\n" ); */
3421 /* addressbook_node_load_datasource( GTK_CTREE(clist), obj ); */
3425 gtk_clist_freeze(clist
);
3426 gtk_clist_clear(clist
);
3428 if( obj
->type
== ADDR_DATASOURCE
) {
3429 ads
= ADAPTER_DSOURCE(obj
);
3430 ds
= ADAPTER_DSOURCE(obj
)->dataSource
;
3432 /* Load root folder */
3433 ItemFolder
*rootFolder
= NULL
;
3434 rootFolder
= addrindex_ds_get_root_folder( ds
);
3435 addressbook_folder_load_person(
3436 ctreelist
, addrindex_ds_get_root_folder( ds
) );
3437 addressbook_folder_load_group(
3438 ctreelist
, addrindex_ds_get_root_folder( ds
) );
3442 if( obj
->type
== ADDR_ITEM_GROUP
) {
3444 ItemGroup
*itemGroup
= ADAPTER_GROUP(obj
)->itemGroup
;
3445 addressbook_load_group( ctreelist
, itemGroup
);
3447 else if( obj
->type
== ADDR_ITEM_FOLDER
) {
3449 ItemFolder
*itemFolder
= ADAPTER_FOLDER(obj
)->itemFolder
;
3450 addressbook_folder_load_person( ctreelist
, itemFolder
);
3451 addressbook_folder_load_group( ctreelist
, itemFolder
);
3454 gtk_sctree_sort_recursive(GTK_CTREE(clist
), NULL
);
3455 clist
->focus_row
= -1;
3456 gtk_clist_thaw(clist
);
3460 * Call back function to free adaptor. Call back is setup by function
3461 * gtk_ctree_node_set_row_data_full() when node is populated. This function is
3462 * called when the address book tree widget node is removed by calling
3463 * function gtk_ctree_remove_node().
3465 * \param data Tree node's row data.
3467 static void addressbook_free_treenode( gpointer data
) {
3470 ao
= ( AddressObject
* ) data
;
3471 if( ao
== NULL
) return;
3472 if( ao
->type
== ADDR_INTERFACE
) {
3473 AdapterInterface
*ai
= ADAPTER_INTERFACE(ao
);
3474 addrbookctl_free_interface( ai
);
3476 else if( ao
->type
== ADDR_DATASOURCE
) {
3477 AdapterDSource
*ads
= ADAPTER_DSOURCE(ao
);
3478 addrbookctl_free_datasource( ads
);
3480 else if( ao
->type
== ADDR_ITEM_FOLDER
) {
3481 AdapterFolder
*af
= ADAPTER_FOLDER(ao
);
3482 addrbookctl_free_folder( af
);
3484 else if( ao
->type
== ADDR_ITEM_GROUP
) {
3485 AdapterGroup
*ag
= ADAPTER_GROUP(ao
);
3486 addrbookctl_free_group( ag
);
3491 * Create new adaptor for specified data source.
3493 AdapterDSource
*addressbook_create_ds_adapter( AddressDataSource
*ds
,
3494 AddressObjectType otype
, gchar
*name
)
3496 AdapterDSource
*adapter
= g_new0( AdapterDSource
, 1 );
3497 ADDRESS_OBJECT(adapter
)->type
= ADDR_DATASOURCE
;
3498 ADDRESS_OBJECT_NAME(adapter
) = g_strdup( name
);
3499 adapter
->dataSource
= ds
;
3500 adapter
->subType
= otype
;
3504 void addressbook_ads_set_name( AdapterDSource
*adapter
, gchar
*value
) {
3505 ADDRESS_OBJECT_NAME(adapter
) =
3506 mgu_replace_string( ADDRESS_OBJECT_NAME(adapter
), value
);
3510 * Load tree from address index with the initial data.
3512 static void addressbook_load_tree( void ) {
3513 GtkCTree
*ctree
= GTK_CTREE( addrbook
.ctree
);
3514 GList
*nodeIf
, *nodeDS
;
3515 AdapterInterface
*adapter
;
3516 AddressInterface
*iface
;
3517 AddressTypeControlItem
*atci
;
3518 AddressDataSource
*ds
;
3519 AdapterDSource
*ads
;
3520 GtkCTreeNode
*node
, *newNode
;
3523 nodeIf
= _addressInterfaceList_
;
3525 adapter
= nodeIf
->data
;
3526 node
= adapter
->treeNode
;
3527 iface
= adapter
->interface
;
3528 atci
= adapter
->atci
;
3530 if( iface
->useInterface
) {
3531 /* Load data sources below interface node */
3532 nodeDS
= iface
->listSource
;
3536 name
= addrindex_ds_get_name( ds
);
3537 ads
= addressbook_create_ds_adapter(
3538 ds
, atci
->objectType
, name
);
3539 newNode
= addressbook_add_object(
3540 node
, ADDRESS_OBJECT(ads
) );
3541 nodeDS
= g_list_next( nodeDS
);
3543 gtk_ctree_expand( ctree
, node
);
3546 nodeIf
= g_list_next( nodeIf
);
3551 * Convert the old address book to new format.
3553 static gboolean
addressbook_convert( AddressIndex
*addrIndex
) {
3554 gboolean retVal
= FALSE
;
3555 gboolean errFlag
= TRUE
;
3558 /* Read old address book, performing conversion */
3559 debug_print( "Reading and converting old address book...\n" );
3560 addrindex_set_file_name( addrIndex
, ADDRESSBOOK_OLD_FILE
);
3561 addrindex_read_data( addrIndex
);
3562 if( addrIndex
->retVal
== MGU_NO_FILE
) {
3563 /* We do not have a file - new user */
3564 debug_print( "New user... create new books...\n" );
3565 addrindex_create_new_books( addrIndex
);
3566 if( addrIndex
->retVal
== MGU_SUCCESS
) {
3567 /* Save index file */
3568 addrindex_set_file_name( addrIndex
, ADDRESSBOOK_INDEX_FILE
);
3569 addrindex_save_data( addrIndex
);
3570 if( addrIndex
->retVal
== MGU_SUCCESS
) {
3575 msg
= _( "New user, could not save index file." );
3579 msg
= _( "New user, could not save address book files." );
3583 /* We have an old file */
3584 if( addrIndex
->wasConverted
) {
3585 /* Converted successfully - save address index */
3586 addrindex_set_file_name( addrIndex
, ADDRESSBOOK_INDEX_FILE
);
3587 addrindex_save_data( addrIndex
);
3588 if( addrIndex
->retVal
== MGU_SUCCESS
) {
3589 msg
= _( "Old address book converted successfully." );
3594 msg
= _("Old address book converted,\n"
3595 "could not save new address index file." );
3599 /* File conversion failed - just create new books */
3600 debug_print( "File conversion failed... just create new books...\n" );
3601 addrindex_create_new_books( addrIndex
);
3602 if( addrIndex
->retVal
== MGU_SUCCESS
) {
3604 addrindex_set_file_name( addrIndex
, ADDRESSBOOK_INDEX_FILE
);
3605 addrindex_save_data( addrIndex
);
3606 if( addrIndex
->retVal
== MGU_SUCCESS
) {
3607 msg
= _("Could not convert address book,\n"
3608 "but created empty new address book files." );
3613 msg
= _("Could not convert address book,\n"
3614 "could not save new address index file." );
3618 msg
= _("Could not convert address book\n"
3619 "and could not create new address book files." );
3624 debug_print( "Error\n%s\n", msg
);
3625 alertpanel_full(_("Addressbook conversion error"), msg
,
3626 GTK_STOCK_CLOSE
, NULL
, NULL
, FALSE
,
3627 NULL
, ALERT_ERROR
, G_ALERTDEFAULT
);
3630 debug_print( "Warning\n%s\n", msg
);
3631 alertpanel_full(_("Addressbook conversion error"), msg
,
3632 GTK_STOCK_CLOSE
, NULL
, NULL
, FALSE
,
3633 NULL
, ALERT_WARNING
, G_ALERTDEFAULT
);
3639 void addressbook_read_file( void ) {
3640 AddressIndex
*addrIndex
= NULL
;
3642 debug_print( "Reading address index...\n" );
3643 if( _addressIndex_
) {
3644 debug_print( "address book already read!!!\n" );
3648 addrIndex
= addrindex_create_index();
3649 addrindex_initialize();
3651 /* Use new address book index. */
3652 addrindex_set_file_path( addrIndex
, get_rc_dir() );
3653 addrindex_set_file_name( addrIndex
, ADDRESSBOOK_INDEX_FILE
);
3654 addrindex_read_data( addrIndex
);
3655 if( addrIndex
->retVal
== MGU_NO_FILE
) {
3656 /* Conversion required */
3657 debug_print( "Converting...\n" );
3658 if( addressbook_convert( addrIndex
) ) {
3659 _addressIndex_
= addrIndex
;
3662 else if( addrIndex
->retVal
== MGU_SUCCESS
) {
3663 _addressIndex_
= addrIndex
;
3666 /* Error reading address book */
3667 debug_print( "Could not read address index.\n" );
3668 addrindex_print_index( addrIndex
, stdout
);
3669 alertpanel_full(_("Addressbook Error"),
3670 _("Could not read address index"),
3671 GTK_STOCK_CLOSE
, NULL
, NULL
, FALSE
,
3672 NULL
, ALERT_ERROR
, G_ALERTDEFAULT
);
3674 debug_print( "done.\n" );
3678 * Add object into the address index tree widget.
3679 * Enter: node Parent node.
3680 * obj Object to add.
3681 * Return: Node that was added, or NULL if object not added.
3683 static GtkCTreeNode
*addressbook_add_object(GtkCTreeNode
*node
,
3686 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
3687 GtkCTreeNode
*added
;
3688 AddressObject
*pobj
;
3689 AddressObjectType otype
;
3690 AddressTypeControlItem
*atci
= NULL
;
3692 g_return_val_if_fail(node
!= NULL
, NULL
);
3693 g_return_val_if_fail(obj
!= NULL
, NULL
);
3695 pobj
= gtk_ctree_node_get_row_data(ctree
, node
);
3696 g_return_val_if_fail(pobj
!= NULL
, NULL
);
3698 /* Determine object type to be displayed */
3699 if( obj
->type
== ADDR_DATASOURCE
) {
3700 otype
= ADAPTER_DSOURCE(obj
)->subType
;
3706 /* Handle any special conditions. */
3708 atci
= addrbookctl_lookup( otype
);
3710 if( atci
->showInTree
) {
3711 /* Add object to tree */
3714 added
= gtk_sctree_insert_node( ctree
, node
, NULL
, name
, FOLDER_SPACING
,
3715 atci
->iconXpm
, atci
->maskXpm
, atci
->iconXpmOpen
, atci
->maskXpmOpen
,
3716 atci
->treeLeaf
, atci
->treeExpand
);
3717 gtk_ctree_node_set_row_data_full( ctree
, added
, obj
,
3718 addressbook_free_treenode
);
3722 gtk_sctree_sort_node(ctree
, node
);
3728 * Add group into the address index tree.
3729 * \param node Parent node.
3730 * \param ds Data source.
3731 * \param itemGroup Group to add.
3732 * \return Inserted node.
3734 static GtkCTreeNode
*addressbook_node_add_group(
3735 GtkCTreeNode
*node
, AddressDataSource
*ds
,
3736 ItemGroup
*itemGroup
)
3738 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
3739 GtkCTreeNode
*newNode
;
3740 AdapterGroup
*adapter
;
3741 AddressTypeControlItem
*atci
= NULL
;
3744 if( ds
== NULL
) return NULL
;
3745 if( node
== NULL
|| itemGroup
== NULL
) return NULL
;
3747 name
= &itemGroup
->obj
.name
;
3749 atci
= addrbookctl_lookup( ADDR_ITEM_GROUP
);
3751 adapter
= g_new0( AdapterGroup
, 1 );
3752 ADDRESS_OBJECT_TYPE(adapter
) = ADDR_ITEM_GROUP
;
3753 ADDRESS_OBJECT_NAME(adapter
) = g_strdup( ADDRITEM_NAME(itemGroup
) );
3754 adapter
->itemGroup
= itemGroup
;
3756 newNode
= gtk_sctree_insert_node( ctree
, node
, NULL
, name
, FOLDER_SPACING
,
3757 atci
->iconXpm
, atci
->maskXpm
, atci
->iconXpm
, atci
->maskXpm
,
3758 atci
->treeLeaf
, atci
->treeExpand
);
3759 gtk_ctree_node_set_row_data_full( ctree
, newNode
, adapter
,
3760 addressbook_free_treenode
);
3761 gtk_sctree_sort_node( ctree
, node
);
3766 * Add folder into the address index tree. Only visible folders are loaded into
3767 * the address index tree. Note that the root folder is not inserted into the
3770 * \param node Parent node.
3771 * \param ds Data source.
3772 * \param itemFolder Folder to add.
3773 * \param otype Object type to display.
3774 * \return Inserted node for the folder.
3776 static GtkCTreeNode
*addressbook_node_add_folder(
3777 GtkCTreeNode
*node
, AddressDataSource
*ds
,
3778 ItemFolder
*itemFolder
, AddressObjectType otype
)
3780 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
3781 GtkCTreeNode
*newNode
= NULL
;
3782 AdapterFolder
*adapter
;
3783 AddressTypeControlItem
*atci
= NULL
;
3784 GList
*listItems
= NULL
;
3786 ItemFolder
*rootFolder
;
3788 /* Only visible folders */
3789 if( itemFolder
->isHidden
) return NULL
;
3791 if( ds
== NULL
) return NULL
;
3792 if( node
== NULL
|| itemFolder
== NULL
) return NULL
;
3794 /* Determine object type */
3795 atci
= addrbookctl_lookup( otype
);
3796 if( atci
== NULL
) return NULL
;
3798 rootFolder
= addrindex_ds_get_root_folder( ds
);
3799 if( itemFolder
== rootFolder
) {
3803 adapter
= g_new0( AdapterFolder
, 1 );
3804 ADDRESS_OBJECT_TYPE(adapter
) = ADDR_ITEM_FOLDER
;
3805 ADDRESS_OBJECT_NAME(adapter
) = g_strdup( ADDRITEM_NAME(itemFolder
) );
3806 adapter
->itemFolder
= itemFolder
;
3808 name
= ADDRITEM_NAME(itemFolder
);
3809 newNode
= gtk_sctree_insert_node( ctree
, node
, NULL
, &name
, FOLDER_SPACING
,
3810 atci
->iconXpm
, atci
->maskXpm
, atci
->iconXpm
, atci
->maskXpm
,
3811 atci
->treeLeaf
, atci
->treeExpand
);
3813 gtk_ctree_node_set_row_data_full( ctree
, newNode
, adapter
,
3814 addressbook_free_treenode
);
3818 listItems
= itemFolder
->listFolder
;
3819 while( listItems
) {
3820 ItemFolder
*item
= listItems
->data
;
3821 addressbook_node_add_folder( newNode
, ds
, item
, otype
);
3822 listItems
= g_list_next( listItems
);
3824 listItems
= itemFolder
->listGroup
;
3825 while( listItems
) {
3826 ItemGroup
*item
= listItems
->data
;
3827 addressbook_node_add_group( newNode
, ds
, item
);
3828 listItems
= g_list_next( listItems
);
3830 gtk_sctree_sort_node( ctree
, node
);
3834 void addressbook_export_to_file( void ) {
3835 if( _addressIndex_
) {
3836 /* Save all new address book data */
3837 debug_print( "Saving address books...\n" );
3838 addrindex_save_all_books( _addressIndex_
);
3840 debug_print( "Exporting addressbook to file...\n" );
3841 addrindex_save_data( _addressIndex_
);
3842 if( _addressIndex_
->retVal
!= MGU_SUCCESS
) {
3843 addrindex_print_index( _addressIndex_
, stdout
);
3846 /* Notify address completion of new data */
3847 invalidate_address_completion();
3851 static gboolean
addressbook_entry_key_pressed(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
3853 if (event
&& event
->keyval
== GDK_Return
)
3854 addressbook_lup_clicked(NULL
, NULL
);
3859 * Comparison using cell contents (text in first column). Used for sort
3860 * address index widget.
3862 static gint
addressbook_treenode_compare_func(
3863 GtkCList
*clist
, gconstpointer ptr1
, gconstpointer ptr2
)
3865 GtkCell
*cell1
= ((GtkCListRow
*)ptr1
)->cell
;
3866 GtkCell
*cell2
= ((GtkCListRow
*)ptr2
)->cell
;
3867 gchar
*name1
= NULL
, *name2
= NULL
;
3868 if( cell1
) name1
= cell1
->u
.text
;
3869 if( cell2
) name2
= cell2
->u
.text
;
3870 if( ! name1
) return ( name2
!= NULL
);
3871 if( ! name2
) return -1;
3872 return g_utf8_collate( name1
, name2
);
3875 static void addressbook_new_book_cb( gpointer data
, guint action
, GtkWidget
*widget
) {
3876 AdapterDSource
*ads
;
3877 AdapterInterface
*adapter
;
3878 GtkCTreeNode
*newNode
;
3880 adapter
= addrbookctl_find_interface( ADDR_IF_BOOK
);
3881 if( adapter
== NULL
) return;
3882 ads
= addressbook_edit_book( _addressIndex_
, NULL
);
3884 newNode
= addressbook_add_object( adapter
->treeNode
, ADDRESS_OBJECT(ads
) );
3886 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), newNode
);
3887 addrbook
.treeSelected
= newNode
;
3892 static void addressbook_new_vcard_cb( gpointer data
, guint action
, GtkWidget
*widget
) {
3893 AdapterDSource
*ads
;
3894 AdapterInterface
*adapter
;
3895 GtkCTreeNode
*newNode
;
3897 adapter
= addrbookctl_find_interface( ADDR_IF_VCARD
);
3898 if( adapter
== NULL
) return;
3899 ads
= addressbook_edit_vcard( _addressIndex_
, NULL
);
3901 newNode
= addressbook_add_object( adapter
->treeNode
, ADDRESS_OBJECT(ads
) );
3903 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), newNode
);
3904 addrbook
.treeSelected
= newNode
;
3910 static void addressbook_new_jpilot_cb( gpointer data
, guint action
, GtkWidget
*widget
) {
3911 AdapterDSource
*ads
;
3912 AdapterInterface
*adapter
;
3913 AddressInterface
*iface
;
3914 GtkCTreeNode
*newNode
;
3916 adapter
= addrbookctl_find_interface( ADDR_IF_JPILOT
);
3917 if( adapter
== NULL
) return;
3918 iface
= adapter
->interface
;
3919 if( ! iface
->haveLibrary
) return;
3920 ads
= addressbook_edit_jpilot( _addressIndex_
, NULL
);
3922 newNode
= addressbook_add_object( adapter
->treeNode
, ADDRESS_OBJECT(ads
) );
3924 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), newNode
);
3925 addrbook
.treeSelected
= newNode
;
3932 static void addressbook_new_ldap_cb( gpointer data
, guint action
, GtkWidget
*widget
) {
3933 AdapterDSource
*ads
;
3934 AdapterInterface
*adapter
;
3935 AddressInterface
*iface
;
3936 GtkCTreeNode
*newNode
;
3938 adapter
= addrbookctl_find_interface( ADDR_IF_LDAP
);
3939 if( adapter
== NULL
) return;
3940 iface
= adapter
->interface
;
3941 if( ! iface
->haveLibrary
) return;
3942 ads
= addressbook_edit_ldap( _addressIndex_
, NULL
);
3944 newNode
= addressbook_add_object( adapter
->treeNode
, ADDRESS_OBJECT(ads
) );
3946 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), newNode
);
3947 addrbook
.treeSelected
= newNode
;
3954 * Display address search status message.
3955 * \param queryType Query type.
3956 * \param status Status/Error code.
3958 static void addressbook_search_message( gint queryType
, gint sts
) {
3960 *addressbook_msgbuf
= '\0';
3962 if( sts
!= MGU_SUCCESS
) {
3963 if( queryType
== ADDRQUERY_LDAP
) {
3965 desc
= addressbook_err2string( _lutErrorsLDAP_
, sts
);
3970 g_snprintf( addressbook_msgbuf
,
3971 sizeof(addressbook_msgbuf
), "%s", desc
);
3972 addressbook_status_show( addressbook_msgbuf
);
3975 addressbook_status_show( "" );
3980 * Refresh addressbook by forcing refresh of current selected object in
3983 static void addressbook_refresh_current( void ) {
3987 ctree
= GTK_CTREE(addrbook
.ctree
);
3988 obj
= gtk_ctree_node_get_row_data( ctree
, addrbook
.treeSelected
);
3989 if( obj
== NULL
) return;
3990 addressbook_set_clist( obj
, TRUE
);
3994 * Message that is displayed whilst a query is executing in a background
3997 static gchar
*_tempMessage_
= N_( "Busy searching..." );
4000 * Address search idle function. This function is called during UI idle time
4001 * while a search is in progress.
4003 * \param data Idler data.
4005 static void addressbook_search_idle( gpointer data
) {
4009 queryID = GPOINTER_TO_INT( data );
4010 printf( "addressbook_ldap_idle... queryID=%d\n", queryID );
4015 * Search completion callback function. This removes the query from the idle
4018 * \param queryID Query ID of search request.
4020 void addressbook_clear_idler( gint queryID
) {
4023 /* Remove idler function */
4024 /* printf( "addressbook_clear_idler::%d::\n", queryID ); */
4025 ptrQID
= GINT_TO_POINTER( queryID
);
4027 g_idle_remove_by_data( ptrQID
);
4032 * Search completion callback function. This removes the query from the idle
4035 * \param sender Sender of query.
4036 * \param queryID Query ID of search request.
4037 * \param status Search status.
4038 * \param data Query data.
4040 static void addressbook_search_callback_end(
4041 gpointer sender
, gint queryID
, gint status
, gpointer data
)
4045 AddrQueryObject
*aqo
;
4047 /* Remove idler function */
4048 ptrQID
= GINT_TO_POINTER( queryID
);
4050 g_idle_remove_by_data( ptrQID
);
4053 /* Refresh addressbook contents */
4054 addressbook_refresh_current();
4055 req
= qrymgr_find_request( queryID
);
4057 aqo
= ( AddrQueryObject
* ) req
->queryList
->data
;
4058 addressbook_search_message( aqo
->queryType
, status
);
4061 /* Stop the search */
4062 addrindex_stop_search( queryID
);
4066 * Label (a format string) that is used to name each folder.
4068 static gchar
*_queryFolderLabel_
= N_( "Search '%s'" );
4073 * \param ds Data source to search.
4074 * \param searchTerm String to lookup.
4075 * \param pNode Parent data source node.
4077 static void addressbook_perform_search(
4078 AddressDataSource
*ds
, gchar
*searchTerm
,
4079 GtkCTreeNode
*pNode
)
4081 AddrBookBase
*adbase
;
4082 AddressCache
*cache
;
4085 GtkCTreeNode
*nNode
;
4089 AddressObjectType aoType
= ADDR_NONE
;
4092 if( *searchTerm
== '\0' || strlen( searchTerm
) < 1 ) return;
4094 if( ds
->type
== ADDR_IF_LDAP
) {
4096 aoType
= ADDR_LDAP_QUERY
;
4103 /* Get reference to address cache */
4104 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
4105 cache
= adbase
->addressCache
;
4107 /* Create a folder for the search results */
4108 folder
= addrcache_add_new_folder( cache
, NULL
);
4109 name
= g_strdup_printf( _queryFolderLabel_
, searchTerm
);
4110 addritem_folder_set_name( folder
, name
);
4111 addritem_folder_set_remarks( folder
, "" );
4114 /* Now let's see the folder */
4115 ctree
= GTK_CTREE(addrbook
.ctree
);
4116 nNode
= addressbook_node_add_folder( pNode
, ds
, folder
, aoType
);
4117 gtk_ctree_expand( ctree
, pNode
);
4119 gtk_sctree_select( GTK_SCTREE(ctree
), nNode
);
4120 addrbook
.treeSelected
= nNode
;
4123 /* Setup the search */
4124 queryID
= addrindex_setup_explicit_search(
4125 ds
, searchTerm
, folder
, addressbook_search_callback_end
, NULL
);
4126 if( queryID
== 0 ) return;
4128 /* Set up idler function */
4129 idleID
= g_idle_add(
4130 ( GtkFunction
) addressbook_search_idle
,
4131 GINT_TO_POINTER( queryID
) );
4133 /* Start search, sit back and wait for something to happen */
4134 addrindex_start_search( queryID
);
4136 addressbook_status_show( _tempMessage_
);
4140 * Lookup button handler. Address search is only performed against
4141 * address interfaces for external queries.
4143 * \param button Lookup button widget.
4144 * \param data Data object.
4146 static void addressbook_lup_clicked( GtkButton
*button
, gpointer data
) {
4149 AddressDataSource
*ds
;
4150 AddressInterface
*iface
;
4152 GtkCTreeNode
*node
, *parentNode
;
4154 node
= addrbook
.treeSelected
;
4155 if( ! node
) return;
4156 if( GTK_CTREE_ROW(node
)->level
== 1 ) return;
4158 ctree
= GTK_CTREE(addrbook
.ctree
);
4159 obj
= gtk_ctree_node_get_row_data( ctree
, node
);
4160 if( obj
== NULL
) return;
4162 ds
= addressbook_find_datasource( node
);
4163 if( ds
== NULL
) return;
4165 /* We must have a datasource that is an external interface */
4166 iface
= ds
->interface
;
4167 if( ! iface
->haveLibrary
) return;
4168 if( ! iface
->externalQuery
) return;
4171 gtk_editable_get_chars( GTK_EDITABLE(addrbook
.entry
), 0, -1 );
4172 g_strchomp( searchTerm
);
4174 if( obj
->type
== ADDR_ITEM_FOLDER
) {
4175 parentNode
= GTK_CTREE_ROW(node
)->parent
;
4180 addressbook_perform_search( ds
, searchTerm
, parentNode
);
4182 gtk_widget_grab_focus( addrbook
.entry
);
4184 g_free( searchTerm
);
4187 static void addressbook_close_clicked( GtkButton
*button
, gpointer data
) {
4188 addressbook_close();
4193 * Browse address entry for highlighted entry.
4195 static void addressbook_browse_entry_cb(void)
4197 GtkCTree
*clist
= GTK_CTREE(addrbook
.clist
);
4199 AddressDataSource
*ds
;
4200 AddressInterface
*iface
;
4204 if(addrbook
.listSelected
== NULL
)
4207 obj
= gtk_ctree_node_get_row_data(clist
, addrbook
.listSelected
);
4211 ds
= addressbook_find_datasource(GTK_CTREE_NODE(addrbook
.treeSelected
));
4215 iface
= ds
->interface
;
4216 if(! iface
->haveLibrary
)
4220 if (obj
->type
== ADDR_ITEM_EMAIL
) {
4221 email
= ( ItemEMail
* ) obj
;
4225 person
= (ItemPerson
*) ADDRITEM_PARENT(email
);
4227 else if (obj
->type
== ADDR_ITEM_PERSON
) {
4228 person
= (ItemPerson
*) obj
;
4235 if( iface
->type
== ADDR_IF_LDAP
) {
4236 browseldap_entry(ds
, person
->externalID
);
4241 /* **********************************************************************
4242 * Build lookup tables.
4243 * ***********************************************************************
4247 * Remap object types.
4248 * Enter: abType AddressObjectType (used in tree node).
4249 * Return: ItemObjectType (used in address cache data).
4251 ItemObjectType
addressbook_type2item( AddressObjectType abType
) {
4252 ItemObjectType ioType
;
4255 case ADDR_ITEM_PERSON
: ioType
= ITEMTYPE_PERSON
; break;
4256 case ADDR_ITEM_EMAIL
: ioType
= ITEMTYPE_EMAIL
; break;
4257 case ADDR_ITEM_FOLDER
: ioType
= ITEMTYPE_FOLDER
; break;
4258 case ADDR_ITEM_GROUP
: ioType
= ITEMTYPE_GROUP
; break;
4259 case ADDR_DATASOURCE
: ioType
= ITEMTYPE_DATASOURCE
; break;
4260 default: ioType
= ITEMTYPE_NONE
; break;
4266 * Build table that controls the rendering of object types.
4268 void addrbookctl_build_map( GtkWidget
*window
) {
4269 AddressTypeControlItem
*atci
;
4272 stock_pixmap_gdk(window
, STOCK_PIXMAP_DIR_CLOSE
, &folderxpm
, &folderxpmmask
);
4273 stock_pixmap_gdk(window
, STOCK_PIXMAP_DIR_OPEN
, &folderopenxpm
, &folderopenxpmmask
);
4274 stock_pixmap_gdk(window
, STOCK_PIXMAP_GROUP
, &groupxpm
, &groupxpmmask
);
4275 stock_pixmap_gdk(window
, STOCK_PIXMAP_VCARD
, &vcardxpm
, &vcardxpmmask
);
4276 stock_pixmap_gdk(window
, STOCK_PIXMAP_BOOK
, &bookxpm
, &bookxpmmask
);
4277 stock_pixmap_gdk(window
, STOCK_PIXMAP_ADDRESS
, &addressxpm
, &addressxpmmask
);
4278 stock_pixmap_gdk(window
, STOCK_PIXMAP_JPILOT
, &jpilotxpm
, &jpilotxpmmask
);
4279 stock_pixmap_gdk(window
, STOCK_PIXMAP_CATEGORY
, &categoryxpm
, &categoryxpmmask
);
4280 stock_pixmap_gdk(window
, STOCK_PIXMAP_LDAP
, &ldapxpm
, &ldapxpmmask
);
4281 stock_pixmap_gdk(window
, STOCK_PIXMAP_ADDRESS_SEARCH
, &addrsearchxpm
, &addrsearchxpmmask
);
4283 _addressBookTypeHash_
= g_hash_table_new( g_int_hash
, g_int_equal
);
4284 _addressBookTypeList_
= NULL
;
4287 atci
= g_new0( AddressTypeControlItem
, 1 );
4288 atci
->objectType
= ADDR_INTERFACE
;
4289 atci
->interfaceType
= ADDR_IF_NONE
;
4290 atci
->showInTree
= TRUE
;
4291 atci
->treeExpand
= TRUE
;
4292 atci
->treeLeaf
= FALSE
;
4293 atci
->displayName
= _( "Interface" );
4294 atci
->iconXpm
= folderxpm
;
4295 atci
->maskXpm
= folderxpmmask
;
4296 atci
->iconXpmOpen
= folderopenxpm
;
4297 atci
->maskXpmOpen
= folderopenxpmmask
;
4298 atci
->menuCommand
= NULL
;
4299 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4300 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4303 atci
= g_new0( AddressTypeControlItem
, 1 );
4304 atci
->objectType
= ADDR_BOOK
;
4305 atci
->interfaceType
= ADDR_IF_BOOK
;
4306 atci
->showInTree
= TRUE
;
4307 atci
->treeExpand
= TRUE
;
4308 atci
->treeLeaf
= FALSE
;
4309 atci
->displayName
= _( "Address Book" );
4310 atci
->iconXpm
= bookxpm
;
4311 atci
->maskXpm
= bookxpmmask
;
4312 atci
->iconXpmOpen
= bookxpm
;
4313 atci
->maskXpmOpen
= bookxpmmask
;
4314 atci
->menuCommand
= "/Book/New Book";
4315 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4316 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4319 atci
= g_new0( AddressTypeControlItem
, 1 );
4320 atci
->objectType
= ADDR_ITEM_PERSON
;
4321 atci
->interfaceType
= ADDR_IF_NONE
;
4322 atci
->showInTree
= FALSE
;
4323 atci
->treeExpand
= FALSE
;
4324 atci
->treeLeaf
= FALSE
;
4325 atci
->displayName
= _( "Person" );
4326 atci
->iconXpm
= NULL
;
4327 atci
->maskXpm
= NULL
;
4328 atci
->iconXpmOpen
= NULL
;
4329 atci
->maskXpmOpen
= NULL
;
4330 atci
->menuCommand
= NULL
;
4331 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4332 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4335 atci
= g_new0( AddressTypeControlItem
, 1 );
4336 atci
->objectType
= ADDR_ITEM_EMAIL
;
4337 atci
->interfaceType
= ADDR_IF_NONE
;
4338 atci
->showInTree
= FALSE
;
4339 atci
->treeExpand
= FALSE
;
4340 atci
->treeLeaf
= TRUE
;
4341 atci
->displayName
= _( "EMail Address" );
4342 atci
->iconXpm
= addressxpm
;
4343 atci
->maskXpm
= addressxpmmask
;
4344 atci
->iconXpmOpen
= addressxpm
;
4345 atci
->maskXpmOpen
= addressxpmmask
;
4346 atci
->menuCommand
= NULL
;
4347 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4348 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4351 atci
= g_new0( AddressTypeControlItem
, 1 );
4352 atci
->objectType
= ADDR_ITEM_GROUP
;
4353 atci
->interfaceType
= ADDR_IF_BOOK
;
4354 atci
->showInTree
= TRUE
;
4355 atci
->treeExpand
= FALSE
;
4356 atci
->treeLeaf
= FALSE
;
4357 atci
->displayName
= _( "Group" );
4358 atci
->iconXpm
= groupxpm
;
4359 atci
->maskXpm
= groupxpmmask
;
4360 atci
->iconXpmOpen
= groupxpm
;
4361 atci
->maskXpmOpen
= groupxpmmask
;
4362 atci
->menuCommand
= NULL
;
4363 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4364 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4367 atci
= g_new0( AddressTypeControlItem
, 1 );
4368 atci
->objectType
= ADDR_ITEM_FOLDER
;
4369 atci
->interfaceType
= ADDR_IF_BOOK
;
4370 atci
->showInTree
= TRUE
;
4371 atci
->treeExpand
= FALSE
;
4372 atci
->treeLeaf
= FALSE
;
4373 atci
->displayName
= _( "Folder" );
4374 atci
->iconXpm
= folderxpm
;
4375 atci
->maskXpm
= folderxpmmask
;
4376 atci
->iconXpmOpen
= folderopenxpm
;
4377 atci
->maskXpmOpen
= folderopenxpmmask
;
4378 atci
->menuCommand
= NULL
;
4379 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4380 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4383 atci
= g_new0( AddressTypeControlItem
, 1 );
4384 atci
->objectType
= ADDR_VCARD
;
4385 atci
->interfaceType
= ADDR_IF_VCARD
;
4386 atci
->showInTree
= TRUE
;
4387 atci
->treeExpand
= TRUE
;
4388 atci
->treeLeaf
= TRUE
;
4389 atci
->displayName
= _( "vCard" );
4390 atci
->iconXpm
= vcardxpm
;
4391 atci
->maskXpm
= vcardxpmmask
;
4392 atci
->iconXpmOpen
= vcardxpm
;
4393 atci
->maskXpmOpen
= vcardxpmmask
;
4394 atci
->menuCommand
= "/Book/New vCard";
4395 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4396 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4399 atci
= g_new0( AddressTypeControlItem
, 1 );
4400 atci
->objectType
= ADDR_JPILOT
;
4401 atci
->interfaceType
= ADDR_IF_JPILOT
;
4402 atci
->showInTree
= TRUE
;
4403 atci
->treeExpand
= TRUE
;
4404 atci
->treeLeaf
= FALSE
;
4405 atci
->displayName
= _( "JPilot" );
4406 atci
->iconXpm
= jpilotxpm
;
4407 atci
->maskXpm
= jpilotxpmmask
;
4408 atci
->iconXpmOpen
= jpilotxpm
;
4409 atci
->maskXpmOpen
= jpilotxpmmask
;
4410 atci
->menuCommand
= "/Book/New JPilot";
4411 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4412 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4415 atci
= g_new0( AddressTypeControlItem
, 1 );
4416 atci
->objectType
= ADDR_CATEGORY
;
4417 atci
->interfaceType
= ADDR_IF_JPILOT
;
4418 atci
->showInTree
= TRUE
;
4419 atci
->treeExpand
= TRUE
;
4420 atci
->treeLeaf
= TRUE
;
4421 atci
->displayName
= _( "JPilot" );
4422 atci
->iconXpm
= categoryxpm
;
4423 atci
->maskXpm
= categoryxpmmask
;
4424 atci
->iconXpmOpen
= categoryxpm
;
4425 atci
->maskXpmOpen
= categoryxpmmask
;
4426 atci
->menuCommand
= NULL
;
4427 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4428 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4431 atci
= g_new0( AddressTypeControlItem
, 1 );
4432 atci
->objectType
= ADDR_LDAP
;
4433 atci
->interfaceType
= ADDR_IF_LDAP
;
4434 atci
->showInTree
= TRUE
;
4435 atci
->treeExpand
= TRUE
;
4436 atci
->treeLeaf
= FALSE
;
4437 atci
->displayName
= _( "LDAP servers" );
4438 atci
->iconXpm
= ldapxpm
;
4439 atci
->maskXpm
= ldapxpmmask
;
4440 atci
->iconXpmOpen
= ldapxpm
;
4441 atci
->maskXpmOpen
= ldapxpmmask
;
4442 atci
->menuCommand
= "/Book/New LDAP Server";
4443 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4444 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4447 atci
= g_new0( AddressTypeControlItem
, 1 );
4448 atci
->objectType
= ADDR_LDAP_QUERY
;
4449 atci
->interfaceType
= ADDR_IF_LDAP
;
4450 atci
->showInTree
= TRUE
;
4451 atci
->treeExpand
= FALSE
;
4452 atci
->treeLeaf
= TRUE
;
4453 atci
->displayName
= _( "LDAP Query" );
4454 atci
->iconXpm
= addrsearchxpm
;
4455 atci
->maskXpm
= addrsearchxpmmask
;
4456 atci
->iconXpmOpen
= addrsearchxpm
;
4457 atci
->maskXpmOpen
= addrsearchxpmmask
;
4458 atci
->menuCommand
= NULL
;
4459 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4460 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4465 * Search for specified object type.
4467 AddressTypeControlItem
*addrbookctl_lookup( gint ot
) {
4469 return ( AddressTypeControlItem
* ) g_hash_table_lookup( _addressBookTypeHash_
, &objType
);
4473 * Search for specified interface type.
4475 AddressTypeControlItem
*addrbookctl_lookup_iface( AddressIfType ifType
) {
4476 GList
*node
= _addressBookTypeList_
;
4478 AddressTypeControlItem
*atci
= node
->data
;
4479 if( atci
->interfaceType
== ifType
) return atci
;
4480 node
= g_list_next( node
);
4485 static void addrbookctl_free_address( AddressObject
*obj
) {
4486 g_free( obj
->name
);
4487 obj
->type
= ADDR_NONE
;
4491 static void addrbookctl_free_interface( AdapterInterface
*adapter
) {
4492 addrbookctl_free_address( ADDRESS_OBJECT(adapter
) );
4493 adapter
->interface
= NULL
;
4494 adapter
->interfaceType
= ADDR_IF_NONE
;
4495 adapter
->atci
= NULL
;
4496 adapter
->enabled
= FALSE
;
4497 adapter
->haveLibrary
= FALSE
;
4498 adapter
->treeNode
= NULL
;
4502 static void addrbookctl_free_datasource( AdapterDSource
*adapter
) {
4503 addrbookctl_free_address( ADDRESS_OBJECT(adapter
) );
4504 adapter
->dataSource
= NULL
;
4505 adapter
->subType
= ADDR_NONE
;
4509 static void addrbookctl_free_folder( AdapterFolder
*adapter
) {
4510 addrbookctl_free_address( ADDRESS_OBJECT(adapter
) );
4511 adapter
->itemFolder
= NULL
;
4515 static void addrbookctl_free_group( AdapterGroup
*adapter
) {
4516 addrbookctl_free_address( ADDRESS_OBJECT(adapter
) );
4517 adapter
->itemGroup
= NULL
;
4522 * Build GUI interface list.
4524 void addrbookctl_build_iflist( void ) {
4525 AddressTypeControlItem
*atci
;
4526 AdapterInterface
*adapter
;
4529 if( _addressIndex_
== NULL
) {
4530 _addressIndex_
= addrindex_create_index();
4531 if( _clipBoard_
== NULL
) {
4532 _clipBoard_
= addrclip_create();
4534 addrclip_set_index( _clipBoard_
, _addressIndex_
);
4536 _addressInterfaceList_
= NULL
;
4537 list
= addrindex_get_interface_list( _addressIndex_
);
4539 AddressInterface
*interface
= list
->data
;
4540 atci
= addrbookctl_lookup_iface( interface
->type
);
4542 adapter
= g_new0( AdapterInterface
, 1 );
4543 adapter
->interfaceType
= interface
->type
;
4544 adapter
->atci
= atci
;
4545 adapter
->interface
= interface
;
4546 adapter
->treeNode
= NULL
;
4547 adapter
->enabled
= TRUE
;
4548 adapter
->haveLibrary
= interface
->haveLibrary
;
4549 ADDRESS_OBJECT(adapter
)->type
= ADDR_INTERFACE
;
4550 ADDRESS_OBJECT_NAME(adapter
) = g_strdup( atci
->displayName
);
4551 _addressInterfaceList_
=
4552 g_list_append( _addressInterfaceList_
, adapter
);
4554 list
= g_list_next( list
);
4559 * Find GUI interface type specified interface type.
4560 * \param ifType Interface type.
4561 * \return Interface item, or NULL if not found.
4563 AdapterInterface
*addrbookctl_find_interface( AddressIfType ifType
) {
4564 GList
*node
= _addressInterfaceList_
;
4566 AdapterInterface
*adapter
= node
->data
;
4567 if( adapter
->interfaceType
== ifType
) return adapter
;
4568 node
= g_list_next( node
);
4574 * Build interface list selection.
4576 void addrbookctl_build_ifselect( void ) {
4577 GList
*newList
= NULL
;
4582 gchar
*endptr
= NULL
;
4584 AdapterInterface
*adapter
;
4586 selectStr
= g_strdup( ADDRESSBOOK_IFACE_SELECTION
);
4589 splitStr
= g_strsplit( selectStr
, ",", -1 );
4590 for( i
= 0; i
< ADDRESSBOOK_MAX_IFACE
; i
++ ) {
4592 /* printf( "%d : %s\n", i, splitStr[i] ); */
4593 ifType
= strtol( splitStr
[i
], &endptr
, 10 );
4596 if( strcmp( endptr
, "/n" ) == 0 ) {
4600 /* printf( "\t%d : %s\n", ifType, enabled ? "yes" : "no" ); */
4601 adapter
= addrbookctl_find_interface( ifType
);
4603 newList
= g_list_append( newList
, adapter
);
4610 /* printf( "i=%d\n", i ); */
4611 g_strfreev( splitStr
);
4612 g_free( selectStr
);
4614 /* Replace existing list */
4615 mgu_clear_list( _addressIFaceSelection_
);
4616 g_list_free( _addressIFaceSelection_
);
4617 _addressIFaceSelection_
= newList
;
4621 /* ***********************************************************************
4622 * Add sender to address book.
4623 * ***********************************************************************
4627 * This function is used by the Add sender to address book function.
4629 gboolean
addressbook_add_contact(
4630 const gchar
*name
, const gchar
*address
, const gchar
*remarks
)
4632 debug_print( "addressbook_add_contact: name/address: %s - %s\n", name
, address
);
4633 if( addressadd_selection( _addressIndex_
, name
, address
, remarks
) ) {
4634 debug_print( "addressbook_add_contact - added\n" );
4635 addressbook_refresh();
4640 /* ***********************************************************************
4641 * Book/folder selection.
4642 * ***********************************************************************
4646 * This function is used by the matcher dialog to select a book/folder.
4648 gboolean
addressbook_folder_selection( gchar
**folderpath
)
4650 AddressBookFile
*book
= NULL
;
4651 ItemFolder
*folder
= NULL
;
4654 g_return_val_if_fail( folderpath
!= NULL
, FALSE
);
4658 if ( addressbook_foldersel_selection( _addressIndex_
, &book
, &folder
, path
)
4660 if ( folder
!= NULL
) {
4662 gchar
*oldtmp
= NULL
;
4663 AddrItemObject
*obj
= NULL
;
4665 /* walk thru folder->parent to build the full folder path */
4666 /* TODO: wwp: optimize this */
4668 tmp
= g_strdup(obj
->uid
);
4669 while ( obj
->parent
) {
4671 if ( obj
->name
!= NULL
) {
4672 oldtmp
= g_strdup(tmp
);
4674 tmp
= g_strdup_printf("%s/%s", obj
->uid
, oldtmp
);
4678 *folderpath
= g_strdup_printf("%s/%s", book
->fileName
, tmp
);
4681 *folderpath
= g_strdup_printf("%s", book
->fileName
);
4683 debug_print( "addressbook_foldersel: %s\n", *folderpath
);
4684 return (*folderpath
!= NULL
);
4689 /* ***********************************************************************
4690 * Book/folder checking.
4691 * ***********************************************************************
4694 static FolderInfo
*addressbook_peek_subfolder_exists_create_folderinfo( AddressBookFile
*abf
, ItemFolder
*folder
)
4696 FolderInfo
*fi
= g_new0( FolderInfo
, 1 );
4698 fi
->folder
= folder
;
4702 static void addressbook_peek_subfolder_exists_load_folder( ItemFolder
*parentFolder
,
4703 FolderInfo
*fiParent
, FolderPathMatch
*match
)
4709 FolderPathMatch
*nextmatch
= NULL
;
4711 list
= parentFolder
->listFolder
;
4713 folder
= list
->data
;
4714 fName
= g_strdup( ADDRITEM_NAME(folder
) );
4716 /* match folder name, match pointer will be set to NULL if next recursive call
4717 doesn't need to match subfolder name */
4718 if ( match
!= NULL
&&
4719 match
->matched
== FALSE
) {
4720 if ( strcmp(match
->folder_path
[match
->index
], folder
->obj
.uid
) == 0 ) {
4721 /* folder name matches, prepare next subfolder match */
4722 debug_print("matched folder name '%s'\n", fName
);
4724 if ( match
->folder_path
[match
->index
] == NULL
) {
4725 /* we've matched all elements */
4726 match
->matched
= TRUE
;
4727 match
->folder
= folder
;
4728 debug_print("book/folder path matched!\n");
4730 /* keep on matching */
4738 fi
= addressbook_peek_subfolder_exists_create_folderinfo( fiParent
->book
, folder
);
4739 addressbook_peek_subfolder_exists_load_folder( folder
, fi
, nextmatch
);
4740 list
= g_list_next( list
);
4745 * This function is used by to check if a matcher book/folder path corresponds to an
4746 existing addressbook book/folder ("" or "Any" are considered as valid, NULL invalid).
4749 gboolean
addressbook_peek_folder_exists( gchar
*folderpath
,
4750 AddressDataSource
**book
,
4751 ItemFolder
**folder
)
4753 AddressDataSource
*ds
;
4754 GList
*list
, *nodeDS
;
4755 ItemFolder
*rootFolder
;
4756 AddressBookFile
*abf
;
4758 FolderPathMatch folder_path_match
= { NULL
, FALSE
, 0, NULL
, NULL
};
4759 FolderPathMatch
*nextmatch
;
4766 if ( folderpath
== NULL
)
4769 if ( strcasecmp(folderpath
, _("Any")) == 0 || *folderpath
== '\0' )
4772 /* split the folder path we've received, we'll try to match this path, subpath by
4773 subpath against the book/folder structure in order */
4774 folder_path_match
.folder_path
= g_strsplit( folderpath
, "/", 256 );
4776 list
= addrindex_get_interface_list( _addressIndex_
);
4778 AddressInterface
*interface
= list
->data
;
4779 if ( interface
->type
== ADDR_IF_BOOK
) {
4780 nodeDS
= interface
->listSource
;
4784 /* Read address book */
4785 if( ! addrindex_ds_get_read_flag( ds
) ) {
4786 addrindex_ds_read_data( ds
);
4789 /* Add node for address book */
4790 abf
= ds
->rawDataSource
;
4792 /* try to match subfolders if this book is the right book
4793 (and if there's smth to match, and not yet matched) */
4795 if ( folder_path_match
.folder_path
!= NULL
&&
4796 folder_path_match
.matched
== FALSE
&&
4797 strcmp(folder_path_match
.folder_path
[0], abf
->fileName
) == 0 ) {
4798 debug_print("matched book name '%s'\n", abf
->fileName
);
4799 folder_path_match
.index
= 1;
4800 if ( folder_path_match
.folder_path
[folder_path_match
.index
] == NULL
) {
4801 /* we've matched all elements */
4802 folder_path_match
.matched
= TRUE
;
4803 folder_path_match
.book
= ds
;
4804 debug_print("book path matched!\n");
4806 /* keep on matching */
4807 nextmatch
= &folder_path_match
;
4811 fi
= addressbook_peek_subfolder_exists_create_folderinfo( abf
, NULL
);
4813 rootFolder
= addrindex_ds_get_root_folder( ds
);
4814 addressbook_peek_subfolder_exists_load_folder( rootFolder
, fi
, nextmatch
);
4816 nodeDS
= g_list_next( nodeDS
);
4819 list
= g_list_next( list
);
4822 g_strfreev( folder_path_match
.folder_path
);
4825 *book
= folder_path_match
.book
;
4827 *folder
= folder_path_match
.folder
;
4828 return folder_path_match
.matched
;
4832 /* **********************************************************************
4834 * ***********************************************************************
4840 static void addressbook_import_ldif_cb( void ) {
4841 AddressDataSource
*ds
= NULL
;
4842 AdapterDSource
*ads
= NULL
;
4843 AddressBookFile
*abf
= NULL
;
4844 AdapterInterface
*adapter
;
4845 GtkCTreeNode
*newNode
;
4847 adapter
= addrbookctl_find_interface( ADDR_IF_BOOK
);
4849 if( adapter
->treeNode
) {
4850 abf
= addressbook_imp_ldif( _addressIndex_
);
4852 ds
= addrindex_index_add_datasource(
4853 _addressIndex_
, ADDR_IF_BOOK
, abf
);
4854 ads
= addressbook_create_ds_adapter(
4855 ds
, ADDR_BOOK
, NULL
);
4856 addressbook_ads_set_name(
4857 ads
, addrbook_get_name( abf
) );
4858 newNode
= addressbook_add_object(
4860 ADDRESS_OBJECT(ads
) );
4862 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
),
4864 addrbook
.treeSelected
= newNode
;
4867 /* Notify address completion */
4868 invalidate_address_completion();
4877 static void addressbook_import_mutt_cb( void ) {
4878 AddressDataSource
*ds
= NULL
;
4879 AdapterDSource
*ads
= NULL
;
4880 AddressBookFile
*abf
= NULL
;
4881 AdapterInterface
*adapter
;
4882 GtkCTreeNode
*newNode
;
4884 adapter
= addrbookctl_find_interface( ADDR_IF_BOOK
);
4886 if( adapter
->treeNode
) {
4887 abf
= addressbook_imp_mutt( _addressIndex_
);
4889 ds
= addrindex_index_add_datasource(
4890 _addressIndex_
, ADDR_IF_BOOK
, abf
);
4891 ads
= addressbook_create_ds_adapter(
4892 ds
, ADDR_BOOK
, NULL
);
4893 addressbook_ads_set_name(
4894 ads
, addrbook_get_name( abf
) );
4895 newNode
= addressbook_add_object(
4897 ADDRESS_OBJECT(ads
) );
4899 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
),
4901 addrbook
.treeSelected
= newNode
;
4904 /* Notify address completion */
4905 invalidate_address_completion();
4914 static void addressbook_import_pine_cb( void ) {
4915 AddressDataSource
*ds
= NULL
;
4916 AdapterDSource
*ads
= NULL
;
4917 AddressBookFile
*abf
= NULL
;
4918 AdapterInterface
*adapter
;
4919 GtkCTreeNode
*newNode
;
4921 adapter
= addrbookctl_find_interface( ADDR_IF_BOOK
);
4923 if( adapter
->treeNode
) {
4924 abf
= addressbook_imp_pine( _addressIndex_
);
4926 ds
= addrindex_index_add_datasource(
4927 _addressIndex_
, ADDR_IF_BOOK
, abf
);
4928 ads
= addressbook_create_ds_adapter(
4929 ds
, ADDR_BOOK
, NULL
);
4930 addressbook_ads_set_name(
4931 ads
, addrbook_get_name( abf
) );
4932 newNode
= addressbook_add_object(
4934 ADDRESS_OBJECT(ads
) );
4936 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
),
4938 addrbook
.treeSelected
= newNode
;
4941 /* Notify address completion */
4942 invalidate_address_completion();
4949 * Harvest addresses.
4950 * \param folderItem Folder to import.
4951 * \param sourceInd Source indicator: FALSE - Folder, TRUE - Messages.
4952 * \param msgList List of message numbers, or NULL to process folder.
4954 void addressbook_harvest(
4955 FolderItem
*folderItem
, gboolean sourceInd
, GList
*msgList
)
4957 AddressDataSource
*ds
= NULL
;
4958 AdapterDSource
*ads
= NULL
;
4959 AddressBookFile
*abf
= NULL
;
4960 AdapterInterface
*adapter
;
4961 GtkCTreeNode
*newNode
;
4963 abf
= addrgather_dlg_execute(
4964 folderItem
, _addressIndex_
, sourceInd
, msgList
);
4966 ds
= addrindex_index_add_datasource(
4967 _addressIndex_
, ADDR_IF_BOOK
, abf
);
4969 adapter
= addrbookctl_find_interface( ADDR_IF_BOOK
);
4971 if( adapter
->treeNode
) {
4972 ads
= addressbook_create_ds_adapter(
4973 ds
, ADDR_BOOK
, addrbook_get_name( abf
) );
4974 newNode
= addressbook_add_object(
4976 ADDRESS_OBJECT(ads
) );
4980 /* Notify address completion */
4981 invalidate_address_completion();
4988 static void addressbook_export_html_cb( void ) {
4989 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
4991 AddressDataSource
*ds
= NULL
;
4992 AddrBookBase
*adbase
;
4993 AddressCache
*cache
;
4994 GtkCTreeNode
*node
= NULL
;
4996 if( ! addrbook
.treeSelected
) return;
4997 node
= addrbook
.treeSelected
;
4998 if( GTK_CTREE_ROW(node
)->level
== 1 ) return;
4999 obj
= gtk_ctree_node_get_row_data( ctree
, node
);
5000 if( obj
== NULL
) return;
5002 ds
= addressbook_find_datasource( node
);
5003 if( ds
== NULL
) return;
5004 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
5005 cache
= adbase
->addressCache
;
5006 addressbook_exp_html( cache
);
5012 static void addressbook_export_ldif_cb( void ) {
5013 GtkCTree
*ctree
= GTK_CTREE(addrbook
.ctree
);
5015 AddressDataSource
*ds
= NULL
;
5016 AddrBookBase
*adbase
;
5017 AddressCache
*cache
;
5018 GtkCTreeNode
*node
= NULL
;
5020 if( ! addrbook
.treeSelected
) return;
5021 node
= addrbook
.treeSelected
;
5022 if( GTK_CTREE_ROW(node
)->level
== 1 ) return;
5023 obj
= gtk_ctree_node_get_row_data( ctree
, node
);
5024 if( obj
== NULL
) return;
5026 ds
= addressbook_find_datasource( node
);
5027 if( ds
== NULL
) return;
5028 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
5029 cache
= adbase
->addressCache
;
5030 addressbook_exp_ldif( cache
);
5033 static void addressbook_start_drag(GtkWidget
*widget
, gint button
,
5037 GdkDragContext
*context
;
5038 if (addressbook_target_list
== NULL
)
5039 addressbook_target_list
= gtk_target_list_new(
5040 addressbook_drag_types
, 1);
5041 context
= gtk_drag_begin(widget
, addressbook_target_list
,
5042 GDK_ACTION_MOVE
|GDK_ACTION_COPY
|GDK_ACTION_DEFAULT
, button
, event
);
5043 gtk_drag_set_icon_default(context
);
5046 static void addressbook_drag_data_get(GtkWidget
*widget
,
5047 GdkDragContext
*drag_context
,
5048 GtkSelectionData
*selection_data
,
5053 AddrItemObject
*aio
= NULL
;
5054 AddressObject
*pobj
= NULL
;
5055 AdapterDSource
*ads
= NULL
;
5056 AddressDataSource
*ds
= NULL
;
5059 pobj
= gtk_ctree_node_get_row_data( GTK_CTREE(addrbook
.ctree
), addrbook
.treeSelected
);
5061 if( pobj
== NULL
) return;
5063 if( pobj
->type
== ADDR_DATASOURCE
) {
5064 ads
= ADAPTER_DSOURCE(pobj
);
5065 ds
= ads
->dataSource
;
5066 } else if (pobj
->type
== ADDR_ITEM_GROUP
) {
5071 else if( pobj
->type
!= ADDR_INTERFACE
) {
5072 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
5078 for(cur
= GTK_CLIST(addrbook
.clist
)->selection
; cur
; cur
= cur
->next
) {
5079 aio
= (AddrItemObject
*)gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.clist
),
5080 GTK_CTREE_NODE(cur
->data
));
5081 while (aio
&& aio
->type
!= ADDR_ITEM_PERSON
) {
5086 if (aio
&& aio
->type
== ADDR_ITEM_PERSON
) {
5087 if( ds
&& ds
->interface
&& ds
->interface
->readOnly
)
5088 gtk_selection_data_set(selection_data
,
5089 selection_data
->target
, 8,
5090 "Dummy_addr_copy", 15);
5092 gtk_selection_data_set(selection_data
,
5093 selection_data
->target
, 8,
5094 "Dummy_addr_move", 15);
5098 static gboolean
addressbook_drag_motion_cb(GtkWidget
*widget
,
5099 GdkDragContext
*context
,
5106 GtkCTreeNode
*node
= NULL
;
5107 gboolean acceptable
= FALSE
;
5108 gint height
= addrbook
.ctree
->allocation
.height
;
5109 gint total_height
= addrbook
.ctree
->requisition
.height
;
5110 GtkAdjustment
*pos
= gtk_scrolled_window_get_vadjustment(
5111 GTK_SCROLLED_WINDOW(addrbook
.ctree_swin
));
5112 gfloat vpos
= pos
->value
;
5114 if (gtk_clist_get_selection_info
5115 (GTK_CLIST(widget
), x
- 24, y
- 24, &row
, &column
)) {
5117 if (y
> height
- 24 && height
+ vpos
< total_height
)
5118 gtk_adjustment_set_value(pos
, (vpos
+5 > height
? height
: vpos
+5));
5120 if (y
< 24 && y
> 0)
5121 gtk_adjustment_set_value(pos
, (vpos
-5 < 0 ? 0 : vpos
-5));
5123 node
= gtk_ctree_node_nth(GTK_CTREE(widget
), row
);
5126 AddressObject
*obj
= gtk_ctree_node_get_row_data(GTK_CTREE(widget
), node
);
5127 if( obj
->type
== ADDR_ITEM_FOLDER
5128 || obj
->type
== ADDR_ITEM_GROUP
)
5131 AdapterDSource
*ads
= NULL
;
5132 AddressDataSource
*ds
= NULL
;
5133 ads
= ADAPTER_DSOURCE(obj
);
5134 if (ads
== NULL
){ return FALSE
;}
5135 ds
= ads
->dataSource
;
5136 if (ds
== NULL
) { return FALSE
;}
5144 g_signal_handlers_block_by_func
5146 G_CALLBACK(addressbook_tree_selected
), NULL
);
5147 gtk_sctree_select( GTK_SCTREE(widget
), node
);
5148 g_signal_handlers_unblock_by_func
5150 G_CALLBACK(addressbook_tree_selected
), NULL
);
5151 gdk_drag_status(context
,
5152 (context
->actions
== GDK_ACTION_COPY
?
5153 GDK_ACTION_COPY
: GDK_ACTION_MOVE
) , time
);
5155 gdk_drag_status(context
, 0, time
);
5161 static void addressbook_drag_leave_cb(GtkWidget
*widget
,
5162 GdkDragContext
*context
,
5166 if (addrbook
.treeSelected
) {
5167 g_signal_handlers_block_by_func
5169 G_CALLBACK(addressbook_tree_selected
), NULL
);
5170 gtk_sctree_select( GTK_SCTREE(widget
), addrbook
.opened
);
5171 g_signal_handlers_unblock_by_func
5173 G_CALLBACK(addressbook_tree_selected
), NULL
);
5178 static void addressbook_drag_received_cb(GtkWidget
*widget
,
5179 GdkDragContext
*drag_context
,
5182 GtkSelectionData
*data
,
5189 GtkCTreeNode
*lastopened
= addrbook
.opened
;
5191 if (!strncmp(data
->data
, "Dummy_addr", 10)) {
5192 if (gtk_clist_get_selection_info
5193 (GTK_CLIST(widget
), x
- 24, y
- 24, &row
, &column
) == 0) {
5197 node
= gtk_ctree_node_nth(GTK_CTREE(widget
), row
);
5198 if( !node
|| !gtk_ctree_node_get_row_data(GTK_CTREE(addrbook
.ctree
), node
))
5201 gtk_clist_freeze(GTK_CLIST(addrbook
.clist
));
5202 if (drag_context
->action
== GDK_ACTION_COPY
||
5203 !strcmp(data
->data
, "Dummy_addr_copy"))
5204 addressbook_clip_copy_cb();
5206 addressbook_clip_cut_cb();
5207 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), node
);
5208 addressbook_clip_paste_cb();
5209 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), lastopened
);
5210 gtk_clist_thaw(GTK_CLIST(addrbook
.clist
));
5211 gtk_drag_finish(drag_context
, TRUE
, TRUE
, time
);