2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2013 Hiroyuki Yamamoto and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "claws-features.h"
28 #include <glib/gi18n.h>
29 #include <gdk/gdkkeysyms.h>
33 #include <sys/types.h>
37 #include "addressbook.h"
38 #include "manage_window.h"
39 #include "prefs_common.h"
40 #include "alertpanel.h"
41 #include "inputdialog.h"
43 #include "stock_pixmap.h"
45 #include "prefs_gtk.h"
51 #include "addr_compl.h"
54 #include "addressitem.h"
56 #include "addrcache.h"
58 #include "addrindex.h"
59 #include "addressadd.h"
60 #include "addrduplicates.h"
61 #include "addressbook_foldersel.h"
63 #include "editvcard.h"
64 #include "editgroup.h"
65 #include "editaddress.h"
67 #include "importldif.h"
68 #include "importmutt.h"
69 #include "importpine.h"
74 #include "editjpilot.h"
79 #include "ldapserver.h"
81 #include "ldapupdate.h"
83 #define ADDRESSBOOK_LDAP_BUSYMSG "Busy"
86 #include "addrquery.h"
87 #include "addrselect.h"
89 #include "addrgather.h"
90 #include "adbookbase.h"
91 #include "exphtmldlg.h"
92 #include "expldifdlg.h"
93 #include "browseldap.h"
94 #include "addrcustomattr.h"
102 } AddressIndexColumns
;
110 } AddressListColumns
;
113 AddressBookFile
*book
;
121 AddressDataSource
*book
;
125 static gchar
*list_titles
[] = { N_("Name"),
129 #define COL_NAME_WIDTH 164
130 #define COL_ADDRESS_WIDTH 156
132 #define COL_FOLDER_WIDTH 170
133 #define ADDRESSBOOK_WIDTH 640
134 #define ADDRESSBOOK_HEIGHT 360
136 #define ADDRESSBOOK_MSGBUF_SIZE 2048
138 static GdkPixbuf
*folderxpm
= NULL
;
139 static GdkPixbuf
*folderopenxpm
= NULL
;
140 static GdkPixbuf
*groupxpm
= NULL
;
141 static GdkPixbuf
*interfacexpm
= NULL
;
142 static GdkPixbuf
*bookxpm
= NULL
;
143 static GdkPixbuf
*addressxpm
= NULL
;
144 static GdkPixbuf
*vcardxpm
= NULL
;
145 static GdkPixbuf
*jpilotxpm
= NULL
;
146 static GdkPixbuf
*categoryxpm
= NULL
;
147 static GdkPixbuf
*ldapxpm
= NULL
;
148 static GdkPixbuf
*addrsearchxpm
= NULL
;
151 static gchar addressbook_msgbuf
[ ADDRESSBOOK_MSGBUF_SIZE
];
153 /* Address list selection */
154 static AddrSelectList
*_addressSelect_
= NULL
;
155 static AddressClipboard
*_clipBoard_
= NULL
;
157 /* Address index file and interfaces */
158 static AddressIndex
*_addressIndex_
= NULL
;
159 static GList
*_addressInterfaceList_
= NULL
;
160 static GList
*_addressIFaceSelection_
= NULL
;
161 #define ADDRESSBOOK_IFACE_SELECTION "1/y,3/y,4/y,2/n"
163 static AddressBook_win addrbook
;
165 static GHashTable
*_addressBookTypeHash_
= NULL
;
166 static GList
*_addressBookTypeList_
= NULL
;
168 static void addressbook_new_address_from_book_post_cb( ItemPerson
*person
);
169 static void addressbook_new_address_from_folder_post_cb( ItemPerson
*person
);
170 static void addressbook_edit_address_post_cb( ItemPerson
*person
);
172 static void addressbook_create (void);
173 static gint
addressbook_close (void);
175 static gboolean address_index_has_focus
= FALSE
;
176 static gboolean address_list_has_focus
= FALSE
;
178 /* callback functions */
179 static void addressbook_del_clicked (GtkButton
*button
,
181 static void addressbook_reg_clicked (GtkButton
*button
,
183 static void addressbook_to_clicked (GtkButton
*button
,
185 static void addressbook_lup_clicked (GtkButton
*button
,
187 static void addressbook_close_clicked (GtkButton
*button
,
190 static void addressbook_tree_selected (GtkCMCTree
*ctree
,
191 GtkCMCTreeNode
*node
,
194 static void addressbook_select_row_tree (GtkCMCTree
*ctree
,
195 GtkCMCTreeNode
*node
,
198 static void addressbook_list_row_selected (GtkCMCTree
*clist
,
199 GtkCMCTreeNode
*node
,
202 static void addressbook_list_row_unselected (GtkCMCTree
*clist
,
203 GtkCMCTreeNode
*node
,
206 static void addressbook_person_expand_node (GtkCMCTree
*ctree
,
209 static void addressbook_person_collapse_node (GtkCMCTree
*ctree
,
213 static void addressbook_entry_activated (GtkWidget
*widget
,
216 static gboolean
addressbook_list_button_pressed (GtkWidget
*widget
,
217 GdkEventButton
*event
,
219 static gboolean
addressbook_list_button_released(GtkWidget
*widget
,
220 GdkEventButton
*event
,
222 static gboolean
addressbook_tree_button_pressed (GtkWidget
*ctree
,
223 GdkEventButton
*event
,
225 static gboolean
addressbook_tree_button_released(GtkWidget
*ctree
,
226 GdkEventButton
*event
,
229 static void addressbook_new_folder_cb (GtkAction
*action
,
231 static void addressbook_new_group_cb (GtkAction
*action
,
233 static void addressbook_treenode_edit_cb (GtkAction
*action
,
235 static void addressbook_treenode_delete_cb (GtkAction
*action
,
238 static void addressbook_change_node_name (GtkCMCTreeNode
*node
,
241 static void addressbook_new_address_cb (GtkAction
*action
,
243 static void addressbook_edit_address_cb (GtkAction
*action
,
245 static void addressbook_delete_address_cb (GtkAction
*action
,
248 static void close_cb (GtkAction
*action
,
250 static void addressbook_file_save_cb (GtkAction
*action
,
253 /* Data source edit stuff */
254 static void addressbook_new_book_cb (GtkAction
*action
,
256 static void addressbook_new_vcard_cb (GtkAction
*action
,
260 static void addressbook_new_jpilot_cb (GtkAction
*action
,
265 static void addressbook_new_ldap_cb (GtkAction
*action
,
269 static void addressbook_set_clist (AddressObject
*obj
,
272 static void addressbook_load_tree (void);
273 void addressbook_read_file (void);
275 static GtkCMCTreeNode
*addressbook_add_object (GtkCMCTreeNode
*node
,
277 static void addressbook_treenode_remove_item ( void );
279 static AddressDataSource
*addressbook_find_datasource
280 (GtkCMCTreeNode
*node
);
282 static AddressBookFile
*addressbook_get_book_file(void);
284 static GtkCMCTreeNode
*addressbook_node_add_folder
285 (GtkCMCTreeNode
*node
,
286 AddressDataSource
*ds
,
287 ItemFolder
*itemFolder
,
288 AddressObjectType otype
);
289 static GtkCMCTreeNode
*addressbook_node_add_group (GtkCMCTreeNode
*node
,
290 AddressDataSource
*ds
,
291 ItemGroup
*itemGroup
);
292 static void addressbook_tree_remove_children (GtkCMCTree
*ctree
,
293 GtkCMCTreeNode
*parent
);
294 static void addressbook_move_nodes_up (GtkCMCTree
*ctree
,
295 GtkCMCTreeNode
*node
);
296 static GtkCMCTreeNode
*addressbook_find_group_node (GtkCMCTreeNode
*parent
,
298 static gboolean
addressbook_entry_key_pressed (GtkWidget
*widget
,
301 static gint
addressbook_treenode_compare_func (GtkCMCList
*clist
,
304 static void addressbook_folder_load_one_person (GtkCMCTree
*clist
,
306 AddressTypeControlItem
*atci
,
307 AddressTypeControlItem
*atciMail
);
308 static void addressbook_folder_refresh_one_person(GtkCMCTree
*clist
,
310 static void addressbook_folder_remove_one_person(GtkCMCTree
*clist
,
312 static void addressbook_folder_remove_node (GtkCMCTree
*clist
,
313 GtkCMCTreeNode
*node
);
315 static void addressbook_edit_address( gpointer data
, guint action
, GtkWidget
*widget
,
316 gboolean force_focus
);
318 /* LUT's and IF stuff */
319 static void addressbook_free_treenode ( gpointer data
);
320 static AddressTypeControlItem
*addrbookctl_lookup (gint ot
);
321 static AddressTypeControlItem
*addrbookctl_lookup_iface(AddressIfType ifType
);
323 static void addrbookctl_build_map (GtkWidget
*window
);
324 static void addrbookctl_build_iflist (void);
325 static AdapterInterface
*addrbookctl_find_interface (AddressIfType ifType
);
326 static void addrbookctl_build_ifselect (void);
328 static void addrbookctl_free_interface (AdapterInterface
*adapter
);
329 static void addrbookctl_free_datasource (AdapterDSource
*adapter
);
330 static void addrbookctl_free_folder (AdapterFolder
*adapter
);
331 static void addrbookctl_free_group (AdapterGroup
*adapter
);
333 static void addressbook_list_select_clear ( void );
334 static void addressbook_list_select_add ( AddrItemObject
*aio
,
335 AddressDataSource
*ds
);
336 static void addressbook_list_select_remove ( AddrItemObject
*aio
);
338 static void addressbook_import_ldif_cb ( GtkAction
*action
, gpointer data
);
339 static void addressbook_find_duplicates_cb ( GtkAction
*action
, gpointer data
);
340 static void addressbook_edit_custom_attr_cb ( GtkAction
*action
, gpointer data
);
341 static void addressbook_import_mutt_cb ( GtkAction
*action
, gpointer data
);
342 static void addressbook_import_pine_cb ( GtkAction
*action
, gpointer data
);
343 static void addressbook_export_html_cb ( GtkAction
*action
, gpointer data
);
344 static void addressbook_export_ldif_cb ( GtkAction
*action
, gpointer data
);
345 static void addressbook_select_all_cb ( GtkAction
*action
, gpointer data
);
346 static void addressbook_clip_cut_cb ( GtkAction
*action
, gpointer data
);
347 static void addressbook_clip_copy_cb ( GtkAction
*action
, gpointer data
);
348 static void addressbook_clip_paste_cb ( GtkAction
*action
, gpointer data
);
349 static void addressbook_treenode_cut_cb ( GtkAction
*action
, gpointer data
);
350 static void addressbook_treenode_copy_cb ( GtkAction
*action
, gpointer data
);
351 static void addressbook_treenode_paste_cb ( GtkAction
*action
, gpointer data
);
353 static void addressbook_mail_to_cb ( GtkAction
*action
, gpointer data
);
356 static void addressbook_browse_entry_cb ( GtkAction
*action
, gpointer data
);
358 static void addressbook_edit_clicked(GtkButton
*button
, gpointer data
);
360 static void addressbook_start_drag(GtkWidget
*widget
, gint button
,
363 static void addressbook_drag_data_get(GtkWidget
*widget
,
364 GdkDragContext
*drag_context
,
365 GtkSelectionData
*selection_data
,
369 static gboolean
addressbook_drag_motion_cb(GtkWidget
*widget
,
370 GdkDragContext
*context
,
375 static void addressbook_drag_leave_cb(GtkWidget
*widget
,
376 GdkDragContext
*context
,
379 static void addressbook_drag_received_cb(GtkWidget
*widget
,
380 GdkDragContext
*drag_context
,
383 GtkSelectionData
*data
,
387 static void addressbook_list_menu_setup( void );
389 static GtkTargetEntry addressbook_drag_types
[] =
391 {"claws-mail/internal", GTK_TARGET_SAME_APP
, TARGET_DUMMY
}
394 static GtkTargetList
*addressbook_target_list
= NULL
;
396 static void about_show_cb(GtkAction
*action
, gpointer data
)
401 static GtkActionEntry addressbook_entries
[] =
403 {"Menu", NULL
, "Menu" },
405 {"Book", NULL
, N_("_Book") },
406 {"Address", NULL
, N_("_Edit") },
407 {"Tools", NULL
, N_("_Tools") },
408 {"Help", NULL
, N_("_Help") },
411 {"Book/NewBook", NULL
, N_("New _Book"), "<control>B", NULL
, G_CALLBACK(addressbook_new_book_cb
) },
412 {"Book/NewFolder", NULL
, N_("New _Folder"), "<control>R", NULL
, G_CALLBACK(addressbook_new_folder_cb
) },
413 {"Book/NewVCard", NULL
, N_("New _vCard"), "<control><shift>D", NULL
, G_CALLBACK(addressbook_new_vcard_cb
) },
417 {"Book/NewJPilot", NULL
, N_("New _JPilot"), "<control>J", NULL
, G_CALLBACK(addressbook_new_jpilot_cb
) },
420 {"Book/NewLDAPServer", NULL
, N_("New LDAP _Server"), "<control><shift>S", NULL
, G_CALLBACK(addressbook_new_ldap_cb
) },
422 {"Book/---", NULL
, "---", NULL
, NULL
, NULL
},
424 {"Book/EditBook", NULL
, N_("_Edit book"), NULL
, NULL
, G_CALLBACK(addressbook_treenode_edit_cb
) },
425 {"Book/DeleteBook", NULL
, N_("_Delete book"), NULL
, NULL
, G_CALLBACK(addressbook_treenode_delete_cb
) },
426 /* {"Book/---", NULL, "---", NULL, NULL, NULL }, */
427 {"Book/Save", NULL
, N_("_Save"), "<control>S", NULL
, G_CALLBACK(addressbook_file_save_cb
) },
428 {"Book/Close", NULL
, N_("_Close"), "<control>W", NULL
, G_CALLBACK(close_cb
) },
431 {"Address/SelectAll", NULL
, N_("_Select all"), "<control>A", NULL
, G_CALLBACK(addressbook_select_all_cb
) },
432 {"Address/---", NULL
, "---", NULL
, NULL
, NULL
},
433 {"Address/Cut", NULL
, N_("C_ut"), "<control>X", NULL
, G_CALLBACK(addressbook_clip_cut_cb
) },
434 {"Address/Copy", NULL
, N_("_Copy"), "<control>C", NULL
, G_CALLBACK(addressbook_clip_copy_cb
) },
435 {"Address/Paste", NULL
, N_("_Paste"), "<control>V", NULL
, G_CALLBACK(addressbook_clip_paste_cb
) },
436 /* {"Address/---", NULL, "---", NULL, NULL, NULL }, */
437 {"Address/Edit", NULL
, N_("_Edit"), "<control>Return", NULL
, G_CALLBACK(addressbook_edit_address_cb
) },
438 {"Address/Delete", NULL
, N_("_Delete"), "<control>D", NULL
, G_CALLBACK(addressbook_delete_address_cb
) },
439 /* {"Address/---", NULL, "---", NULL, NULL, NULL }, */
440 {"Address/NewAddress", NULL
, N_("New _Address"), "<control>N", NULL
, G_CALLBACK(addressbook_new_address_cb
) },
441 {"Address/NewGroup", NULL
, N_("New _Group"), "<control>G", NULL
, G_CALLBACK(addressbook_new_group_cb
) },
442 /* {"Address/---", NULL, "---", NULL, NULL, NULL }, */
443 {"Address/Mailto", NULL
, N_("_Mail To"), "<control>M", NULL
, G_CALLBACK(addressbook_mail_to_cb
) },
447 {"Tools/ImportLDIF", NULL
, N_("Import _LDIF file..."), NULL
, NULL
, G_CALLBACK(addressbook_import_ldif_cb
) },
448 {"Tools/ImportMutt", NULL
, N_("Import M_utt file..."), NULL
, NULL
, G_CALLBACK(addressbook_import_mutt_cb
) },
449 {"Tools/ImportPine", NULL
, N_("Import _Pine file..."), NULL
, NULL
, G_CALLBACK(addressbook_import_pine_cb
) },
450 {"Tools/---", NULL
, "---", NULL
, NULL
, NULL
},
451 {"Tools/ExportHTML", NULL
, N_("Export _HTML..."), NULL
, NULL
, G_CALLBACK(addressbook_export_html_cb
) },
452 {"Tools/ExportLDIF", NULL
, N_("Export LDI_F..."), NULL
, NULL
, G_CALLBACK(addressbook_export_ldif_cb
) },
453 /* {"Tools/---", NULL, "---", NULL, NULL, NULL },*/
454 {"Tools/FindDuplicates", NULL
, N_("Find duplicates..."), NULL
, NULL
, G_CALLBACK(addressbook_find_duplicates_cb
) },
455 {"Tools/EditAttrs", NULL
, N_("Edit custom attributes..."), NULL
, NULL
, G_CALLBACK(addressbook_edit_custom_attr_cb
) },
458 {"Help/About", NULL
, N_("_About"), NULL
, NULL
, G_CALLBACK(about_show_cb
) },
462 static GtkActionEntry addressbook_tree_popup_entries
[] =
464 {"ABTreePopup", NULL
, "ABTreePopup" },
465 {"ABTreePopup/EditBook", NULL
, N_("_Edit"), NULL
, NULL
, G_CALLBACK(addressbook_treenode_edit_cb
) },
466 {"ABTreePopup/DeleteBook", NULL
, N_("_Delete"), NULL
, NULL
, G_CALLBACK(addressbook_treenode_delete_cb
) },
467 {"ABTreePopup/---", NULL
, "---", NULL
, NULL
, NULL
},
468 {"ABTreePopup/NewBook", NULL
, N_("New _Book"), NULL
, NULL
, G_CALLBACK(addressbook_new_book_cb
) },
469 {"ABTreePopup/NewFolder", NULL
, N_("New _Folder"), NULL
, NULL
, G_CALLBACK(addressbook_new_folder_cb
) },
470 {"ABTreePopup/NewGroup", NULL
, N_("New _Group"), NULL
, NULL
, G_CALLBACK(addressbook_new_group_cb
) },
471 /* {"ABTreePopup/---", NULL, "---", NULL, NULL, NULL }, */
472 {"ABTreePopup/Cut", NULL
, N_("C_ut"), NULL
, NULL
, G_CALLBACK(addressbook_treenode_cut_cb
) },
473 {"ABTreePopup/Copy", NULL
, N_("_Copy"), NULL
, NULL
, G_CALLBACK(addressbook_treenode_copy_cb
) },
474 {"ABTreePopup/Paste", NULL
, N_("_Paste"), NULL
, NULL
, G_CALLBACK(addressbook_treenode_paste_cb
) },
477 static GtkActionEntry addressbook_list_popup_entries
[] =
479 {"ABListPopup", NULL
, "ABListPopup" },
480 {"ABListPopup/SelectAll", NULL
, N_("_Select all"), NULL
, NULL
, G_CALLBACK(addressbook_select_all_cb
) },
481 {"ABListPopup/---", NULL
, "---", NULL
, NULL
, NULL
},
482 {"ABListPopup/Edit", NULL
, N_("_Edit"), NULL
, NULL
, G_CALLBACK(addressbook_edit_address_cb
) },
483 {"ABListPopup/Delete", NULL
, N_("_Delete"), NULL
, NULL
, G_CALLBACK(addressbook_delete_address_cb
) },
484 /* {"ABListPopup/---", NULL, "---", NULL, NULL, NULL }, */
485 {"ABListPopup/NewAddress", NULL
, N_("New _Address"), NULL
, NULL
, G_CALLBACK(addressbook_new_address_cb
) },
486 {"ABListPopup/NewGroup", NULL
, N_("New _Group"), NULL
, NULL
, G_CALLBACK(addressbook_new_group_cb
) },
487 /* {"ABListPopup/---", NULL, "---", NULL, NULL, NULL }, */
488 {"ABListPopup/Cut", NULL
, N_("C_ut"), NULL
, NULL
, G_CALLBACK(addressbook_clip_cut_cb
) },
489 {"ABListPopup/Copy", NULL
, N_("_Copy"), NULL
, NULL
, G_CALLBACK(addressbook_clip_copy_cb
) },
490 {"ABListPopup/Paste", NULL
, N_("_Paste"), NULL
, NULL
, G_CALLBACK(addressbook_clip_paste_cb
) },
491 /* {"ABListPopup/---", NULL, "---", NULL, NULL, NULL }, */
492 {"ABListPopup/Mailto", NULL
, N_("_Mail To"), NULL
, NULL
, G_CALLBACK(addressbook_mail_to_cb
) },
494 {"ABListPopup/BrowseEntry", NULL
, N_("_Browse Entry"), NULL
, NULL
, G_CALLBACK(addressbook_browse_entry_cb
) },
499 * Structure of error message table.
501 typedef struct _ErrMsgTableEntry ErrMsgTableEntry
;
502 struct _ErrMsgTableEntry
{
507 static gchar
*_errMsgUnknown_
= N_( "Unknown" );
510 * Lookup table of error messages for general errors. Note that a NULL
511 * description signifies the end of the table.
513 static ErrMsgTableEntry _lutErrorsGeneral_
[] = {
514 { MGU_SUCCESS
, N_("Success") },
515 { MGU_BAD_ARGS
, N_("Bad arguments") },
516 { MGU_NO_FILE
, N_("File not specified") },
517 { MGU_OPEN_FILE
, N_("Error opening file") },
518 { MGU_ERROR_READ
, N_("Error reading file") },
519 { MGU_EOF
, N_("End of file encountered") },
520 { MGU_OO_MEMORY
, N_("Error allocating memory") },
521 { MGU_BAD_FORMAT
, N_("Bad file format") },
522 { MGU_ERROR_WRITE
, N_("Error writing to file") },
523 { MGU_OPEN_DIRECTORY
, N_("Error opening directory") },
524 { MGU_NO_PATH
, N_("No path specified") },
530 * Lookup table of error messages for LDAP errors.
532 static ErrMsgTableEntry _lutErrorsLDAP_
[] = {
533 { LDAPRC_SUCCESS
, N_("Success") },
534 { LDAPRC_CONNECT
, N_("Error connecting to LDAP server") },
535 { LDAPRC_INIT
, N_("Error initializing LDAP") },
536 { LDAPRC_BIND
, N_("Error binding to LDAP server") },
537 { LDAPRC_SEARCH
, N_("Error searching LDAP database") },
538 { LDAPRC_TIMEOUT
, N_("Timeout performing LDAP operation") },
539 { LDAPRC_CRITERIA
, N_("Error in LDAP search criteria") },
540 { LDAPRC_NOENTRIES
, N_("No LDAP entries found for search criteria") },
541 { LDAPRC_STOP_FLAG
, N_("LDAP search terminated on request") },
542 { LDAPRC_TLS
, N_("Error starting STARTTLS connection") },
543 { LDAPRC_NODN
, N_("Distinguished Name (dn) is missing") },
544 { LDAPRC_NAMING_VIOLATION
, N_("Missing required information") },
545 { LDAPRC_ALREADY_EXIST
, N_("Another contact exists with that key") },
546 { LDAPRC_STRONG_AUTH
, N_("Strong(er) authentication required") },
552 * Lookup message for specified error code.
553 * \param lut Lookup table.
554 * \param code Code to lookup.
555 * \return Description associated to code.
557 static gchar
*addressbook_err2string( ErrMsgTableEntry lut
[], gint code
) {
559 ErrMsgTableEntry entry
;
562 for( i
= 0; ; i
++ ) {
564 if( entry
.description
== NULL
) break;
565 if( entry
.code
== code
) {
566 desc
= entry
.description
;
571 desc
= _errMsgUnknown_
;
576 static gboolean lastCanLookup
= FALSE
;
578 static void addressbook_show_buttons(gboolean add_and_delete
, gboolean lookup
, gboolean mail_ops
)
580 if (add_and_delete
) {
581 gtk_widget_show(addrbook
.edit_btn
);
582 gtk_widget_show(addrbook
.del_btn
);
583 gtk_widget_show(addrbook
.reg_btn
);
585 gtk_widget_hide(addrbook
.edit_btn
);
586 gtk_widget_hide(addrbook
.del_btn
);
587 gtk_widget_hide(addrbook
.reg_btn
);
591 gtk_widget_show(addrbook
.lup_btn
);
592 gtk_widget_show(addrbook
.entry
);
593 gtk_widget_show(addrbook
.label
);
595 gtk_widget_hide(addrbook
.lup_btn
);
596 gtk_widget_hide(addrbook
.entry
);
597 gtk_widget_hide(addrbook
.label
);
600 lastCanLookup
= lookup
;
603 gtk_widget_show(addrbook
.to_btn
);
604 gtk_widget_show(addrbook
.cc_btn
);
605 gtk_widget_show(addrbook
.bcc_btn
);
607 gtk_widget_hide(addrbook
.to_btn
);
608 gtk_widget_hide(addrbook
.cc_btn
);
609 gtk_widget_hide(addrbook
.bcc_btn
);
613 void addressbook_open(Compose
*target
)
615 /* Initialize all static members */
616 if( _clipBoard_
== NULL
) {
617 _clipBoard_
= addrclip_create();
619 if( _addressIndex_
!= NULL
) {
620 addrclip_set_index( _clipBoard_
, _addressIndex_
);
622 if( _addressSelect_
== NULL
) {
623 _addressSelect_
= addrselect_list_create();
625 if (!addrbook
.window
) {
626 addressbook_read_file();
627 addressbook_create();
628 addressbook_load_tree();
629 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
),
630 GTK_CMCTREE_NODE(GTK_CMCLIST(addrbook
.ctree
)->row_list
));
633 gtk_widget_hide(addrbook
.window
);
636 gtk_widget_show_all(addrbook
.window
);
638 if (!prefs_common
.addressbook_use_editaddress_dialog
)
639 addressbook_edit_person_widgetset_hide();
641 address_completion_start(addrbook
.window
);
643 addressbook_show_buttons(target
== NULL
, lastCanLookup
, target
!= NULL
);
644 addressbook_set_target_compose(target
);
648 * Destroy addressbook.
650 void addressbook_destroy( void ) {
651 /* Free up address stuff */
652 if( _addressSelect_
!= NULL
) {
653 addrselect_list_free( _addressSelect_
);
655 if( _clipBoard_
!= NULL
) {
656 addrclip_free( _clipBoard_
);
658 if( _addressIndex_
!= NULL
) {
659 addrindex_free_index( _addressIndex_
);
660 addrindex_teardown();
662 _addressSelect_
= NULL
;
664 _addressIndex_
= NULL
;
667 void addressbook_set_target_compose(Compose
*target
)
669 addrbook
.target_compose
= target
;
672 Compose
*addressbook_get_target_compose(void)
674 return addrbook
.target_compose
;
678 * Refresh addressbook and save to file(s).
680 void addressbook_refresh( void )
682 if (addrbook
.window
) {
683 if (addrbook
.treeSelected
) {
684 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
),
685 addrbook
.treeSelected
);
686 addressbook_set_clist(
687 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook
.ctree
),
688 addrbook
.treeSelected
),
693 addressbook_export_to_file();
696 static gboolean
key_pressed(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
698 if (event
&& event
->keyval
== GDK_KEY_Escape
)
700 else if (event
&& event
->keyval
== GDK_KEY_Delete
) {
701 /* TODO: enable deletion when focus is in ctree (needs implementation in _del_clicked() */
702 if ( /* address_index_has_focus || */ address_list_has_focus
)
703 addressbook_del_clicked(NULL
, NULL
);
709 *\brief Save Gtk object size to prefs dataset
711 static void addressbook_size_allocate_cb(GtkWidget
*widget
,
712 GtkAllocation
*allocation
)
714 cm_return_if_fail(allocation
!= NULL
);
716 prefs_common
.addressbookwin_width
= allocation
->width
;
717 prefs_common
.addressbookwin_height
= allocation
->height
;
720 static gint sort_column_number
= 0;
721 static GtkSortType sort_column_type
= GTK_SORT_ASCENDING
;
723 static gint
list_case_sort(
724 GtkCMCList
*clist
, gconstpointer ptr1
, gconstpointer ptr2
)
726 GtkCMCListRow
*row1
= (GtkCMCListRow
*) ptr1
;
727 GtkCMCListRow
*row2
= (GtkCMCListRow
*) ptr2
;
728 gchar
*name1
= NULL
, *name2
= NULL
;
729 AddrItemObject
*aio1
= ((GtkCMCListRow
*)ptr1
)->data
;
730 AddrItemObject
*aio2
= ((GtkCMCListRow
*)ptr2
)->data
;
732 if( aio1
->type
== aio2
->type
) {
734 name1
= GTK_CMCELL_TEXT (row1
->cell
[sort_column_number
])->text
;
736 name2
= GTK_CMCELL_TEXT (row2
->cell
[sort_column_number
])->text
;
737 if( ! name1
) return ( name2
!= NULL
);
738 if( ! name2
) return -1;
739 return g_utf8_collate( name1
, name2
);
741 /* Order groups before person */
742 if( aio1
->type
== ITEMTYPE_GROUP
) {
743 return (sort_column_type
==GTK_SORT_ASCENDING
) ? -1:+1;
744 } else if( aio2
->type
== ITEMTYPE_GROUP
) {
745 return (sort_column_type
==GTK_SORT_ASCENDING
) ? +1:-1;
751 static void addressbook_sort_list(GtkCMCList
*clist
, const gint col
,
752 const GtkSortType sort_type
)
755 GtkWidget
*hbox
, *label
, *arrow
;
757 sort_column_number
= col
;
758 sort_column_type
= sort_type
;
759 gtk_cmclist_set_compare_func(clist
, list_case_sort
);
760 gtk_cmclist_set_sort_type(clist
, sort_type
);
761 gtk_cmclist_set_sort_column(clist
, col
);
763 gtk_cmclist_freeze(clist
);
764 gtk_cmclist_sort(clist
);
766 for(pos
= 0 ; pos
< N_LIST_COLS
; pos
++) {
767 hbox
= gtk_hbox_new(FALSE
, 4);
768 label
= gtk_label_new(gettext(list_titles
[pos
]));
769 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
772 arrow
= gtk_arrow_new(sort_type
== GTK_SORT_ASCENDING
?
773 GTK_ARROW_DOWN
: GTK_ARROW_UP
, GTK_SHADOW_IN
);
774 gtk_box_pack_end(GTK_BOX(hbox
), arrow
, FALSE
, FALSE
, 0);
777 gtk_widget_show_all(hbox
);
778 gtk_cmclist_set_column_widget(clist
, pos
, hbox
);
781 gtk_cmclist_thaw(clist
);
784 static void addressbook_name_clicked(GtkWidget
*button
, GtkCMCList
*clist
)
786 static GtkSortType sort_type
= GTK_SORT_ASCENDING
;
788 sort_type
= (sort_type
== GTK_SORT_ASCENDING
) ? GTK_SORT_DESCENDING
:
790 addressbook_sort_list(clist
, COL_NAME
, sort_type
);
793 static void addressbook_address_clicked(GtkWidget
*button
, GtkCMCList
*clist
)
795 static GtkSortType sort_type
= GTK_SORT_ASCENDING
;
797 sort_type
= (sort_type
== GTK_SORT_ASCENDING
) ? GTK_SORT_DESCENDING
:
799 addressbook_sort_list(clist
, COL_ADDRESS
, sort_type
);
802 static void addressbook_remarks_clicked(GtkWidget
*button
, GtkCMCList
*clist
)
804 static GtkSortType sort_type
= GTK_SORT_ASCENDING
;
806 sort_type
= (sort_type
== GTK_SORT_ASCENDING
) ? GTK_SORT_DESCENDING
:
808 addressbook_sort_list(clist
, COL_REMARKS
, sort_type
);
811 static gboolean
addressbook_address_index_focus_evt_in(GtkWidget
*widget
, GdkEventFocus
*event
,
814 address_index_has_focus
= TRUE
;
818 static gboolean
addressbook_address_index_focus_evt_out(GtkWidget
*widget
, GdkEventFocus
*event
,
821 address_index_has_focus
= FALSE
;
822 if (!prefs_common
.addressbook_use_editaddress_dialog
823 && !address_list_has_focus
)
824 addressbook_address_list_disable_some_actions();
828 static gboolean
addressbook_address_list_focus_evt_in(GtkWidget
*widget
, GdkEventFocus
*event
,
831 address_list_has_focus
= TRUE
;
835 static gboolean
addressbook_address_list_focus_evt_out(GtkWidget
*widget
, GdkEventFocus
*event
,
838 address_list_has_focus
= FALSE
;
839 if (!prefs_common
.addressbook_use_editaddress_dialog
840 && !address_index_has_focus
)
841 addressbook_address_list_disable_some_actions();
845 /* save hpane and vpane's handle position when it moves */
846 static void addressbook_pane_save_position(void)
849 prefs_common
.addressbook_hpaned_pos
=
850 gtk_paned_get_position(GTK_PANED(addrbook
.hpaned
));
852 prefs_common
.addressbook_vpaned_pos
=
853 gtk_paned_get_position(GTK_PANED(addrbook
.vpaned
));
857 * Create the address book widgets. The address book contains two CTree widgets: the
858 * address index tree on the left and the address list on the right.
860 * The address index tree displays a hierarchy of interfaces and groups. Each node in
861 * this tree is linked to an address Adapter. Adapters have been created for interfaces,
862 * data sources and folder objects.
864 * The address list displays group, person and email objects. These items are linked
865 * directly to ItemGroup, ItemPerson and ItemEMail objects inside the address book data
868 * In the tradition of MVC architecture, the data stores have been separated from the
869 * GUI components. The addrindex.c file provides the interface to all data stores.
871 static void addressbook_create(void)
877 GtkWidget
*ctree_swin
;
879 GtkWidget
*editaddress_vbox
;
880 GtkWidget
*clist_vbox
;
881 GtkWidget
*clist_swin
;
888 GtkWidget
*statusbar
;
899 GtkWidget
*close_btn
;
900 GtkWidget
*tree_popup
;
901 GtkWidget
*list_popup
;
903 GtkUIManager
*ui_manager
;
904 GtkActionGroup
*action_group
;
905 gchar
*index_titles
[N_INDEX_COLS
];
909 static GdkGeometry geometry
;
911 debug_print("Creating addressbook window...\n");
913 index_titles
[COL_SOURCES
] = _("Sources");
915 /* Address book window */
916 window
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "addressbook");
917 gtk_window_set_title(GTK_WINDOW(window
), _("Address book"));
918 gtk_window_set_resizable(GTK_WINDOW(window
), TRUE
);
919 gtk_widget_realize(window
);
921 g_signal_connect(G_OBJECT(window
), "delete_event",
922 G_CALLBACK(addressbook_close
), NULL
);
923 g_signal_connect(G_OBJECT(window
), "size_allocate",
924 G_CALLBACK(addressbook_size_allocate_cb
), NULL
);
925 g_signal_connect(G_OBJECT(window
), "key_press_event",
926 G_CALLBACK(key_pressed
), NULL
);
927 MANAGE_WINDOW_SIGNALS_CONNECT(window
);
929 vbox
= gtk_vbox_new(FALSE
, 0);
930 gtk_container_add(GTK_CONTAINER(window
), vbox
);
933 ui_manager
= gtk_ui_manager_new();
934 action_group
= cm_menu_create_action_group_full(ui_manager
,"Menu", addressbook_entries
,
935 G_N_ELEMENTS(addressbook_entries
), NULL
);
936 gtk_action_group_add_actions(action_group
, addressbook_tree_popup_entries
,
937 G_N_ELEMENTS(addressbook_tree_popup_entries
), NULL
);
938 gtk_action_group_add_actions(action_group
, addressbook_list_popup_entries
,
939 G_N_ELEMENTS(addressbook_list_popup_entries
), NULL
);
941 MENUITEM_ADDUI_MANAGER(ui_manager
, "/", "Menu", NULL
, GTK_UI_MANAGER_MENUBAR
)
943 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu", "Book", "Book", GTK_UI_MANAGER_MENU
)
944 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu", "Address", "Address", GTK_UI_MANAGER_MENU
)
945 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu", "Tools", "Tools", GTK_UI_MANAGER_MENU
)
946 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu", "Help", "Help", GTK_UI_MANAGER_MENU
)
949 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Book", "NewBook", "Book/NewBook", GTK_UI_MANAGER_MENUITEM
)
950 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Book", "NewFolder", "Book/NewFolder", GTK_UI_MANAGER_MENUITEM
)
951 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Book", "NewVCard", "Book/NewVCard", GTK_UI_MANAGER_MENUITEM
)
953 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Book", "NewJPilot", "Book/NewJPilot", GTK_UI_MANAGER_MENUITEM
)
956 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Book", "NewLDAPServer", "Book/NewLDAPServer", GTK_UI_MANAGER_MENUITEM
)
958 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Book", "Separator1", "Book/---", GTK_UI_MANAGER_SEPARATOR
)
959 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Book", "EditBook", "Book/EditBook", GTK_UI_MANAGER_MENUITEM
)
960 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Book", "DeleteBook", "Book/DeleteBook", GTK_UI_MANAGER_MENUITEM
)
961 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Book", "Separator2", "Book/---", GTK_UI_MANAGER_SEPARATOR
)
962 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Book", "Save", "Book/Save", GTK_UI_MANAGER_MENUITEM
)
963 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Book", "Close", "Book/Close", GTK_UI_MANAGER_MENUITEM
)
966 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "SelectAll", "Address/SelectAll", GTK_UI_MANAGER_MENUITEM
)
967 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "Separator1", "Address/---", GTK_UI_MANAGER_SEPARATOR
)
968 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "Cut", "Address/Cut", GTK_UI_MANAGER_MENUITEM
)
969 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "Copy", "Address/Copy", GTK_UI_MANAGER_MENUITEM
)
970 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "Paste", "Address/Paste", GTK_UI_MANAGER_MENUITEM
)
971 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "Separator2", "Address/---", GTK_UI_MANAGER_SEPARATOR
)
972 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "Edit", "Address/Edit", GTK_UI_MANAGER_MENUITEM
)
973 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "Delete", "Address/Delete", GTK_UI_MANAGER_MENUITEM
)
974 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "Separator3", "Address/---", GTK_UI_MANAGER_SEPARATOR
)
975 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "NewAddress", "Address/NewAddress", GTK_UI_MANAGER_MENUITEM
)
976 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "NewGroup", "Address/NewGroup", GTK_UI_MANAGER_MENUITEM
)
977 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "Separator4", "Address/---", GTK_UI_MANAGER_SEPARATOR
)
978 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Address", "Mailto", "Address/Mailto", GTK_UI_MANAGER_MENUITEM
)
981 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Tools", "ImportLDIF", "Tools/ImportLDIF", GTK_UI_MANAGER_MENUITEM
)
982 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Tools", "ImportMutt", "Tools/ImportMutt", GTK_UI_MANAGER_MENUITEM
)
983 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Tools", "ImportPine", "Tools/ImportPine", GTK_UI_MANAGER_MENUITEM
)
984 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Tools", "Separator1", "Tools/---", GTK_UI_MANAGER_SEPARATOR
)
985 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Tools", "ExportHTML", "Tools/ExportHTML", GTK_UI_MANAGER_MENUITEM
)
986 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Tools", "ExportLDIF", "Tools/ExportLDIF", GTK_UI_MANAGER_MENUITEM
)
987 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Tools", "Separator2", "Tools/---", GTK_UI_MANAGER_SEPARATOR
)
988 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Tools", "FindDuplicates", "Tools/FindDuplicates", GTK_UI_MANAGER_MENUITEM
)
989 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Tools", "EditAttrs", "Tools/EditAttrs", GTK_UI_MANAGER_MENUITEM
)
992 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Menu/Help", "About", "Help/About", GTK_UI_MANAGER_MENUITEM
)
994 menubar
= gtk_ui_manager_get_widget(ui_manager
, "/Menu");
996 gtk_box_pack_start(GTK_BOX(vbox
), menubar
, FALSE
, TRUE
, 0);
998 vbox2
= gtk_vbox_new(FALSE
, BORDER_WIDTH
);
999 gtk_container_set_border_width(GTK_CONTAINER(vbox2
), BORDER_WIDTH
);
1000 gtk_box_pack_start(GTK_BOX(vbox
), vbox2
, TRUE
, TRUE
, 0);
1002 ctree_swin
= gtk_scrolled_window_new(NULL
, NULL
);
1003 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ctree_swin
),
1004 GTK_POLICY_AUTOMATIC
,
1005 GTK_POLICY_AUTOMATIC
);
1006 gtk_widget_set_size_request(ctree_swin
, COL_FOLDER_WIDTH
+ 20, -1);
1009 ctree
= gtk_sctree_new_with_titles(N_INDEX_COLS
, 0, index_titles
);
1010 gtkut_widget_set_can_focus(GTK_CMCLIST(ctree
)->column
[0].button
, FALSE
);
1012 gtk_container_add(GTK_CONTAINER(ctree_swin
), ctree
);
1013 gtk_cmclist_set_selection_mode(GTK_CMCLIST(ctree
), GTK_SELECTION_BROWSE
);
1014 gtk_cmclist_set_column_width(GTK_CMCLIST(ctree
), 0, COL_FOLDER_WIDTH
);
1015 gtk_cmctree_set_line_style(GTK_CMCTREE(ctree
), GTK_CMCTREE_LINES_NONE
);
1016 gtk_cmctree_set_expander_style(GTK_CMCTREE(ctree
),
1017 GTK_CMCTREE_EXPANDER_TRIANGLE
);
1018 gtk_sctree_set_stripes(GTK_SCTREE(ctree
), prefs_common
.use_stripes_in_summaries
);
1019 gtk_cmctree_set_indent(GTK_CMCTREE(ctree
), CTREE_INDENT
);
1020 gtk_cmclist_set_compare_func(GTK_CMCLIST(ctree
),
1021 addressbook_treenode_compare_func
);
1023 g_signal_connect(G_OBJECT(ctree
), "tree_select_row",
1024 G_CALLBACK(addressbook_tree_selected
), NULL
);
1025 g_signal_connect(G_OBJECT(ctree
), "button_press_event",
1026 G_CALLBACK(addressbook_tree_button_pressed
),
1028 g_signal_connect(G_OBJECT(ctree
), "button_release_event",
1029 G_CALLBACK(addressbook_tree_button_released
),
1032 g_signal_connect(G_OBJECT(ctree
), "select_row",
1033 G_CALLBACK(addressbook_select_row_tree
), NULL
);
1035 gtk_drag_dest_set(ctree
, GTK_DEST_DEFAULT_ALL
& ~GTK_DEST_DEFAULT_HIGHLIGHT
,
1036 addressbook_drag_types
, 1,
1037 GDK_ACTION_MOVE
| GDK_ACTION_COPY
| GDK_ACTION_DEFAULT
);
1038 g_signal_connect(G_OBJECT(ctree
), "drag_motion",
1039 G_CALLBACK(addressbook_drag_motion_cb
),
1041 g_signal_connect(G_OBJECT(ctree
), "drag_leave",
1042 G_CALLBACK(addressbook_drag_leave_cb
),
1044 g_signal_connect(G_OBJECT(ctree
), "drag_data_received",
1045 G_CALLBACK(addressbook_drag_received_cb
),
1047 g_signal_connect(G_OBJECT(ctree
), "focus_in_event",
1048 G_CALLBACK(addressbook_address_index_focus_evt_in
), NULL
);
1049 g_signal_connect(G_OBJECT(ctree
), "focus_out_event",
1050 G_CALLBACK(addressbook_address_index_focus_evt_out
), NULL
);
1052 clist_vbox
= gtk_vbox_new(FALSE
, 4);
1054 clist_swin
= gtk_scrolled_window_new(NULL
, NULL
);
1055 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin
),
1056 GTK_POLICY_AUTOMATIC
,
1057 GTK_POLICY_AUTOMATIC
);
1058 gtk_box_pack_start(GTK_BOX(clist_vbox
), clist_swin
, TRUE
, TRUE
, 0);
1061 clist
= gtk_sctree_new_with_titles(N_LIST_COLS
, 0, list_titles
);
1062 gtk_container_add(GTK_CONTAINER(clist_swin
), clist
);
1063 gtk_cmclist_set_selection_mode(GTK_CMCLIST(clist
), GTK_SELECTION_MULTIPLE
);
1064 gtk_cmctree_set_line_style(GTK_CMCTREE(clist
), GTK_CMCTREE_LINES_NONE
);
1065 gtk_cmctree_set_expander_style(GTK_CMCTREE(clist
),
1066 GTK_CMCTREE_EXPANDER_TRIANGLE
);
1067 gtk_sctree_set_stripes(GTK_SCTREE(ctree
), prefs_common
.use_stripes_in_summaries
);
1068 gtk_cmctree_set_indent(GTK_CMCTREE(clist
), CTREE_INDENT
);
1069 gtk_cmclist_set_column_width(GTK_CMCLIST(clist
), COL_NAME
,
1071 gtk_cmclist_set_column_width(GTK_CMCLIST(clist
), COL_ADDRESS
,
1073 gtk_widget_set_size_request(clist
, -1, 80);
1075 addressbook_sort_list(GTK_CMCLIST(clist
), COL_NAME
, GTK_SORT_ASCENDING
);
1076 g_signal_connect(G_OBJECT(GTK_CMCLIST(clist
)->column
[COL_NAME
].button
),
1077 "clicked", G_CALLBACK(addressbook_name_clicked
), clist
);
1078 g_signal_connect(G_OBJECT(GTK_CMCLIST(clist
)->column
[COL_ADDRESS
].button
),
1079 "clicked", G_CALLBACK(addressbook_address_clicked
), clist
);
1080 g_signal_connect(G_OBJECT(GTK_CMCLIST(clist
)->column
[COL_REMARKS
].button
),
1081 "clicked", G_CALLBACK(addressbook_remarks_clicked
), clist
);
1082 g_signal_connect(G_OBJECT(clist
), "focus_in_event",
1083 G_CALLBACK(addressbook_address_list_focus_evt_in
), NULL
);
1084 g_signal_connect(G_OBJECT(clist
), "focus_out_event",
1085 G_CALLBACK(addressbook_address_list_focus_evt_out
), NULL
);
1087 for (i
= 0; i
< N_LIST_COLS
; i
++)
1088 gtkut_widget_set_can_focus(GTK_CMCLIST(clist
)->column
[i
].button
,
1091 g_signal_connect(G_OBJECT(clist
), "tree_select_row",
1092 G_CALLBACK(addressbook_list_row_selected
), NULL
);
1093 g_signal_connect(G_OBJECT(clist
), "tree_unselect_row",
1094 G_CALLBACK(addressbook_list_row_unselected
), NULL
);
1095 g_signal_connect(G_OBJECT(clist
), "button_press_event",
1096 G_CALLBACK(addressbook_list_button_pressed
),
1098 g_signal_connect(G_OBJECT(clist
), "button_release_event",
1099 G_CALLBACK(addressbook_list_button_released
),
1101 g_signal_connect(G_OBJECT(clist
), "tree_expand",
1102 G_CALLBACK(addressbook_person_expand_node
), NULL
);
1103 g_signal_connect(G_OBJECT(clist
), "tree_collapse",
1104 G_CALLBACK(addressbook_person_collapse_node
), NULL
);
1105 g_signal_connect(G_OBJECT(clist
), "start_drag",
1106 G_CALLBACK(addressbook_start_drag
), NULL
);
1107 g_signal_connect(G_OBJECT(clist
), "drag_data_get",
1108 G_CALLBACK(addressbook_drag_data_get
), NULL
);
1109 hbox
= gtk_hbox_new(FALSE
, 4);
1110 gtk_box_pack_start(GTK_BOX(clist_vbox
), hbox
, FALSE
, FALSE
, 0);
1112 label
= gtk_label_new(_("Search"));
1113 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
1115 entry
= gtk_entry_new();
1116 gtk_box_pack_start(GTK_BOX(hbox
), entry
, TRUE
, TRUE
, 0);
1118 address_completion_register_entry(GTK_ENTRY(entry
), FALSE
);
1120 g_signal_connect(G_OBJECT(entry
), "key_press_event",
1121 G_CALLBACK(addressbook_entry_key_pressed
),
1123 g_signal_connect(G_OBJECT(entry
), "activate",
1124 G_CALLBACK(addressbook_entry_activated
), NULL
);
1126 if (!prefs_common
.addressbook_use_editaddress_dialog
) {
1127 editaddress_vbox
= gtk_vbox_new(FALSE
, 4);
1128 vpaned
= gtk_vpaned_new();
1129 gtk_paned_pack1(GTK_PANED(vpaned
), clist_vbox
, FALSE
, FALSE
);
1130 gtk_paned_pack2(GTK_PANED(vpaned
), editaddress_vbox
, TRUE
, FALSE
);
1133 editaddress_vbox
= NULL
;
1135 hpaned
= gtk_hpaned_new();
1136 gtk_box_pack_start(GTK_BOX(vbox2
), hpaned
, TRUE
, TRUE
, 0);
1137 gtk_paned_pack1(GTK_PANED(hpaned
), ctree_swin
, FALSE
, FALSE
);
1138 if (prefs_common
.addressbook_use_editaddress_dialog
)
1139 gtk_paned_pack2(GTK_PANED(hpaned
), clist_vbox
, TRUE
, FALSE
);
1141 gtk_paned_pack2(GTK_PANED(hpaned
), vpaned
, TRUE
, FALSE
);
1144 hsbox
= gtk_hbox_new(FALSE
, 0);
1145 gtk_box_pack_end(GTK_BOX(vbox
), hsbox
, FALSE
, FALSE
, BORDER_WIDTH
);
1146 statusbar
= gtk_statusbar_new();
1147 gtk_box_pack_start(GTK_BOX(hsbox
), statusbar
, TRUE
, TRUE
, BORDER_WIDTH
);
1150 hbbox
= gtk_hbutton_box_new();
1151 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox
), GTK_BUTTONBOX_END
);
1152 gtk_box_set_spacing(GTK_BOX(hbbox
), 2);
1153 gtk_container_set_border_width(GTK_CONTAINER(hbbox
), 4);
1154 gtk_box_pack_end(GTK_BOX(vbox
), hbbox
, FALSE
, FALSE
, 0);
1156 gtkut_stock_button_add_help(hbbox
, &help_btn
);
1158 edit_btn
= gtk_button_new_from_stock(GTK_STOCK_EDIT
);
1159 gtkut_widget_set_can_default(edit_btn
, TRUE
);
1160 gtk_box_pack_start(GTK_BOX(hbbox
), edit_btn
, TRUE
, TRUE
, 0);
1161 del_btn
= gtk_button_new_from_stock(GTK_STOCK_DELETE
);
1162 gtkut_widget_set_can_default(del_btn
, TRUE
);
1163 gtk_box_pack_start(GTK_BOX(hbbox
), del_btn
, TRUE
, TRUE
, 0);
1164 reg_btn
= gtk_button_new_from_stock(GTK_STOCK_NEW
);
1165 gtkut_widget_set_can_default(reg_btn
, TRUE
);
1166 gtk_box_pack_start(GTK_BOX(hbbox
), reg_btn
, TRUE
, TRUE
, 0);
1169 lup_btn
= gtk_button_new_from_stock(GTK_STOCK_FIND
);
1170 gtkut_widget_set_can_default(lup_btn
, TRUE
);
1171 gtk_box_pack_start(GTK_BOX(hbox
), lup_btn
, TRUE
, TRUE
, 0);
1173 g_signal_connect(G_OBJECT(help_btn
), "clicked",
1174 G_CALLBACK(manual_open_with_anchor_cb
),
1175 MANUAL_ANCHOR_ADDRBOOK
);
1177 g_signal_connect(G_OBJECT(edit_btn
), "clicked",
1178 G_CALLBACK(addressbook_edit_clicked
), NULL
);
1179 g_signal_connect(G_OBJECT(del_btn
), "clicked",
1180 G_CALLBACK(addressbook_del_clicked
), NULL
);
1181 g_signal_connect(G_OBJECT(reg_btn
), "clicked",
1182 G_CALLBACK(addressbook_reg_clicked
), NULL
);
1183 g_signal_connect(G_OBJECT(lup_btn
), "clicked",
1184 G_CALLBACK(addressbook_lup_clicked
), NULL
);
1186 to_btn
= gtk_button_new_with_label
1187 (prefs_common_translated_header_name("To:"));
1188 gtkut_widget_set_can_default(to_btn
, TRUE
);
1189 gtk_box_pack_start(GTK_BOX(hbbox
), to_btn
, TRUE
, TRUE
, 0);
1190 cc_btn
= gtk_button_new_with_label
1191 (prefs_common_translated_header_name("Cc:"));
1192 gtkut_widget_set_can_default(cc_btn
, TRUE
);
1193 gtk_box_pack_start(GTK_BOX(hbbox
), cc_btn
, TRUE
, TRUE
, 0);
1194 bcc_btn
= gtk_button_new_with_label
1195 (prefs_common_translated_header_name("Bcc:"));
1196 gtkut_widget_set_can_default(bcc_btn
, TRUE
);
1197 gtk_box_pack_start(GTK_BOX(hbbox
), bcc_btn
, TRUE
, TRUE
, 0);
1199 close_btn
= gtk_button_new_from_stock(GTK_STOCK_CLOSE
);
1200 gtkut_widget_set_can_default(close_btn
, TRUE
);
1201 gtk_box_pack_start(GTK_BOX(hbbox
), close_btn
, TRUE
, TRUE
, 0);
1203 g_signal_connect(G_OBJECT(to_btn
), "clicked",
1204 G_CALLBACK(addressbook_to_clicked
),
1205 GINT_TO_POINTER(COMPOSE_TO
));
1206 g_signal_connect(G_OBJECT(cc_btn
), "clicked",
1207 G_CALLBACK(addressbook_to_clicked
),
1208 GINT_TO_POINTER(COMPOSE_CC
));
1209 g_signal_connect(G_OBJECT(bcc_btn
), "clicked",
1210 G_CALLBACK(addressbook_to_clicked
),
1211 GINT_TO_POINTER(COMPOSE_BCC
));
1212 g_signal_connect(G_OBJECT(close_btn
), "clicked",
1213 G_CALLBACK(addressbook_close_clicked
), NULL
);
1215 /* Build icons for interface */
1217 /* Build control tables */
1218 addrbookctl_build_map(window
);
1219 addrbookctl_build_iflist();
1220 addrbookctl_build_ifselect();
1222 addrbook
.clist
= NULL
;
1224 /* Add each interface into the tree as a root level folder */
1225 nodeIf
= _addressInterfaceList_
;
1227 AdapterInterface
*adapter
= nodeIf
->data
;
1228 AddressInterface
*iface
= adapter
->interface
;
1229 nodeIf
= g_list_next(nodeIf
);
1231 if(iface
->useInterface
) {
1232 AddressTypeControlItem
*atci
= adapter
->atci
;
1233 text
= atci
->displayName
;
1235 gtk_sctree_insert_node( GTK_CMCTREE(ctree
),
1236 NULL
, NULL
, &text
, FOLDER_SPACING
,
1240 cm_menu_set_sensitive_full(ui_manager
, atci
->menuCommand
, adapter
->haveLibrary
);
1241 gtk_cmctree_node_set_row_data_full(
1242 GTK_CMCTREE(ctree
), adapter
->treeNode
, adapter
,
1243 addressbook_free_treenode
);
1249 MENUITEM_ADDUI_MANAGER(ui_manager
, "/", "Popups", NULL
, GTK_UI_MANAGER_MENUBAR
);
1250 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups", "ABTreePopup", "ABTreePopup", GTK_UI_MANAGER_MENU
)
1251 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABTreePopup", "EditBook", "ABTreePopup/EditBook", GTK_UI_MANAGER_MENUITEM
)
1252 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABTreePopup", "DeleteBook", "ABTreePopup/DeleteBook", GTK_UI_MANAGER_MENUITEM
)
1253 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABTreePopup", "Separator1", "ABTreePopup/---", GTK_UI_MANAGER_SEPARATOR
)
1254 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABTreePopup", "NewBook", "ABTreePopup/NewBook", GTK_UI_MANAGER_MENUITEM
)
1255 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABTreePopup", "NewFolder", "ABTreePopup/NewFolder", GTK_UI_MANAGER_MENUITEM
)
1256 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABTreePopup", "NewGroup", "ABTreePopup/NewGroup", GTK_UI_MANAGER_MENUITEM
)
1257 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABTreePopup", "Separator2", "ABTreePopup/---", GTK_UI_MANAGER_SEPARATOR
)
1258 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABTreePopup", "Cut", "ABTreePopup/Cut", GTK_UI_MANAGER_MENUITEM
)
1259 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABTreePopup", "Copy", "ABTreePopup/Copy", GTK_UI_MANAGER_MENUITEM
)
1260 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABTreePopup", "Paste", "ABTreePopup/Paste", GTK_UI_MANAGER_MENUITEM
)
1262 tree_popup
= gtk_menu_item_get_submenu(GTK_MENU_ITEM(
1263 gtk_ui_manager_get_widget(ui_manager
, "/Popups/ABTreePopup")));
1265 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups", "ABListPopup", "ABListPopup", GTK_UI_MANAGER_MENU
)
1266 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "SelectAll", "ABListPopup/SelectAll", GTK_UI_MANAGER_MENUITEM
)
1267 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "Separator1", "ABListPopup/---", GTK_UI_MANAGER_SEPARATOR
)
1268 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "Edit", "ABListPopup/Edit", GTK_UI_MANAGER_MENUITEM
)
1269 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "Delete", "ABListPopup/Delete", GTK_UI_MANAGER_MENUITEM
)
1270 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "Separator2", "ABListPopup/---", GTK_UI_MANAGER_SEPARATOR
)
1271 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "NewAddress", "ABListPopup/NewAddress", GTK_UI_MANAGER_MENUITEM
)
1272 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "NewGroup", "ABListPopup/NewGroup", GTK_UI_MANAGER_MENUITEM
)
1273 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "Separator3", "ABListPopup/---", GTK_UI_MANAGER_SEPARATOR
)
1274 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "Cut", "ABListPopup/Cut", GTK_UI_MANAGER_MENUITEM
)
1275 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "Copy", "ABListPopup/Copy", GTK_UI_MANAGER_MENUITEM
)
1276 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "Paste", "ABListPopup/Paste", GTK_UI_MANAGER_MENUITEM
)
1277 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "Separator4", "ABListPopup/---", GTK_UI_MANAGER_SEPARATOR
)
1278 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "Mailto", "ABListPopup/Mailto", GTK_UI_MANAGER_MENUITEM
)
1280 MENUITEM_ADDUI_MANAGER(ui_manager
, "/Popups/ABListPopup", "BrowseEntry", "ABListPopup/BrowseEntry", GTK_UI_MANAGER_MENUITEM
)
1282 list_popup
= gtk_menu_item_get_submenu(GTK_MENU_ITEM(
1283 gtk_ui_manager_get_widget(ui_manager
, "/Popups/ABListPopup")));
1285 addrbook
.window
= window
;
1286 addrbook
.hpaned
= hpaned
;
1287 addrbook
.vpaned
= vpaned
;
1288 addrbook
.menubar
= menubar
;
1289 addrbook
.ctree
= ctree
;
1292 addrbook
.editaddress_vbox
= editaddress_vbox
;
1293 addrbook
.clist
= clist
;
1294 addrbook
.label
= label
;
1295 addrbook
.entry
= entry
;
1296 addrbook
.statusbar
= statusbar
;
1297 addrbook
.status_cid
= gtk_statusbar_get_context_id(
1298 GTK_STATUSBAR(statusbar
), "Addressbook Window" );
1300 addrbook
.help_btn
= help_btn
;
1301 addrbook
.edit_btn
= edit_btn
;
1302 addrbook
.del_btn
= del_btn
;
1303 addrbook
.reg_btn
= reg_btn
;
1304 addrbook
.lup_btn
= lup_btn
;
1305 addrbook
.to_btn
= to_btn
;
1306 addrbook
.cc_btn
= cc_btn
;
1307 addrbook
.bcc_btn
= bcc_btn
;
1309 addrbook
.tree_popup
= tree_popup
;
1310 addrbook
.list_popup
= list_popup
;
1311 addrbook
.ui_manager
= ui_manager
;
1313 addrbook
.listSelected
= NULL
;
1315 if (!geometry
.min_height
) {
1316 geometry
.min_width
= ADDRESSBOOK_WIDTH
;
1317 geometry
.min_height
= ADDRESSBOOK_HEIGHT
;
1320 gtk_window_set_geometry_hints(GTK_WINDOW(window
), NULL
, &geometry
,
1322 gtk_widget_set_size_request(window
, prefs_common
.addressbookwin_width
,
1323 prefs_common
.addressbookwin_height
);
1325 gtk_window_move(GTK_WINDOW(window
), 48, 48);
1328 if (!prefs_common
.addressbook_use_editaddress_dialog
) {
1329 if (prefs_common
.addressbook_vpaned_pos
> 0)
1330 gtk_paned_set_position(GTK_PANED(vpaned
),
1331 prefs_common
.addressbook_vpaned_pos
);
1333 if (prefs_common
.addressbook_hpaned_pos
> 0)
1334 gtk_paned_set_position(GTK_PANED(hpaned
),
1335 prefs_common
.addressbook_hpaned_pos
);
1338 gtk_widget_show_all(window
);
1342 * Close address book window and save to file(s).
1344 static gint
addressbook_close( void ) {
1345 address_completion_end(addrbook
.window
);
1346 if (!prefs_common
.addressbook_use_editaddress_dialog
)
1347 addressbook_edit_person_invalidate(NULL
, NULL
, NULL
);
1349 addressbook_pane_save_position();
1351 gtk_widget_hide(addrbook
.window
);
1352 addressbook_export_to_file();
1357 * Display message in status line.
1358 * \param msg Message to display.
1360 static void addressbook_status_show( gchar
*msg
) {
1361 if( addrbook
.statusbar
!= NULL
) {
1363 GTK_STATUSBAR(addrbook
.statusbar
),
1364 addrbook
.status_cid
);
1367 GTK_STATUSBAR(addrbook
.statusbar
),
1368 addrbook
.status_cid
, msg
);
1373 static void addressbook_ds_show_message( AddressDataSource
*ds
) {
1377 *addressbook_msgbuf
= '\0';
1379 name
= addrindex_ds_get_name( ds
);
1380 retVal
= addrindex_ds_get_status_code( ds
);
1381 if( retVal
== MGU_SUCCESS
) {
1382 g_snprintf( addressbook_msgbuf
,
1383 sizeof(addressbook_msgbuf
), "%s", name
);
1386 desc
= addressbook_err2string( _lutErrorsGeneral_
, retVal
);
1387 g_snprintf( addressbook_msgbuf
,
1388 sizeof(addressbook_msgbuf
), "%s: %s", name
, desc
);
1391 addressbook_status_show( addressbook_msgbuf
);
1394 static void addressbook_edit_clicked(GtkButton
*button
, gpointer data
)
1396 addressbook_edit_address_cb(NULL
, NULL
);
1399 static gboolean
find_person(AddrSelectItem
*item_a
, ItemPerson
*person
)
1401 return ((ItemPerson
*)item_a
->addressItem
== person
)?0:-1;
1405 * Delete one or more objects from address list.
1407 static void addressbook_del_clicked(GtkButton
*button
, gpointer data
)
1409 GtkCMCTree
*clist
= GTK_CMCTREE(addrbook
.clist
);
1410 GtkCMCTree
*ctree
= GTK_CMCTREE(addrbook
.ctree
);
1411 AddressObject
*pobj
;
1412 AdapterDSource
*ads
= NULL
;
1413 GtkCMCTreeNode
*nodeList
;
1416 AddressBookFile
*abf
= NULL
;
1417 AddressDataSource
*ds
= NULL
;
1418 AddressInterface
*iface
;
1419 AddrItemObject
*aio
;
1420 AddrSelectItem
*item
;
1422 gboolean refreshList
= FALSE
;
1424 pobj
= gtk_cmctree_node_get_row_data(ctree
, addrbook
.opened
);
1425 cm_return_if_fail(pobj
!= NULL
);
1427 /* Test whether anything selected for deletion */
1428 nodeList
= addrbook
.listSelected
;
1430 aio
= gtk_cmctree_node_get_row_data( clist
, nodeList
);
1431 if( aio
== NULL
) return;
1432 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
1433 if( ds
== NULL
) return;
1435 /* Test for read only */
1436 iface
= ds
->interface
;
1437 if( iface
->readOnly
) {
1438 alertpanel( _("Delete address(es)"),
1439 _("This address data is readonly and cannot be deleted."),
1440 GTK_STOCK_CLOSE
, NULL
, NULL
);
1444 /* Test whether Ok to proceed */
1446 if( pobj
->type
== ADDR_DATASOURCE
) {
1447 ads
= ADAPTER_DSOURCE(pobj
);
1448 if( ads
->subType
== ADDR_BOOK
) procFlag
= TRUE
;
1450 else if( pobj
->type
== ADDR_ITEM_FOLDER
) {
1453 else if( pobj
->type
== ADDR_ITEM_GROUP
) {
1456 if( ! procFlag
) return;
1457 abf
= ds
->rawDataSource
;
1458 if( abf
== NULL
) return;
1460 gtk_cmclist_freeze(GTK_CMCLIST(addrbook
.clist
));
1461 g_signal_handlers_block_by_func
1462 (G_OBJECT(addrbook
.clist
),
1463 G_CALLBACK(addressbook_list_row_unselected
), NULL
);
1465 /* Process deletions */
1466 if( pobj
->type
== ADDR_DATASOURCE
|| pobj
->type
== ADDR_ITEM_FOLDER
) {
1467 GList
*groups
= NULL
, *persons
= NULL
, *emails
= NULL
;
1468 gboolean group_delete
= TRUE
;
1469 /* Items inside folders */
1470 list
= addrselect_get_list( _addressSelect_
);
1471 /* Confirm deletion */
1475 node
= g_list_next( node
);
1476 aio
= ( AddrItemObject
* ) item
->addressItem
;
1477 if( aio
->type
== ITEMTYPE_PERSON
|| aio
->type
== ITEMTYPE_EMAIL
) {
1478 group_delete
= FALSE
;
1483 aval
= alertpanel( _("Delete group"),
1484 _("Really delete the group(s)?\n"
1485 "The addresses it contains will not be lost."),
1486 GTK_STOCK_CANCEL
, "+"GTK_STOCK_DELETE
, NULL
);
1487 if( aval
!= G_ALERTALTERNATE
) {
1491 aval
= alertpanel( _("Delete address(es)"),
1492 _("Really delete the address(es)?"),
1493 GTK_STOCK_CANCEL
, "+"GTK_STOCK_DELETE
, NULL
);
1494 if( aval
!= G_ALERTALTERNATE
) {
1499 /* first, set lists of groups and persons to remove */
1503 node
= g_list_next( node
);
1504 aio
= ( AddrItemObject
* ) item
->addressItem
;
1507 if( aio
->type
== ITEMTYPE_GROUP
) {
1508 groups
= g_list_prepend(groups
, item
);
1510 else if( aio
->type
== ITEMTYPE_PERSON
) {
1511 persons
= g_list_prepend(persons
, item
);
1514 /* then set list of emails to remove *if* they're not children of
1515 * persons to remove */
1519 node
= g_list_next( node
);
1520 aio
= ( AddrItemObject
* ) item
->addressItem
;
1523 if( aio
->type
== ITEMTYPE_EMAIL
) {
1524 ItemEMail
*sitem
= ( ItemEMail
* ) aio
;
1525 ItemPerson
*person
= ( ItemPerson
* ) ADDRITEM_PARENT(sitem
);
1526 if (!g_list_find_custom(persons
, person
, (GCompareFunc
)(find_person
))) {
1527 emails
= g_list_prepend(emails
, item
);
1529 /* else, the email will be removed via the parent person */
1532 /* then delete groups */
1536 node
= g_list_next( node
);
1537 aio
= ( AddrItemObject
* ) item
->addressItem
;
1540 if( aio
->type
== ITEMTYPE_GROUP
) {
1541 ItemGroup
*item
= ( ItemGroup
* ) aio
;
1542 GtkCMCTreeNode
*nd
= NULL
;
1543 nd
= addressbook_find_group_node( addrbook
.opened
, item
);
1544 item
= addrbook_remove_group( abf
, item
);
1546 addritem_free_item_group( item
);
1548 /* Remove group from parent node */
1549 gtk_cmctree_remove_node( ctree
, nd
);
1553 /* then delete persons */
1557 node
= g_list_next( node
);
1558 aio
= ( AddrItemObject
* ) item
->addressItem
;
1561 if( aio
->type
== ITEMTYPE_PERSON
) {
1562 ItemPerson
*item
= ( ItemPerson
* ) aio
;
1563 item
->status
= DELETE_ENTRY
;
1564 addressbook_folder_remove_one_person( clist
, item
);
1565 if (pobj
->type
== ADDR_ITEM_FOLDER
)
1566 addritem_folder_remove_person(ADAPTER_FOLDER(pobj
)->itemFolder
, item
);
1567 item
= addrbook_remove_person( abf
, item
);
1569 if (ds
&& ds
->type
== ADDR_IF_LDAP
) {
1570 LdapServer
*server
= ds
->rawDataSource
;
1571 ldapsvr_set_modified(server
, TRUE
);
1572 ldapsvr_update_book(server
, item
);
1576 gchar
*filename
= addritem_person_get_picture(item
);
1577 if (filename
&& is_file_exist(filename
))
1578 claws_unlink(filename
);
1580 addritem_free_item_person( item
);
1584 /* then delete emails */
1588 node
= g_list_next( node
);
1589 aio
= ( AddrItemObject
* ) item
->addressItem
;
1593 if( aio
->type
== ITEMTYPE_EMAIL
) {
1594 ItemEMail
*sitem
= ( ItemEMail
* ) aio
;
1595 ItemPerson
*person
= ( ItemPerson
* ) ADDRITEM_PARENT(sitem
);
1596 sitem
= addrbook_person_remove_email( abf
, person
, sitem
);
1598 addrcache_remove_email(abf
->addressCache
, sitem
);
1599 addritem_free_item_email( sitem
);
1601 addressbook_folder_refresh_one_person( clist
, person
);
1604 g_list_free( groups
);
1605 g_list_free( persons
);
1606 g_list_free( emails
);
1607 g_list_free( list
);
1608 addressbook_list_select_clear();
1610 gtk_sctree_select( GTK_SCTREE(ctree
), addrbook
.opened
);
1611 addressbook_set_clist(
1612 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook
.ctree
),
1616 addrbook_set_dirty(abf
, TRUE
);
1617 addressbook_export_to_file();
1618 addressbook_list_menu_setup();
1621 else if( pobj
->type
== ADDR_ITEM_GROUP
) {
1622 /* Items inside groups */
1623 list
= addrselect_get_list( _addressSelect_
);
1627 node
= g_list_next( node
);
1628 aio
= ( AddrItemObject
* ) item
->addressItem
;
1629 if( aio
->type
== ITEMTYPE_EMAIL
) {
1630 ItemEMail
*item
= ( ItemEMail
* ) aio
;
1631 ItemPerson
*person
= ( ItemPerson
* ) ADDRITEM_PARENT(item
);
1632 item
= addrbook_person_remove_email( abf
, person
, item
);
1634 addritem_free_item_email( item
);
1638 g_list_free( list
);
1639 addressbook_list_select_clear();
1640 gtk_sctree_select( GTK_SCTREE(ctree
), addrbook
.opened
);
1641 addressbook_set_clist(
1642 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook
.ctree
),
1646 addrbook_set_dirty(abf
, TRUE
);
1647 addressbook_export_to_file();
1648 addressbook_list_menu_setup();
1652 gtk_cmctree_node_set_row_data( clist
, nodeList
, NULL
);
1653 gtk_cmctree_remove_node( clist
, nodeList
);
1655 gtk_cmclist_thaw(GTK_CMCLIST(addrbook
.clist
));
1656 g_signal_handlers_unblock_by_func
1657 (G_OBJECT(addrbook
.clist
),
1658 G_CALLBACK(addressbook_list_row_unselected
), NULL
);
1661 static void addressbook_reg_clicked(GtkButton
*button
, gpointer data
)
1663 addressbook_new_address_cb( NULL
, NULL
);
1666 static gchar
*addressbook_format_address( AddrItemObject
* aio
) {
1669 gchar
*address
= NULL
;
1671 if( aio
->type
== ITEMTYPE_EMAIL
) {
1672 ItemPerson
*person
= NULL
;
1673 ItemEMail
*email
= ( ItemEMail
* ) aio
;
1675 person
= ( ItemPerson
* ) ADDRITEM_PARENT(email
);
1676 if( email
->address
) {
1677 if( ADDRITEM_NAME(email
) ) {
1678 name
= ADDRITEM_NAME(email
);
1679 if( *name
== '\0' ) {
1680 name
= ADDRITEM_NAME(person
);
1683 else if( ADDRITEM_NAME(person
) ) {
1684 name
= ADDRITEM_NAME(person
);
1687 buf
= g_strdup( email
->address
);
1689 address
= email
->address
;
1692 else if( aio
->type
== ITEMTYPE_PERSON
) {
1693 ItemPerson
*person
= ( ItemPerson
* ) aio
;
1694 GList
*node
= person
->listEMail
;
1696 name
= ADDRITEM_NAME(person
);
1698 ItemEMail
*email
= ( ItemEMail
* ) node
->data
;
1699 address
= email
->address
;
1703 if( name
&& name
[0] != '\0' ) {
1704 if( strchr_with_skip_quote( name
, '"', ',' ) )
1705 buf
= g_strdup_printf( "\"%s\" <%s>", name
, address
);
1707 buf
= g_strdup_printf( "%s <%s>", name
, address
);
1710 buf
= g_strdup( address
);
1717 static void addressbook_to_clicked(GtkButton
*button
, gpointer data
)
1721 AddrSelectItem
*item
;
1722 AddrItemObject
*aio
;
1725 compose
= addrbook
.target_compose
;
1726 if( ! compose
) return;
1728 /* Nothing selected, but maybe there is something in text entry */
1729 addr
= (char *)gtk_entry_get_text( GTK_ENTRY( addrbook
.entry
) );
1731 compose_entry_append(
1732 compose
, addr
, (ComposeEntryType
)data
, PREF_NONE
);
1735 /* Select from address list */
1736 list
= addrselect_get_list( _addressSelect_
);
1741 node
= g_list_next( node
);
1742 aio
= item
->addressItem
;
1743 if( aio
->type
== ITEMTYPE_PERSON
||
1744 aio
->type
== ITEMTYPE_EMAIL
) {
1745 addr
= addressbook_format_address( aio
);
1746 compose_entry_append(
1747 compose
, addr
, (ComposeEntryType
) data
, PREF_NONE
);
1750 else if( aio
->type
== ITEMTYPE_GROUP
) {
1751 ItemGroup
*group
= ( ItemGroup
* ) aio
;
1752 GList
*nodeMail
= group
->listEMail
;
1754 ItemEMail
*email
= nodeMail
->data
;
1756 addr
= addressbook_format_address(
1757 ( AddrItemObject
* ) email
);
1758 compose_entry_append(
1759 compose
, addr
, (ComposeEntryType
) data
, PREF_NONE
);
1761 nodeMail
= g_list_next( nodeMail
);
1766 AddressObject
*obj
= NULL
;
1768 obj
= gtk_cmctree_node_get_row_data( GTK_CMCTREE(addrbook
.ctree
), addrbook
.treeSelected
);
1770 if( obj
&& obj
->type
== ADDR_ITEM_GROUP
) {
1771 ItemGroup
*itemGroup
= ADAPTER_GROUP(obj
)->itemGroup
;
1772 GList
*nodeMail
= itemGroup
->listEMail
;
1774 ItemEMail
*email
= nodeMail
->data
;
1776 addr
= addressbook_format_address(
1777 ( AddrItemObject
* ) email
);
1778 compose_entry_append(
1779 compose
, addr
, (ComposeEntryType
) data
, PREF_NONE
);
1781 nodeMail
= g_list_next( nodeMail
);
1785 g_list_free( list
);
1788 static void addressbook_menubar_set_sensitive( gboolean sensitive
) {
1789 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Book/EditBook", sensitive
);
1790 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Book/DeleteBook", sensitive
);
1791 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Book/NewFolder", sensitive
);
1793 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/SelectAll", TRUE
);
1794 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Cut", sensitive
);
1795 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Copy", sensitive
);
1796 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Paste", sensitive
);
1798 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/NewAddress", sensitive
);
1799 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/NewGroup", sensitive
);
1800 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Mailto", sensitive
);
1801 gtk_widget_set_sensitive( addrbook
.edit_btn
, sensitive
);
1802 gtk_widget_set_sensitive( addrbook
.del_btn
, sensitive
);
1805 static void addressbook_menuitem_set_sensitive( AddressObject
*obj
, GtkCMCTreeNode
*node
) {
1806 gboolean canEdit
= FALSE
;
1807 gboolean canDelete
= TRUE
;
1808 gboolean canAdd
= FALSE
;
1809 gboolean canEditTr
= TRUE
;
1810 gboolean editAddress
= FALSE
;
1811 gboolean canExport
= TRUE
;
1812 AddressTypeControlItem
*atci
= NULL
;
1813 AddressDataSource
*ds
= NULL
;
1814 AddressInterface
*iface
= NULL
;
1816 if( obj
== NULL
) return;
1817 if( obj
->type
== ADDR_INTERFACE
) {
1818 AdapterInterface
*adapter
= ADAPTER_INTERFACE(obj
);
1819 iface
= adapter
->interface
;
1821 if( iface
->haveLibrary
) {
1822 /* Enable appropriate File / New command */
1823 atci
= adapter
->atci
;
1824 cm_menu_set_sensitive_full(addrbook
.ui_manager
, atci
->menuCommand
, TRUE
);
1827 canEditTr
= canExport
= FALSE
;
1829 else if( obj
->type
== ADDR_DATASOURCE
) {
1830 AdapterDSource
*ads
= ADAPTER_DSOURCE(obj
);
1831 ds
= ads
->dataSource
;
1832 iface
= ds
->interface
;
1833 if( ! iface
->readOnly
) {
1834 canAdd
= canEdit
= editAddress
= canDelete
= TRUE
;
1836 if( ! iface
->haveLibrary
) {
1837 canAdd
= canEdit
= editAddress
= canExport
= canDelete
= FALSE
;
1840 else if( obj
->type
== ADDR_ITEM_FOLDER
) {
1841 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
1843 iface
= ds
->interface
;
1844 if( iface
->readOnly
) {
1849 canAdd
= editAddress
= TRUE
;
1853 else if( obj
->type
== ADDR_ITEM_GROUP
) {
1854 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
1856 iface
= ds
->interface
;
1857 if( ! iface
->readOnly
) {
1863 if( addrbook
.listSelected
== NULL
)
1867 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/NewAddress", editAddress
);
1868 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/NewGroup", canAdd
);
1869 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Book/NewFolder", canAdd
);
1870 gtk_widget_set_sensitive( addrbook
.reg_btn
, editAddress
);
1873 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Edit", canEdit
);
1874 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Delete", canDelete
);
1875 gtk_widget_set_sensitive( addrbook
.edit_btn
, canEdit
);
1876 gtk_widget_set_sensitive( addrbook
.del_btn
, canDelete
);
1878 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Book/EditBook", canEditTr
);
1879 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Book/DeleteBook", canEditTr
);
1882 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Tools/ExportHTML", canExport
);
1883 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Tools/ExportLDIF", canExport
);
1887 * Address book tree callback function that responds to selection of tree
1890 * \param ctree Tree widget.
1891 * \param node Node that was selected.
1892 * \param column Column number where selected occurred.
1893 * \param data Pointer to user data.
1895 static void addressbook_tree_selected(GtkCMCTree
*ctree
, GtkCMCTreeNode
*node
,
1896 gint column
, gpointer data
)
1898 AddressObject
*obj
= NULL
;
1899 AdapterDSource
*ads
= NULL
;
1900 AddressDataSource
*ds
= NULL
;
1901 ItemFolder
*rootFolder
= NULL
;
1902 AddressObjectType aot
;
1904 addrbook
.treeSelected
= node
;
1905 addrbook
.listSelected
= NULL
;
1906 addressbook_status_show( "" );
1907 if( addrbook
.entry
!= NULL
) gtk_entry_set_text(GTK_ENTRY(addrbook
.entry
), "");
1909 if( node
) obj
= gtk_cmctree_node_get_row_data( ctree
, node
);
1911 addressbook_set_clist(NULL
, TRUE
);
1914 addrbook
.opened
= node
;
1916 if( obj
->type
== ADDR_DATASOURCE
) {
1917 /* Read from file */
1918 static gboolean tVal
= TRUE
;
1920 ads
= ADAPTER_DSOURCE(obj
);
1922 ds
= ads
->dataSource
;
1923 if( ds
== NULL
) return;
1925 if( addrindex_ds_get_modify_flag( ds
) ) {
1926 addrindex_ds_read_data( ds
);
1929 if( ! addrindex_ds_get_read_flag( ds
) ) {
1930 addrindex_ds_read_data( ds
);
1932 addressbook_ds_show_message( ds
);
1934 if( ! addrindex_ds_get_access_flag( ds
) ) {
1935 /* Remove existing folders and groups */
1936 gtk_cmclist_freeze( GTK_CMCLIST(ctree
) );
1937 addressbook_tree_remove_children( ctree
, node
);
1938 gtk_cmclist_thaw( GTK_CMCLIST(ctree
) );
1940 /* Load folders into the tree */
1941 rootFolder
= addrindex_ds_get_root_folder( ds
);
1942 if( ds
&& ds
->type
== ADDR_IF_JPILOT
) {
1943 aot
= ADDR_CATEGORY
;
1945 else if( ds
&& ds
->type
== ADDR_IF_LDAP
) {
1946 aot
= ADDR_LDAP_QUERY
;
1949 aot
= ADDR_ITEM_FOLDER
;
1951 addressbook_node_add_folder( node
, ds
, rootFolder
, aot
);
1952 addrindex_ds_set_access_flag( ds
, &tVal
);
1953 gtk_cmctree_expand( ctree
, node
);
1956 addressbook_set_clist(NULL
, TRUE
);
1959 /* Update address list */
1960 g_signal_handlers_block_by_func
1962 G_CALLBACK(addressbook_tree_selected
), NULL
);
1963 addressbook_set_clist( obj
, FALSE
);
1964 g_signal_handlers_unblock_by_func
1966 G_CALLBACK(addressbook_tree_selected
), NULL
);
1967 if (!prefs_common
.addressbook_use_editaddress_dialog
)
1968 addressbook_edit_person_invalidate(NULL
, NULL
, NULL
);
1970 /* Setup main menu selections */
1971 addressbook_menubar_set_sensitive( FALSE
);
1972 addressbook_menuitem_set_sensitive( obj
, node
);
1973 addressbook_list_select_clear();
1974 addressbook_list_menu_setup();
1979 * Setup address list popup menu items. Items are enabled or disabled as
1982 static void addressbook_list_menu_setup( void ) {
1983 GtkCMCTree
*clist
= NULL
;
1984 AddressObject
*pobj
= NULL
;
1985 AddressObject
*obj
= NULL
;
1986 AdapterDSource
*ads
= NULL
;
1987 AddressInterface
*iface
= NULL
;
1988 AddressDataSource
*ds
= NULL
;
1989 gboolean canEdit
= FALSE
;
1990 gboolean canDelete
= FALSE
;
1991 gboolean canCut
= FALSE
;
1992 gboolean canCopy
= FALSE
;
1993 gboolean canPaste
= FALSE
;
1994 gboolean canBrowse
= FALSE
;
1996 pobj
= gtk_cmctree_node_get_row_data( GTK_CMCTREE(addrbook
.ctree
), addrbook
.treeSelected
);
1997 if( pobj
== NULL
) return;
1999 clist
= GTK_CMCTREE(addrbook
.clist
);
2000 obj
= gtk_cmctree_node_get_row_data( clist
, addrbook
.listSelected
);
2001 if( obj
== NULL
) canEdit
= FALSE
;
2003 menu_set_insensitive_all( GTK_MENU_SHELL(addrbook
.list_popup
) );
2004 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/SelectAll", TRUE
);
2006 if( pobj
->type
== ADDR_DATASOURCE
) {
2007 /* Parent object is a data source */
2008 ads
= ADAPTER_DSOURCE(pobj
);
2009 ds
= ads
->dataSource
;
2012 iface
= ds
->interface
;
2015 if( ! iface
->readOnly
) {
2016 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/NewAddress", TRUE
);
2017 if (iface
->type
!= ADDR_IF_LDAP
)
2018 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/NewGroup", TRUE
);
2019 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
2022 canDelete
= canEdit
;
2025 else if( pobj
->type
!= ADDR_INTERFACE
) {
2026 /* Parent object is not an interface */
2027 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
2030 iface
= ds
->interface
;
2033 if( ! iface
->readOnly
) {
2034 /* Folder or group */
2035 if( pobj
->type
== ADDR_ITEM_FOLDER
|| pobj
->type
== ADDR_ITEM_GROUP
) {
2036 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/NewAddress", TRUE
);
2037 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
2038 if( obj
) canEdit
= TRUE
;
2041 if( pobj
->type
== ADDR_ITEM_FOLDER
) {
2042 if (iface
->type
!= ADDR_IF_LDAP
)
2043 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/NewGroup", TRUE
);
2044 if( obj
) canEdit
= TRUE
;
2046 canDelete
= canEdit
;
2048 if( iface
->type
== ADDR_IF_LDAP
) {
2049 if( obj
) canBrowse
= TRUE
;
2056 /* Enable cut and paste */
2057 if( ! addrclip_is_empty( _clipBoard_
) )
2059 if( ! addrselect_test_empty( _addressSelect_
) )
2061 /* Enable copy if something is selected */
2062 if( ! addrselect_test_empty( _addressSelect_
) )
2066 /* Disable edit or browse if more than one row selected */
2067 if( GTK_CMCLIST(clist
)->selection
&& GTK_CMCLIST(clist
)->selection
->next
) {
2072 /* Forbid write changes when read-only */
2073 if( iface
&& iface
->readOnly
) {
2079 /* Now go finalize menu items */
2080 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/Edit", canEdit
);
2081 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/Delete", canDelete
);
2083 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/Cut", canCut
);
2084 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/Copy", canCopy
);
2085 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/Paste", canPaste
);
2087 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/Mailto", canCopy
);
2089 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Cut", canCut
);
2090 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Copy", canCopy
);
2091 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Paste", canPaste
);
2093 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Edit", canEdit
);
2094 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Delete", canDelete
);
2095 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Mailto", canCopy
);
2097 gtk_widget_set_sensitive( addrbook
.edit_btn
, canEdit
);
2098 gtk_widget_set_sensitive( addrbook
.del_btn
, canDelete
);
2100 if (addrbook
.target_compose
) {
2101 gtk_widget_set_sensitive(addrbook
.to_btn
, obj
? TRUE
: FALSE
);
2102 gtk_widget_set_sensitive(addrbook
.cc_btn
, obj
? TRUE
: FALSE
);
2103 gtk_widget_set_sensitive(addrbook
.bcc_btn
, obj
? TRUE
: FALSE
);
2106 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/BrowseEntry", canBrowse
);
2110 static void addressbook_select_row_tree (GtkCMCTree
*ctree
,
2111 GtkCMCTreeNode
*node
,
2118 * Add list of items into tree node below specified tree node.
2119 * \param treeNode Tree node.
2120 * \param ds Data source.
2121 * \param listItems List of items.
2123 static void addressbook_treenode_add_list(
2124 GtkCMCTreeNode
*treeNode
, AddressDataSource
*ds
, GList
*listItems
)
2130 AddrItemObject
*aio
;
2134 if( ADDRESS_OBJECT_TYPE(aio
) == ADDR_ITEM_GROUP
) {
2137 group
= ( ItemGroup
* ) aio
;
2138 nn
= addressbook_node_add_group( treeNode
, ds
, group
);
2140 g_message("error adding addressbook group\n");
2143 else if( ADDRESS_OBJECT_TYPE(aio
) == ADDR_ITEM_FOLDER
) {
2146 folder
= ( ItemFolder
* ) aio
;
2147 nn
= addressbook_node_add_folder(
2148 treeNode
, ds
, folder
, ADDR_ITEM_FOLDER
);
2150 g_message("error adding addressbook folder\n");
2153 node
= g_list_next( node
);
2157 static void addressbook_select_all_cb( GtkAction
*action
, gpointer data
) {
2158 gtk_cmclist_select_all(GTK_CMCLIST(addrbook
.clist
));
2162 * Cut from address list widget.
2164 static void addressbook_clip_cut_cb( GtkAction
*action
, gpointer data
) {
2165 _clipBoard_
->cutFlag
= TRUE
;
2166 addrclip_clear( _clipBoard_
);
2167 addrclip_add( _clipBoard_
, _addressSelect_
);
2168 /* addrclip_list_show( _clipBoard_, stdout ); */
2172 * Copy from address list widget.
2174 static void addressbook_clip_copy_cb(GtkAction
*action
, gpointer data
) {
2175 _clipBoard_
->cutFlag
= FALSE
;
2176 addrclip_clear( _clipBoard_
);
2177 addrclip_add( _clipBoard_
, _addressSelect_
);
2178 /* addrclip_list_show( _clipBoard_, stdout ); */
2182 * Paste clipboard into address list widget.
2184 static void addressbook_clip_paste_cb( GtkAction
*action
, gpointer data
) {
2185 GtkCMCTree
*ctree
= GTK_CMCTREE( addrbook
.ctree
);
2186 AddressObject
*pobj
= NULL
;
2187 AddressDataSource
*ds
= NULL
;
2188 AddressBookFile
*abf
= NULL
;
2189 ItemFolder
*folder
= NULL
;
2190 GList
*folderGroup
= NULL
;
2192 ds
= addressbook_find_datasource( GTK_CMCTREE_NODE(addrbook
.treeSelected
) );
2193 if( ds
== NULL
) return;
2194 if( addrindex_ds_get_readonly( ds
) ) {
2195 alertpanel_error( _("Cannot paste. Target address book is readonly.") );
2199 pobj
= gtk_cmctree_node_get_row_data( ctree
, addrbook
.treeSelected
);
2201 if( pobj
->type
== ADDR_ITEM_FOLDER
) {
2202 folder
= ADAPTER_FOLDER(pobj
)->itemFolder
;
2204 else if( pobj
->type
== ADDR_ITEM_GROUP
) {
2205 alertpanel_error( _("Cannot paste into an address group.") );
2210 /* Get an address book */
2211 abf
= addressbook_get_book_file();
2212 if( abf
== NULL
) return;
2214 if( _clipBoard_
->cutFlag
) {
2216 folderGroup
= addrclip_paste_cut( _clipBoard_
, abf
, folder
);
2218 /* Remove all groups and folders in clipboard from tree node */
2219 addressbook_treenode_remove_item();
2221 /* Remove all "cut" items */
2222 addrclip_delete_item( _clipBoard_
);
2224 /* Clear clipboard - cut items??? */
2225 addrclip_clear( _clipBoard_
);
2229 folderGroup
= addrclip_paste_copy( _clipBoard_
, abf
, folder
);
2232 /* addrclip_list_show( _clipBoard_, stdout ); */
2234 /* Update tree by inserting node for each folder or group */
2235 addressbook_treenode_add_list(
2236 addrbook
.treeSelected
, ds
, folderGroup
);
2237 gtk_cmctree_expand( ctree
, addrbook
.treeSelected
);
2238 g_list_free( folderGroup
);
2242 /* Display items pasted */
2243 gtk_sctree_select( GTK_SCTREE(ctree
), addrbook
.opened
);
2244 addressbook_set_clist(
2245 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook
.ctree
),
2253 * Add current treenode object to clipboard. Note that widget only allows
2254 * one entry from the tree list to be selected.
2256 static void addressbook_treenode_to_clipboard( void ) {
2257 AddressObject
*obj
= NULL
;
2258 AddressDataSource
*ds
= NULL
;
2259 AddrSelectItem
*item
;
2260 GtkCMCTree
*ctree
= GTK_CMCTREE( addrbook
.ctree
);
2261 GtkCMCTreeNode
*node
;
2263 node
= addrbook
.treeSelected
;
2264 if( node
== NULL
) return;
2265 obj
= gtk_cmctree_node_get_row_data( ctree
, node
);
2266 if( obj
== NULL
) return;
2268 ds
= addressbook_find_datasource( node
);
2269 if( ds
== NULL
) return;
2272 if( obj
->type
== ADDR_ITEM_FOLDER
) {
2273 AdapterFolder
*adapter
= ADAPTER_FOLDER(obj
);
2274 ItemFolder
*folder
= adapter
->itemFolder
;
2276 item
= addrselect_create_node( obj
);
2277 item
->uid
= g_strdup( ADDRITEM_ID(folder
) );
2279 else if( obj
->type
== ADDR_ITEM_GROUP
) {
2280 AdapterGroup
*adapter
= ADAPTER_GROUP(obj
);
2281 ItemGroup
*group
= adapter
->itemGroup
;
2283 item
= addrselect_create_node( obj
);
2284 item
->uid
= g_strdup( ADDRITEM_ID(group
) );
2286 else if( obj
->type
== ADDR_DATASOURCE
) {
2288 item
= addrselect_create_node( obj
);
2293 /* Clear existing list and add item into list */
2296 addressbook_list_select_clear();
2297 cacheID
= addrindex_get_cache_id( _addressIndex_
, ds
);
2298 addrselect_list_add( _addressSelect_
, item
, cacheID
);
2304 * Cut from tree widget.
2306 static void addressbook_treenode_cut_cb( GtkAction
*action
, gpointer data
) {
2307 _clipBoard_
->cutFlag
= TRUE
;
2308 addressbook_treenode_to_clipboard();
2309 addrclip_clear( _clipBoard_
);
2310 addrclip_add( _clipBoard_
, _addressSelect_
);
2311 /* addrclip_list_show( _clipBoard_, stdout ); */
2315 * Copy from tree widget.
2317 static void addressbook_treenode_copy_cb( GtkAction
*action
, gpointer data
) {
2318 _clipBoard_
->cutFlag
= FALSE
;
2319 addressbook_treenode_to_clipboard();
2320 addrclip_clear( _clipBoard_
);
2321 addrclip_add( _clipBoard_
, _addressSelect_
);
2322 /* addrclip_list_show( _clipBoard_, stdout ); */
2326 * Paste clipboard into address tree widget.
2328 static void addressbook_treenode_paste_cb( GtkAction
*action
, gpointer data
) {
2329 addressbook_clip_paste_cb(NULL
,NULL
);
2333 * Clear selected entries in clipboard.
2335 static void addressbook_list_select_clear( void ) {
2336 addrselect_list_clear( _addressSelect_
);
2340 * Add specified address item to selected address list.
2341 * \param aio Address item object.
2342 * \param ds Datasource.
2344 static void addressbook_list_select_add( AddrItemObject
*aio
, AddressDataSource
*ds
) {
2347 if( ds
== NULL
) return;
2348 cacheID
= addrindex_get_cache_id( _addressIndex_
, ds
);
2349 addrselect_list_add_obj( _addressSelect_
, aio
, cacheID
);
2354 * Remove specified address item from selected address list.
2355 * \param aio Address item object.
2357 static void addressbook_list_select_remove( AddrItemObject
*aio
) {
2358 addrselect_list_remove( _addressSelect_
, aio
);
2362 * Invoke EMail compose window with addresses in selected address list.
2364 static void addressbook_mail_to_cb( GtkAction
*action
, gpointer data
) {
2367 if( ! addrselect_test_empty( _addressSelect_
) ) {
2368 listAddress
= addrselect_build_list( _addressSelect_
);
2369 compose_new_with_list( NULL
, listAddress
);
2370 mgu_free_dlist( listAddress
);
2375 static void addressbook_list_row_selected( GtkCMCTree
*clist
,
2376 GtkCMCTreeNode
*node
,
2380 AddrItemObject
*aio
= NULL
;
2381 AddressObject
*pobj
= NULL
;
2382 AdapterDSource
*ads
= NULL
;
2383 AddressDataSource
*ds
= NULL
;
2385 addrbook
.listSelected
= node
;
2387 pobj
= gtk_cmctree_node_get_row_data( GTK_CMCTREE(addrbook
.ctree
), addrbook
.treeSelected
);
2388 if( pobj
== NULL
) return;
2390 if( pobj
->type
== ADDR_DATASOURCE
) {
2391 ads
= ADAPTER_DSOURCE(pobj
);
2392 ds
= ads
->dataSource
;
2394 else if( pobj
->type
!= ADDR_INTERFACE
) {
2395 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
2398 aio
= gtk_cmctree_node_get_row_data( clist
, node
);
2400 /* g_print( "list select: %d : '%s'\n", aio->type, aio->name ); */
2401 addressbook_list_select_add( aio
, ds
);
2404 addressbook_list_menu_setup();
2406 if (!addrbook
.target_compose
&& !prefs_common
.addressbook_use_editaddress_dialog
) {
2407 AddressObject
*obj
= gtk_cmctree_node_get_row_data( clist
, addrbook
.listSelected
);
2409 if (obj
&& obj
->type
!= ADDR_ITEM_GROUP
)
2410 addressbook_edit_address(NULL
, 0, NULL
, FALSE
);
2414 static void addressbook_list_row_unselected( GtkCMCTree
*ctree
,
2415 GtkCMCTreeNode
*node
,
2419 AddrItemObject
*aio
;
2421 aio
= gtk_cmctree_node_get_row_data( ctree
, node
);
2423 /* g_print( "list unselect: %d : '%s'\n", aio->type, aio->name ); */
2424 addressbook_list_select_remove( aio
);
2427 if (!prefs_common
.addressbook_use_editaddress_dialog
)
2428 addressbook_edit_person_invalidate(NULL
, NULL
, NULL
);
2431 static void addressbook_entry_activated(GtkWidget
*widget
, gpointer data
)
2433 addressbook_lup_clicked(NULL
, NULL
);
2436 static gboolean
addressbook_list_button_pressed(GtkWidget
*widget
,
2437 GdkEventButton
*event
,
2440 if( ! event
) return FALSE
;
2442 addressbook_list_menu_setup();
2444 if( event
->button
== 3 ) {
2445 gtk_menu_popup( GTK_MENU(addrbook
.list_popup
), NULL
, NULL
, NULL
, NULL
,
2446 event
->button
, event
->time
);
2447 } else if (event
->button
== 1) {
2448 if (event
->type
== GDK_2BUTTON_PRESS
) {
2449 if (prefs_common
.add_address_by_click
&&
2450 addrbook
.target_compose
)
2451 addressbook_to_clicked(NULL
, GINT_TO_POINTER(COMPOSE_TO
));
2453 if (prefs_common
.addressbook_use_editaddress_dialog
)
2454 addressbook_edit_address_cb(NULL
, NULL
);
2456 GtkCMCTree
*clist
= GTK_CMCTREE(addrbook
.clist
);
2457 AddressObject
*obj
= gtk_cmctree_node_get_row_data( clist
, addrbook
.listSelected
);
2458 if( obj
&& obj
->type
== ADDR_ITEM_GROUP
)
2459 addressbook_edit_address_cb(NULL
, NULL
);
2467 static gboolean
addressbook_list_button_released(GtkWidget
*widget
,
2468 GdkEventButton
*event
,
2474 static gboolean
addressbook_tree_button_pressed(GtkWidget
*ctree
,
2475 GdkEventButton
*event
,
2478 GtkCMCList
*clist
= GTK_CMCLIST(ctree
);
2480 AddressObject
*obj
= NULL
;
2481 AdapterDSource
*ads
= NULL
;
2482 AddressInterface
*iface
= NULL
;
2483 AddressDataSource
*ds
= NULL
;
2484 gboolean canEdit
= FALSE
;
2485 gboolean canDelete
= FALSE
;
2486 gboolean canCut
= FALSE
;
2487 gboolean canCopy
= FALSE
;
2488 gboolean canPaste
= FALSE
;
2489 gboolean canTreeCut
= FALSE
;
2490 gboolean canTreeCopy
= FALSE
;
2491 gboolean canTreePaste
= FALSE
;
2492 gboolean canLookup
= FALSE
;
2493 GtkCMCTreeNode
*node
= NULL
;
2495 if( ! event
) return FALSE
;
2496 /* if( ! event || event->type != GDK_BUTTON_PRESS) return FALSE;*/
2498 if (event
->button
== 1) {
2499 if (event
->type
== GDK_2BUTTON_PRESS
) {
2500 if( gtk_cmclist_get_selection_info( clist
, event
->x
, event
->y
, &row
, &column
) ) {
2501 gtkut_clist_set_focus_row(clist
, row
);
2502 obj
= gtk_cmclist_get_row_data( clist
, row
);
2507 if (obj
->type
== ADDR_ITEM_GROUP
||
2508 obj
->type
== ADDR_DATASOURCE
) {
2510 addressbook_treenode_edit_cb(NULL
, NULL
);
2512 /* expand pr collapse */
2513 node
= gtk_cmctree_node_nth(GTK_CMCTREE(ctree
), row
);
2514 gtk_cmctree_toggle_expansion(GTK_CMCTREE(ctree
), node
);
2520 addressbook_menubar_set_sensitive( FALSE
);
2522 if( gtk_cmclist_get_selection_info( clist
, event
->x
, event
->y
, &row
, &column
) ) {
2523 gtkut_clist_set_focus_row(clist
, row
);
2524 obj
= gtk_cmclist_get_row_data( clist
, row
);
2527 menu_set_insensitive_all(GTK_MENU_SHELL(addrbook
.tree_popup
));
2531 node
= gtk_cmctree_node_nth(GTK_CMCTREE(clist
), row
);
2533 if( ! addrclip_is_empty( _clipBoard_
) )
2534 canTreePaste
= TRUE
;
2536 if (obj
->type
== ADDR_INTERFACE
) {
2537 AdapterInterface
*adapter
= ADAPTER_INTERFACE(obj
);
2538 iface
= adapter
->interface
;
2541 if( !iface
->readOnly
&& iface
->type
== ADDR_IF_BOOK
) {
2542 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABTreePopup/NewBook", TRUE
);
2544 if( iface
->externalQuery
)
2547 if (obj
->type
== ADDR_DATASOURCE
) {
2549 ads
= ADAPTER_DSOURCE(obj
);
2550 ds
= ads
->dataSource
;
2553 iface
= ds
->interface
;
2556 if( !iface
->readOnly
) {
2557 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABTreePopup/NewFolder", TRUE
);
2558 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABTreePopup/NewGroup", TRUE
);
2559 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
2565 else if (obj
->type
== ADDR_ITEM_FOLDER
) {
2567 ds
= addressbook_find_datasource( node
);
2570 iface
= ds
->interface
;
2573 if( !iface
->readOnly
) {
2577 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABTreePopup/NewFolder", TRUE
);
2578 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABTreePopup/NewGroup", TRUE
);
2579 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
2583 if( iface
->externalQuery
) {
2584 /* Enable deletion of LDAP folder */
2588 else if (obj
->type
== ADDR_ITEM_GROUP
) {
2590 ds
= addressbook_find_datasource( node
);
2593 iface
= ds
->interface
;
2596 if( ! iface
->readOnly
) {
2599 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABListPopup/NewAddress", TRUE
);
2600 gtk_widget_set_sensitive( addrbook
.reg_btn
, TRUE
);
2604 if( canEdit
&& !addrselect_test_empty( _addressSelect_
) )
2606 if( ! addrselect_test_empty( _addressSelect_
) )
2608 if( ! addrclip_is_empty( _clipBoard_
) )
2611 /* Forbid write changes when read-only */
2612 if( iface
&& iface
->readOnly
) {
2614 canTreePaste
= FALSE
;
2621 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABTreePopup/EditBook", canEdit
);
2622 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABTreePopup/DeleteBook", canDelete
);
2623 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABTreePopup/Cut", canTreeCut
);
2624 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABTreePopup/Copy", canTreeCopy
);
2625 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Popups/ABTreePopup/Paste", canTreePaste
);
2627 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Book/EditBook", canEdit
);
2628 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Book/DeleteBook", canDelete
);
2629 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Cut", canCut
);
2630 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Copy", canCopy
);
2631 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Paste", canPaste
);
2633 addressbook_show_buttons(addrbook
.target_compose
== NULL
, canLookup
,
2634 addrbook
.target_compose
!= NULL
);
2636 if( event
->button
== 3 )
2637 gtk_menu_popup(GTK_MENU(addrbook
.tree_popup
), NULL
, NULL
, NULL
, NULL
,
2638 event
->button
, event
->time
);
2643 static gboolean
addressbook_tree_button_released(GtkWidget
*ctree
,
2644 GdkEventButton
*event
,
2647 gtkut_ctree_set_focus_row(GTK_CMCTREE(addrbook
.ctree
), addrbook
.opened
);
2651 static void addressbook_new_folder_cb(GtkAction
*action
, gpointer data
)
2653 GtkCMCTree
*ctree
= GTK_CMCTREE(addrbook
.ctree
);
2654 AddressObject
*obj
= NULL
;
2655 AddressDataSource
*ds
= NULL
;
2656 AddressBookFile
*abf
= NULL
;
2657 ItemFolder
*parentFolder
= NULL
;
2658 ItemFolder
*folder
= NULL
;
2660 if( ! addrbook
.treeSelected
) return;
2661 obj
= gtk_cmctree_node_get_row_data( ctree
, addrbook
.treeSelected
);
2662 if( obj
== NULL
) return;
2663 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
2664 if( ds
== NULL
) return;
2666 if( obj
->type
== ADDR_DATASOURCE
) {
2667 if( ADAPTER_DSOURCE(obj
)->subType
!= ADDR_BOOK
) return;
2669 else if( obj
->type
== ADDR_ITEM_FOLDER
) {
2670 parentFolder
= ADAPTER_FOLDER(obj
)->itemFolder
;
2676 abf
= ds
->rawDataSource
;
2677 if( abf
== NULL
) return;
2678 folder
= addressbook_edit_folder( abf
, parentFolder
, NULL
);
2681 nn
= addressbook_node_add_folder(
2682 addrbook
.treeSelected
, ds
, folder
, ADDR_ITEM_FOLDER
);
2684 g_message("error adding addressbook folder\n");
2686 gtk_cmctree_expand( ctree
, addrbook
.treeSelected
);
2687 if( addrbook
.treeSelected
== addrbook
.opened
)
2688 addressbook_set_clist(obj
, TRUE
);
2692 static void addressbook_new_group_cb(GtkAction
*action
, gpointer data
)
2694 GtkCMCTree
*ctree
= GTK_CMCTREE(addrbook
.ctree
);
2695 AddressObject
*obj
= NULL
;
2696 AddressDataSource
*ds
= NULL
;
2697 AddressBookFile
*abf
= NULL
;
2698 ItemFolder
*parentFolder
= NULL
;
2699 ItemGroup
*group
= NULL
;
2701 if( ! addrbook
.treeSelected
) return;
2702 obj
= gtk_cmctree_node_get_row_data(ctree
, addrbook
.treeSelected
);
2703 if( obj
== NULL
) return;
2704 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
2705 if( ds
== NULL
) return;
2707 if( obj
->type
== ADDR_DATASOURCE
) {
2708 if( ADAPTER_DSOURCE(obj
)->subType
!= ADDR_BOOK
) return;
2710 else if( obj
->type
== ADDR_ITEM_FOLDER
) {
2711 parentFolder
= ADAPTER_FOLDER(obj
)->itemFolder
;
2717 abf
= ds
->rawDataSource
;
2718 if( abf
== NULL
) return;
2719 group
= addressbook_edit_group( abf
, parentFolder
, NULL
);
2722 nn
= addressbook_node_add_group( addrbook
.treeSelected
, ds
, group
);
2724 g_message("error adding addressbook group\n");
2726 gtk_cmctree_expand( ctree
, addrbook
.treeSelected
);
2727 if( addrbook
.treeSelected
== addrbook
.opened
)
2728 addressbook_set_clist(obj
, TRUE
);
2732 static void addressbook_change_node_name(GtkCMCTreeNode
*node
, const gchar
*name
)
2734 GtkCMCTree
*ctree
= GTK_CMCTREE(addrbook
.ctree
);
2737 GdkPixbuf
*pix_cl
, *pix_op
;
2738 gboolean is_leaf
, expanded
;
2740 gtk_cmctree_get_node_info(ctree
, node
, text
, &spacing
,
2742 &is_leaf
, &expanded
);
2743 gtk_cmctree_set_node_info(ctree
, node
, name
, spacing
,
2750 * \param obj Address object to edit.
2751 * \param node Node in tree.
2752 * \return New name of data source.
2754 static gchar
*addressbook_edit_datasource( AddressObject
*obj
, GtkCMCTreeNode
*node
) {
2755 gchar
*newName
= NULL
;
2756 AddressDataSource
*ds
= NULL
;
2757 AddressInterface
*iface
= NULL
;
2758 AdapterDSource
*ads
= NULL
;
2760 ds
= addressbook_find_datasource( node
);
2761 if( ds
== NULL
) return NULL
;
2762 iface
= ds
->interface
;
2763 if( ! iface
->haveLibrary
) return NULL
;
2765 /* Read data from data source */
2766 if( addrindex_ds_get_modify_flag( ds
) ) {
2767 addrindex_ds_read_data( ds
);
2770 if( ! addrindex_ds_get_read_flag( ds
) ) {
2771 addrindex_ds_read_data( ds
);
2775 ads
= ADAPTER_DSOURCE(obj
);
2776 if( ads
->subType
== ADDR_BOOK
) {
2777 if( addressbook_edit_book( _addressIndex_
, ads
) == NULL
) return NULL
;
2779 else if( ads
->subType
== ADDR_VCARD
) {
2780 if( addressbook_edit_vcard( _addressIndex_
, ads
) == NULL
) return NULL
;
2783 else if( ads
->subType
== ADDR_JPILOT
) {
2784 if( addressbook_edit_jpilot( _addressIndex_
, ads
) == NULL
) return NULL
;
2788 else if( ads
->subType
== ADDR_LDAP
) {
2789 if( addressbook_edit_ldap( _addressIndex_
, ads
) == NULL
) return NULL
;
2795 newName
= obj
->name
;
2800 * Edit an object that is in the address tree area.
2802 static void addressbook_treenode_edit_cb(GtkAction
*action
, gpointer data
)
2804 GtkCMCTree
*ctree
= GTK_CMCTREE(addrbook
.ctree
);
2806 AddressDataSource
*ds
= NULL
;
2807 AddressBookFile
*abf
= NULL
;
2808 GtkCMCTreeNode
*node
= NULL
, *parentNode
= NULL
;
2811 if( ! addrbook
.treeSelected
) return;
2812 node
= addrbook
.treeSelected
;
2813 if( GTK_CMCTREE_ROW(node
)->level
== 1 ) return;
2814 obj
= gtk_cmctree_node_get_row_data( ctree
, node
);
2815 if( obj
== NULL
) return;
2816 parentNode
= GTK_CMCTREE_ROW(node
)->parent
;
2818 ds
= addressbook_find_datasource( node
);
2819 if( ds
== NULL
) return;
2821 if( obj
->type
== ADDR_DATASOURCE
) {
2822 name
= addressbook_edit_datasource( obj
, node
);
2823 if( name
== NULL
) return;
2826 abf
= ds
->rawDataSource
;
2827 if( abf
== NULL
) return;
2828 if( obj
->type
== ADDR_ITEM_FOLDER
) {
2829 AdapterFolder
*adapter
= ADAPTER_FOLDER(obj
);
2830 ItemFolder
*item
= adapter
->itemFolder
;
2831 ItemFolder
*parentFolder
= NULL
;
2832 parentFolder
= ( ItemFolder
* ) ADDRITEM_PARENT(item
);
2833 if( addressbook_edit_folder( abf
, parentFolder
, item
) == NULL
) return;
2834 name
= ADDRITEM_NAME(item
);
2836 else if( obj
->type
== ADDR_ITEM_GROUP
) {
2837 AdapterGroup
*adapter
= ADAPTER_GROUP(obj
);
2838 ItemGroup
*item
= adapter
->itemGroup
;
2839 ItemFolder
*parentFolder
= NULL
;
2840 parentFolder
= ( ItemFolder
* ) ADDRITEM_PARENT(item
);
2841 if( addressbook_edit_group( abf
, parentFolder
, item
) == NULL
) return;
2842 name
= ADDRITEM_NAME(item
);
2845 if( name
&& parentNode
) {
2846 /* Update node in tree view */
2847 addressbook_change_node_name( node
, name
);
2848 gtk_sctree_sort_node(ctree
, parentNode
);
2849 gtk_cmctree_expand( ctree
, node
);
2850 gtk_sctree_select( GTK_SCTREE( ctree
), node
);
2857 ADDRTREE_DEL_FOLDER_ONLY
,
2858 ADDRTREE_DEL_FOLDER_ADDR
2862 * Delete an item from the tree widget.
2863 * \param data Data passed in.
2864 * \param action Action.
2865 * \param widget Widget issuing callback.
2867 static void addressbook_treenode_delete_cb(GtkAction
*action
, gpointer data
)
2869 GtkCMCTree
*ctree
= GTK_CMCTREE(addrbook
.ctree
);
2870 GtkCMCTreeNode
*node
= NULL
;
2874 AddrBookBase
*adbase
;
2875 AddressCache
*cache
;
2876 AdapterDSource
*ads
= NULL
;
2877 AddressInterface
*iface
= NULL
;
2878 AddressDataSource
*ds
= NULL
;
2879 gboolean remFlag
= FALSE
;
2880 TreeItemDelType delType
;
2882 if( ! addrbook
.treeSelected
) return;
2883 node
= addrbook
.treeSelected
;
2884 if( GTK_CMCTREE_ROW(node
)->level
== 1 ) return;
2886 obj
= gtk_cmctree_node_get_row_data( ctree
, node
);
2887 cm_return_if_fail(obj
!= NULL
);
2889 if( obj
->type
== ADDR_DATASOURCE
) {
2890 ads
= ADAPTER_DSOURCE(obj
);
2892 ds
= ads
->dataSource
;
2893 if( ds
== NULL
) return;
2896 /* Must be folder or something else */
2897 ds
= addressbook_find_datasource( node
);
2898 if( ds
== NULL
) return;
2900 /* Only allow deletion from non-readOnly */
2901 iface
= ds
->interface
;
2902 if( iface
->readOnly
) {
2903 /* Allow deletion of query results */
2904 if( ! iface
->externalQuery
) return;
2908 /* Confirm deletion */
2909 delType
= ADDRTREE_DEL_NONE
;
2910 if( obj
->type
== ADDR_ITEM_FOLDER
) {
2911 if( iface
&& iface
->externalQuery
) {
2912 message
= g_strdup_printf( _(
2913 "Do you want to delete the query " \
2914 "results and addresses in '%s'?" ),
2916 aval
= alertpanel( _("Delete"), message
,
2917 GTK_STOCK_CANCEL
, "+"GTK_STOCK_DELETE
, NULL
);
2919 if( aval
== G_ALERTALTERNATE
) {
2920 delType
= ADDRTREE_DEL_FOLDER_ADDR
;
2924 message
= g_strdup_printf
2925 ( _( "Do you want to delete '%s'? "
2926 "If you delete the folder only, the addresses it contains will be moved into the parent folder." ),
2928 aval
= alertpanel( _("Delete folder"), message
,
2929 GTK_STOCK_CANCEL
, g_strconcat("+",_("Delete _folder only"), NULL
), _("Delete folder and _addresses"));
2931 if( aval
== G_ALERTALTERNATE
) {
2932 delType
= ADDRTREE_DEL_FOLDER_ONLY
;
2934 else if( aval
== G_ALERTOTHER
) {
2935 delType
= ADDRTREE_DEL_FOLDER_ADDR
;
2939 else if( obj
->type
== ADDR_ITEM_GROUP
) {
2940 message
= g_strdup_printf(_("Do you want to delete '%s'?\n"
2941 "The addresses it contains will not be lost."), obj
->name
);
2942 aval
= alertpanel(_("Delete"), message
, GTK_STOCK_CANCEL
,
2943 "+" GTK_STOCK_DELETE
, NULL
);
2945 if( aval
== G_ALERTALTERNATE
) delType
= ADDRTREE_DEL_FOLDER_ONLY
;
2947 message
= g_strdup_printf(_("Do you want to delete '%s'?\n"
2948 "The addresses it contains will be lost."), obj
->name
);
2949 aval
= alertpanel(_("Delete"), message
, GTK_STOCK_CANCEL
,
2950 "+" GTK_STOCK_DELETE
, NULL
);
2952 if( aval
== G_ALERTALTERNATE
) delType
= ADDRTREE_DEL_DATA
;
2954 if( delType
== ADDRTREE_DEL_NONE
) return;
2956 /* Proceed with deletion */
2957 if( obj
->type
== ADDR_DATASOURCE
) {
2958 /* Remove node from tree */
2959 gtk_cmctree_remove_node( ctree
, node
);
2961 if (delType
== ADDRTREE_DEL_DATA
&&
2962 ds
->interface
&& ds
->interface
->type
== ADDR_IF_BOOK
)
2963 addrbook_delete_book_file((AddressBookFile
*) ds
->rawDataSource
);
2965 /* Remove data source. */
2966 if( addrindex_index_remove_datasource( _addressIndex_
, ds
) ) {
2967 addrindex_free_datasource( ds
);
2972 /* Get reference to cache */
2973 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
2974 if( adbase
== NULL
) return;
2975 cache
= adbase
->addressCache
;
2977 /* Remove query results folder */
2978 if( iface
&& iface
->externalQuery
) {
2979 AdapterFolder
*adapter
= ADAPTER_FOLDER(obj
);
2980 ItemFolder
*folder
= adapter
->itemFolder
;
2982 adapter
->itemFolder
= NULL
;
2984 g_print( "remove folder for ::%s::\n", obj->name );
2985 g_print( " folder name ::%s::\n", ADDRITEM_NAME(folder) );
2986 g_print( "-------------- remove results\n" );
2988 addrindex_remove_results( ds
, folder
);
2989 /* g_print( "-------------- remove node\n" ); */
2990 gtk_cmctree_remove_node( ctree
, node
);
2994 /* Code below is valid for regular address book deletion */
2995 if( obj
->type
== ADDR_ITEM_FOLDER
) {
2996 AdapterFolder
*adapter
= ADAPTER_FOLDER(obj
);
2997 ItemFolder
*item
= adapter
->itemFolder
;
2999 if( delType
== ADDRTREE_DEL_FOLDER_ONLY
) {
3000 /* Remove folder only */
3001 item
= addrcache_remove_folder( cache
, item
);
3003 addritem_free_item_folder( item
);
3004 addressbook_move_nodes_up( ctree
, node
);
3008 else if( delType
== ADDRTREE_DEL_FOLDER_ADDR
) {
3009 /* Remove folder and addresses */
3010 item
= addrcache_remove_folder_delete( cache
, item
);
3012 addritem_free_item_folder( item
);
3017 else if( obj
->type
== ADDR_ITEM_GROUP
) {
3018 AdapterGroup
*adapter
= ADAPTER_GROUP(obj
);
3019 ItemGroup
*item
= adapter
->itemGroup
;
3021 item
= addrcache_remove_group( cache
, item
);
3023 addritem_free_item_group( item
);
3030 gtk_cmctree_remove_node(ctree
, node
);
3034 static void addressbook_new_address_from_book_post_cb( ItemPerson
*person
)
3036 if( person
&& addrbook
.treeSelected
== addrbook
.opened
) {
3037 person
->status
= ADD_ENTRY
;
3038 gtk_cmclist_unselect_all( GTK_CMCLIST(addrbook
.clist
) );
3039 addressbook_folder_refresh_one_person(
3040 GTK_CMCTREE(addrbook
.clist
), person
);
3042 addressbook_address_list_set_focus();
3045 static void addressbook_new_address_from_folder_post_cb( ItemPerson
*person
)
3047 if( person
&& addrbook
.treeSelected
== addrbook
.opened
) {
3048 person
->status
= ADD_ENTRY
;
3049 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), addrbook
.opened
);
3050 addressbook_set_clist(
3051 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook
.ctree
),
3055 addressbook_address_list_set_focus();
3059 * Label (a format string) that is used to name each folder.
3061 static gchar
*_queryFolderLabel_
= N_( "Search '%s'" );
3064 * Search ctree widget callback function.
3065 * \param pA Pointer to node.
3066 * \param pB Pointer to data item being sought.
3067 * \return Zero (0) if folder found.
3069 static int addressbook_treenode_find_folder_cb( gconstpointer pA
, gconstpointer pB
) {
3072 aoA
= ( AddressObject
* ) pA
;
3073 if( aoA
->type
== ADDR_ITEM_FOLDER
) {
3074 ItemFolder
*folder
, *fld
;
3076 fld
= ADAPTER_FOLDER(aoA
)->itemFolder
;
3077 folder
= ( ItemFolder
* ) pB
;
3078 if( fld
== folder
) return 0; /* Found folder */
3083 static ItemFolder
* addressbook_setup_subf(
3084 AddressDataSource
*ds
, gchar
*title
,
3085 GtkCMCTreeNode
*pNode
)
3087 AddrBookBase
*adbase
;
3088 AddressCache
*cache
;
3091 GtkCMCTreeNode
*nNode
;
3093 AddressObjectType aoType
= ADDR_NONE
;
3096 if( *title
== '\0' || strlen( title
) < 1 ) return NULL
;
3098 if( ds
&& ds
->type
== ADDR_IF_LDAP
) {
3100 aoType
= ADDR_LDAP_QUERY
;
3107 ctree
= GTK_CMCTREE(addrbook
.ctree
);
3108 /* Get reference to address cache */
3109 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
3110 cache
= adbase
->addressCache
;
3112 if ((children
= addrcache_get_list_folder(cache
)) != NULL
) {
3113 GList
*cur
= children
;
3114 for (; cur
; cur
= cur
->next
) {
3115 ItemFolder
*child
= (ItemFolder
*) cur
->data
;
3116 if (!strcmp2(ADDRITEM_NAME(child
), title
)) {
3117 nNode
= gtk_cmctree_find_by_row_data_custom(
3119 addressbook_treenode_find_folder_cb
);
3121 addrindex_remove_results( ds
, child
);
3122 while( child
->listPerson
) {
3123 ItemPerson
*item
= ( ItemPerson
* ) child
->listPerson
->data
;
3124 item
= addrcache_remove_person( cache
, item
);
3126 addritem_free_item_person( item
);
3130 gtk_sctree_select( GTK_SCTREE(ctree
), nNode
);
3131 addrbook
.treeSelected
= nNode
;
3138 /* Create a folder */
3139 folder
= addrcache_add_new_folder( cache
, NULL
);
3140 name
= g_strdup_printf( "%s", title
);
3141 addritem_folder_set_name( folder
, name
);
3142 addritem_folder_set_remarks( folder
, "" );
3145 /* Now let's see the folder */
3146 nNode
= addressbook_node_add_folder( pNode
, ds
, folder
, aoType
);
3147 gtk_cmctree_expand( ctree
, pNode
);
3149 gtk_sctree_select( GTK_SCTREE(ctree
), nNode
);
3150 addrbook
.treeSelected
= nNode
;
3156 static void addressbook_new_address_cb( GtkAction
*action
, gpointer data
) {
3157 AddressObject
*pobj
= NULL
;
3158 AddressDataSource
*ds
= NULL
;
3159 AddressBookFile
*abf
= NULL
;
3160 debug_print("adding address\n");
3161 pobj
= gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook
.ctree
), addrbook
.treeSelected
);
3162 if( pobj
== NULL
) {
3163 debug_print("no row data\n");
3166 ds
= addressbook_find_datasource( GTK_CMCTREE_NODE(addrbook
.treeSelected
) );
3168 debug_print("no datasource\n");
3172 abf
= ds
->rawDataSource
;
3174 g_print("no addressbook file\n");
3178 if( pobj
->type
== ADDR_DATASOURCE
) {
3179 if (ADAPTER_DSOURCE(pobj
)->subType
== ADDR_BOOK
||
3180 ADAPTER_DSOURCE(pobj
)->subType
== ADDR_LDAP
) {
3182 ItemFolder
*folder
= NULL
;
3184 if (abf
&& abf
->type
== ADBOOKTYPE_LDAP
) {
3185 GtkCMCTreeNode
*parentNode
;
3186 ds
= addressbook_find_datasource( GTK_CMCTREE_NODE( addrbook
.treeSelected
) );
3187 if( ds
== NULL
) return;
3189 /* We must have a datasource that is an external interface */
3190 if( ! ds
->interface
->haveLibrary
) return;
3191 if( ! ds
->interface
->externalQuery
) return;
3193 if( pobj
->type
== ADDR_ITEM_FOLDER
) {
3194 parentNode
= GTK_CMCTREE_ROW(GTK_CMCTREE_NODE( addrbook
.treeSelected
) )->parent
;
3197 parentNode
= GTK_CMCTREE_NODE( addrbook
.treeSelected
);
3199 folder
= addressbook_setup_subf( ds
, _("New Contacts"), parentNode
);
3201 ds
= addressbook_find_datasource( GTK_CMCTREE_NODE(addrbook
.treeSelected
) );
3203 abf
= ds
->rawDataSource
;
3206 person
= addressbook_edit_person( abf
, folder
, NULL
, FALSE
,
3207 addrbook
.editaddress_vbox
,
3208 addressbook_new_address_from_book_post_cb
,
3211 if (ds
&& abf
&& abf
->type
== ADBOOKTYPE_LDAP
) {
3212 LdapServer
*server
= ds
->rawDataSource
;
3213 ldapsvr_set_modified(server
, TRUE
);
3214 ldapsvr_update_book(server
, NULL
);
3215 if (server
->retVal
!= LDAPRC_SUCCESS
) {
3216 alertpanel( _("Add address(es)"),
3217 addressbook_err2string(_lutErrorsLDAP_
, server
->retVal
),
3218 GTK_STOCK_CLOSE
, NULL
, NULL
);
3219 server
->retVal
= LDAPRC_SUCCESS
;
3224 if (prefs_common
.addressbook_use_editaddress_dialog
)
3225 addressbook_new_address_from_book_post_cb( person
);
3228 else if( pobj
->type
== ADDR_ITEM_FOLDER
) {
3230 ItemFolder
*folder
= ADAPTER_FOLDER(pobj
)->itemFolder
;
3233 if (abf
&& abf
->type
== ADBOOKTYPE_LDAP
) {
3234 GtkCMCTreeNode
*parentNode
;
3235 ds
= addressbook_find_datasource( GTK_CMCTREE_NODE( addrbook
.treeSelected
) );
3236 if( ds
== NULL
) return;
3238 /* We must have a datasource that is an external interface */
3239 if( ! ds
->interface
->haveLibrary
) return;
3240 if( ! ds
->interface
->externalQuery
) return;
3242 if( pobj
->type
== ADDR_ITEM_FOLDER
) {
3243 parentNode
= GTK_CMCTREE_ROW(GTK_CMCTREE_NODE( addrbook
.treeSelected
) )->parent
;
3246 parentNode
= GTK_CMCTREE_NODE( addrbook
.treeSelected
);
3248 folder
= addressbook_setup_subf( ds
, _("New Contacts"), parentNode
);
3252 ds
= addressbook_find_datasource( GTK_CMCTREE_NODE(addrbook
.treeSelected
) );
3254 abf
= ds
->rawDataSource
;
3257 person
= addressbook_edit_person( abf
, folder
, NULL
, FALSE
,
3258 addrbook
.editaddress_vbox
,
3259 addressbook_new_address_from_folder_post_cb
,
3262 if (ds
&& abf
&& abf
->type
== ADBOOKTYPE_LDAP
) {
3263 LdapServer
*server
= ds
->rawDataSource
;
3264 ldapsvr_set_modified(server
, TRUE
);
3265 ldapsvr_update_book(server
, NULL
);
3266 if (server
->retVal
!= LDAPRC_SUCCESS
) {
3267 alertpanel( _("Add address(es)"),
3268 addressbook_err2string(_lutErrorsLDAP_
, server
->retVal
),
3269 GTK_STOCK_CLOSE
, NULL
, NULL
);
3274 if (prefs_common
.addressbook_use_editaddress_dialog
)
3275 addressbook_new_address_from_folder_post_cb( person
);
3277 else if( pobj
->type
== ADDR_ITEM_GROUP
) {
3278 /* New address in group */
3279 ItemGroup
*group
= ADAPTER_GROUP(pobj
)->itemGroup
;
3280 if( addressbook_edit_group( abf
, NULL
, group
) == NULL
) return;
3281 if (addrbook
.treeSelected
== addrbook
.opened
) {
3282 /* Change node name in tree. */
3283 addressbook_change_node_name( addrbook
.treeSelected
, ADDRITEM_NAME(group
) );
3284 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), addrbook
.opened
);
3285 addressbook_set_clist(
3286 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook
.ctree
),
3294 * Search for specified child group node in address index tree.
3295 * \param parent Parent node.
3296 * \param group Group to find.
3298 static GtkCMCTreeNode
*addressbook_find_group_node( GtkCMCTreeNode
*parent
, ItemGroup
*group
) {
3299 GtkCMCTreeNode
*node
= NULL
;
3300 GtkCMCTreeRow
*currRow
;
3302 currRow
= GTK_CMCTREE_ROW( parent
);
3304 node
= currRow
->children
;
3308 obj
= gtk_cmctree_node_get_row_data( GTK_CMCTREE(addrbook
.ctree
), node
);
3309 if(obj
&& obj
->type
== ADDR_ITEM_GROUP
) {
3310 ItemGroup
*g
= ADAPTER_GROUP(obj
)->itemGroup
;
3311 if( g
== group
) return node
;
3313 currRow
= GTK_CMCTREE_ROW(node
);
3314 node
= currRow
->sibling
;
3320 static AddressBookFile
*addressbook_get_book_file() {
3321 AddressBookFile
*abf
= NULL
;
3322 AddressDataSource
*ds
= NULL
;
3324 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
3325 if( ds
== NULL
) return NULL
;
3326 if( ds
->type
== ADDR_IF_BOOK
|| ds
->type
== ADDR_IF_LDAP
) abf
= ds
->rawDataSource
;
3330 static void addressbook_tree_remove_children( GtkCMCTree
*ctree
, GtkCMCTreeNode
*parent
) {
3331 GtkCMCTreeNode
*node
;
3334 /* Remove existing folders and groups */
3335 row
= GTK_CMCTREE_ROW( parent
);
3337 while( (node
= row
->children
) ) {
3338 gtk_cmctree_remove_node( ctree
, node
);
3343 static void addressbook_move_nodes_up( GtkCMCTree
*ctree
, GtkCMCTreeNode
*node
) {
3344 GtkCMCTreeNode
*parent
, *child
;
3345 GtkCMCTreeRow
*currRow
;
3346 currRow
= GTK_CMCTREE_ROW( node
);
3348 parent
= currRow
->parent
;
3349 while( (child
= currRow
->children
) ) {
3350 gtk_cmctree_move( ctree
, child
, parent
, node
);
3352 gtk_sctree_sort_node( ctree
, parent
);
3356 static void addressbook_edit_address_post_cb( ItemPerson
*person
)
3360 AddressBookFile
*abf
= addressbook_get_book_file();
3362 if (abf
&& abf
->type
== ADBOOKTYPE_LDAP
) {
3363 if (strcmp2(person
->nickName
, ADDRITEM_NAME(person
)))
3364 addritem_person_set_nick_name( person
, ADDRITEM_NAME(person
));
3367 addressbook_folder_refresh_one_person( GTK_CMCTREE(addrbook
.clist
), person
);
3368 invalidate_address_completion();
3370 addressbook_address_list_set_focus();
3373 void addressbook_address_list_set_focus( void )
3375 if (!prefs_common
.addressbook_use_editaddress_dialog
) {
3376 gtk_window_set_focus(GTK_WINDOW(addrbook
.window
), addrbook
.clist
);
3377 addressbook_list_menu_setup();
3381 void addressbook_address_list_disable_some_actions(void)
3383 /* disable address copy/pasting when editing contact's detail (embedded form) */
3384 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Cut", FALSE
);
3385 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Copy", FALSE
);
3386 cm_menu_set_sensitive_full( addrbook
.ui_manager
, "Menu/Address/Paste", FALSE
);
3389 static void addressbook_edit_address_cb( GtkAction
*action
, gpointer data
) {
3390 addressbook_edit_address(data
, 0, NULL
, TRUE
);
3393 static void addressbook_edit_address( gpointer data
, guint action
, GtkWidget
*widget
,
3394 gboolean force_focus
) {
3395 GtkCMCTree
*clist
= GTK_CMCTREE(addrbook
.clist
);
3397 AddressObject
*obj
= NULL
, *pobj
= NULL
;
3398 AddressDataSource
*ds
= NULL
;
3399 GtkCMCTreeNode
*node
= NULL
, *parentNode
= NULL
;
3401 AddressBookFile
*abf
= NULL
;
3403 if( addrbook
.listSelected
== NULL
) return;
3404 obj
= gtk_cmctree_node_get_row_data( clist
, addrbook
.listSelected
);
3405 cm_return_if_fail(obj
!= NULL
);
3407 ctree
= GTK_CMCTREE( addrbook
.ctree
);
3408 pobj
= gtk_cmctree_node_get_row_data( ctree
, addrbook
.treeSelected
);
3410 ds
= addressbook_find_datasource( GTK_CMCTREE_NODE(addrbook
.treeSelected
) );
3411 if( ds
== NULL
) return;
3413 abf
= addressbook_get_book_file();
3415 if( obj
->type
== ADDR_ITEM_EMAIL
) {
3416 ItemEMail
*email
= ( ItemEMail
* ) obj
;
3418 if( pobj
&& pobj
->type
== ADDR_ITEM_GROUP
) {
3419 /* Edit parent group */
3420 AdapterGroup
*adapter
= ADAPTER_GROUP(pobj
);
3421 ItemGroup
*itemGrp
= adapter
->itemGroup
;
3422 if( abf
== NULL
) return;
3423 if( addressbook_edit_group( abf
, NULL
, itemGrp
) == NULL
) return;
3424 name
= ADDRITEM_NAME(itemGrp
);
3425 node
= addrbook
.treeSelected
;
3426 parentNode
= GTK_CMCTREE_ROW(node
)->parent
;
3429 /* Edit person - email page */
3431 person
= ( ItemPerson
* ) ADDRITEM_PARENT(email
);
3432 if ( addressbook_edit_person( abf
, NULL
, person
, TRUE
, addrbook
.editaddress_vbox
,
3433 addressbook_edit_address_post_cb
,
3434 (prefs_common
.addressbook_use_editaddress_dialog
||force_focus
) )
3437 if (abf
&& abf
->type
== ADBOOKTYPE_LDAP
) {
3438 ldapsvr_set_modified( (LdapServer
*) abf
, TRUE
);
3439 person
->status
= UPDATE_ENTRY
;
3442 if (prefs_common
.addressbook_use_editaddress_dialog
)
3443 addressbook_edit_address_post_cb( person
);
3448 else if( obj
->type
== ADDR_ITEM_PERSON
) {
3449 /* Edit person - basic page */
3450 ItemPerson
*person
= ( ItemPerson
* ) obj
;
3451 if( addressbook_edit_person( abf
, NULL
, person
, FALSE
, addrbook
.editaddress_vbox
,
3452 addressbook_edit_address_post_cb
,
3453 (prefs_common
.addressbook_use_editaddress_dialog
||force_focus
) )
3456 if (abf
&& abf
->type
== ADBOOKTYPE_LDAP
) {
3457 ldapsvr_set_modified( (LdapServer
*) abf
, TRUE
);
3458 person
->status
= UPDATE_ENTRY
;
3461 if (prefs_common
.addressbook_use_editaddress_dialog
)
3462 addressbook_edit_address_post_cb( person
);
3466 else if( obj
->type
== ADDR_ITEM_GROUP
) {
3467 ItemGroup
*itemGrp
= ( ItemGroup
* ) obj
;
3468 if( addressbook_edit_group( abf
, NULL
, itemGrp
) == NULL
) return;
3469 parentNode
= addrbook
.treeSelected
;
3470 node
= addressbook_find_group_node( parentNode
, itemGrp
);
3471 name
= ADDRITEM_NAME(itemGrp
);
3472 invalidate_address_completion();
3478 /* Update tree node with node name */
3479 if( node
== NULL
) return;
3480 addressbook_change_node_name( node
, name
);
3481 gtk_sctree_sort_node( ctree
, parentNode
);
3482 gtk_sctree_select( GTK_SCTREE(ctree
), addrbook
.opened
);
3483 addressbook_set_clist(
3484 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook
.ctree
),
3489 static void addressbook_delete_address_cb(GtkAction
*action
, gpointer data
)
3491 addressbook_del_clicked(NULL
, NULL
);
3494 static void close_cb(GtkAction
*action
, gpointer data
)
3496 addressbook_close();
3499 static void addressbook_file_save_cb( GtkAction
*action
, gpointer data
) {
3500 addressbook_export_to_file();
3503 static void addressbook_person_expand_node( GtkCMCTree
*ctree
, GList
*node
, gpointer
*data
) {
3505 ItemPerson
*person
= gtk_cmctree_node_get_row_data( ctree
, GTK_CMCTREE_NODE(node
) );
3506 if( person
) addritem_person_set_opened( person
, TRUE
);
3510 static void addressbook_person_collapse_node( GtkCMCTree
*ctree
, GList
*node
, gpointer
*data
) {
3512 ItemPerson
*person
= gtk_cmctree_node_get_row_data( ctree
, GTK_CMCTREE_NODE(node
) );
3513 if( person
) addritem_person_set_opened( person
, FALSE
);
3517 static gchar
*addressbook_format_item_clist( ItemPerson
*person
, ItemEMail
*email
) {
3519 gchar
*eMailAlias
= ADDRITEM_NAME(email
);
3520 if( eMailAlias
&& *eMailAlias
!= '\0' ) {
3522 str
= g_strdup_printf( "%s - %s", ADDRITEM_NAME(person
), eMailAlias
);
3525 str
= g_strdup( eMailAlias
);
3531 static gboolean
addressbook_match_item(const gchar
*name
,
3532 const gchar
*email_alias
,
3534 const gchar
*remarks
,
3539 if (!str
|| str
[0] == '\0')
3541 if (strcasestr(name
, str
))
3543 else if (email_alias
&& strcasestr(email_alias
, str
))
3545 else if (addr
&& strcasestr(addr
, str
))
3547 else if (remarks
&& strcasestr(remarks
, str
))
3553 static void addressbook_load_group( GtkCMCTree
*clist
, ItemGroup
*itemGroup
) {
3554 GList
*items
= itemGroup
->listEMail
;
3555 AddressTypeControlItem
*atci
= addrbookctl_lookup( ADDR_ITEM_EMAIL
);
3556 const gchar
*search_str
= gtk_entry_get_text(GTK_ENTRY(addrbook
.entry
));
3557 for( ; items
!= NULL
; items
= g_list_next( items
) ) {
3558 GtkCMCTreeNode
*nodeEMail
= NULL
;
3559 gchar
*text
[N_LIST_COLS
];
3560 ItemEMail
*email
= items
->data
;
3564 if( ! email
) continue;
3566 person
= ( ItemPerson
* ) ADDRITEM_PARENT(email
);
3568 if( !addressbook_match_item(ADDRITEM_NAME(person
),
3569 ADDRITEM_NAME(email
),
3570 email
->address
, email
->remarks
,
3574 str
= addressbook_format_item_clist( person
, email
);
3576 text
[COL_NAME
] = addressbook_set_col_name_guard(str
);
3579 text
[COL_NAME
] = addressbook_set_col_name_guard(ADDRITEM_NAME(person
));
3581 text
[COL_ADDRESS
] = email
->address
;
3582 text
[COL_REMARKS
] = email
->remarks
;
3583 nodeEMail
= gtk_sctree_insert_node(
3585 text
, FOLDER_SPACING
,
3589 gtk_cmctree_node_set_row_data( clist
, nodeEMail
, email
);
3595 gchar
*addressbook_set_col_name_guard(gchar
*value
)
3597 gchar
*ret
= "<not set>";
3598 gchar
*tmp
= g_strdup(value
);
3600 if (tmp
!=NULL
&& *tmp
!= '\0')
3606 static void addressbook_folder_load_one_person(
3607 GtkCMCTree
*clist
, ItemPerson
*person
,
3608 AddressTypeControlItem
*atci
,
3609 AddressTypeControlItem
*atciMail
)
3611 GtkCMCTreeNode
*nodePerson
= NULL
;
3612 GtkCMCTreeNode
*nodeEMail
= NULL
;
3613 gchar
*text
[N_LIST_COLS
];
3614 gboolean flgFirst
= TRUE
, haveAddr
= FALSE
;
3617 AddressBookFile
*abf
= addressbook_get_book_file();
3620 if( person
== NULL
) return;
3622 text
[COL_NAME
] = "";
3623 node
= person
->listEMail
;
3625 ItemEMail
*email
= node
->data
;
3626 gchar
*eMailAddr
= NULL
;
3627 node
= g_list_next( node
);
3629 text
[COL_ADDRESS
] = email
->address
;
3630 text
[COL_REMARKS
] = email
->remarks
;
3631 eMailAddr
= ADDRITEM_NAME(email
);
3632 if( eMailAddr
&& *eMailAddr
== '\0' ) eMailAddr
= NULL
;
3634 /* First email belongs with person */
3635 gchar
*str
= addressbook_format_item_clist( person
, email
);
3637 text
[COL_NAME
] = addressbook_set_col_name_guard(str
);
3640 else if( abf
&& abf
->type
== ADBOOKTYPE_LDAP
&&
3641 person
&& person
->nickName
) {
3642 if (person
->nickName
) {
3643 if (strcmp(person
->nickName
, "") != 0) {
3644 text
[COL_NAME
] = addressbook_set_col_name_guard(person
->nickName
);
3647 text
[COL_NAME
] = addressbook_set_col_name_guard(ADDRITEM_NAME(person
));
3653 text
[COL_NAME
] = addressbook_set_col_name_guard(ADDRITEM_NAME(person
));
3655 nodePerson
= gtk_sctree_insert_node(
3657 text
, FOLDER_SPACING
,
3660 FALSE
, person
->isOpened
);
3663 gtk_cmctree_node_set_row_data(clist
, nodePerson
, person
);
3666 /* Subsequent email is a child node of person */
3667 text
[COL_NAME
] = ADDRITEM_NAME(email
);
3668 nodeEMail
= gtk_sctree_insert_node(
3669 clist
, nodePerson
, NULL
,
3670 text
, FOLDER_SPACING
,
3672 atciMail
->iconXpmOpen
,
3674 gtk_cmctree_node_set_row_data(clist
, nodeEMail
, email
);
3680 /* Have name without EMail */
3681 text
[COL_NAME
] = addressbook_set_col_name_guard(ADDRITEM_NAME(person
));
3682 text
[COL_ADDRESS
] = "";
3683 text
[COL_REMARKS
] = "";
3684 nodePerson
= gtk_sctree_insert_node(
3686 text
, FOLDER_SPACING
,
3689 FALSE
, person
->isOpened
);
3690 gtk_cmctree_node_set_row_data(clist
, nodePerson
, person
);
3695 static void addressbook_folder_load_person( GtkCMCTree
*clist
, ItemFolder
*itemFolder
) {
3697 AddressTypeControlItem
*atci
= addrbookctl_lookup( ADDR_ITEM_PERSON
);
3698 AddressTypeControlItem
*atciMail
= addrbookctl_lookup( ADDR_ITEM_EMAIL
);
3699 const gchar
*search_str
;
3701 if( atci
== NULL
) return;
3702 if( atciMail
== NULL
) return;
3704 search_str
= gtk_entry_get_text(GTK_ENTRY(addrbook
.entry
));
3706 /* Load email addresses */
3707 items
= addritem_folder_get_person_list( itemFolder
);
3708 for( ; items
!= NULL
; items
= g_list_next( items
) ) {
3713 person
= (ItemPerson
*)items
->data
;
3716 node
= person
->listEMail
;
3717 if (node
&& node
->data
) {
3719 if (!addressbook_match_item(ADDRITEM_NAME(person
), ADDRITEM_NAME(email
), email
->address
, email
->remarks
, search_str
))
3722 if (!addressbook_match_item(ADDRITEM_NAME(person
), NULL
, NULL
, NULL
, search_str
))
3726 addressbook_folder_load_one_person( clist
, items
->data
, atci
, atciMail
);
3728 /* Free up the list */
3729 mgu_clear_list( items
);
3730 g_list_free( items
);
3733 static void addressbook_folder_remove_node( GtkCMCTree
*clist
, GtkCMCTreeNode
*node
) {
3734 addrbook
.listSelected
= NULL
;
3735 gtk_cmctree_remove_node( clist
, node
);
3736 addressbook_menubar_set_sensitive( FALSE
);
3737 addressbook_menuitem_set_sensitive(
3738 gtk_cmctree_node_get_row_data(
3739 GTK_CMCTREE(clist
), addrbook
.treeSelected
),
3740 addrbook
.treeSelected
);
3743 static void addressbook_folder_refresh_one_person( GtkCMCTree
*clist
, ItemPerson
*person
) {
3744 AddressTypeControlItem
*atci
= addrbookctl_lookup( ADDR_ITEM_PERSON
);
3745 AddressTypeControlItem
*atciMail
= addrbookctl_lookup( ADDR_ITEM_EMAIL
);
3746 GtkCMCTreeNode
*node
;
3747 if( atci
== NULL
) return;
3748 if( atciMail
== NULL
) return;
3749 if( person
== NULL
) return;
3750 /* unload the person */
3752 node
= gtk_cmctree_find_by_row_data( clist
, NULL
, person
);
3754 addressbook_folder_remove_node( clist
, node
);
3755 addressbook_folder_load_one_person( clist
, person
, atci
, atciMail
);
3756 gtk_sctree_sort_node( clist
, NULL
);
3757 node
= gtk_cmctree_find_by_row_data( clist
, NULL
, person
);
3759 gtk_sctree_select( GTK_SCTREE(clist
), node
);
3760 if (!gtk_cmctree_node_is_visible( clist
, node
) )
3761 gtk_cmctree_node_moveto( clist
, node
, 0, 0, 0 );
3765 static void addressbook_folder_remove_one_person( GtkCMCTree
*clist
, ItemPerson
*person
) {
3766 GtkCMCTreeNode
*node
;
3768 if( person
== NULL
) return;
3769 node
= gtk_cmctree_find_by_row_data( clist
, NULL
, person
);
3771 addressbook_folder_remove_node( clist
, node
);
3775 static void addressbook_folder_load_group( GtkCMCTree
*clist
, ItemFolder
*itemFolder
) {
3777 AddressTypeControlItem
*atci
= addrbookctl_lookup( ADDR_ITEM_GROUP
);
3778 const gchar
*search_str
;
3780 /* Load any groups */
3781 if( ! atci
) return;
3783 search_str
= gtk_entry_get_text(GTK_ENTRY(addrbook
.entry
));
3785 items
= addritem_folder_get_group_list( itemFolder
);
3786 for( ; items
!= NULL
; items
= g_list_next( items
) ) {
3787 GtkCMCTreeNode
*nodeGroup
= NULL
;
3788 gchar
*text
[N_LIST_COLS
];
3789 ItemGroup
*group
= items
->data
;
3790 if( group
== NULL
) continue;
3791 if( !addressbook_match_item(ADDRITEM_NAME(group
),
3792 NULL
, NULL
, NULL
, search_str
) )
3795 text
[COL_NAME
] = ADDRITEM_NAME(group
);
3796 text
[COL_ADDRESS
] = "";
3797 text
[COL_REMARKS
] = "";
3798 nodeGroup
= gtk_sctree_insert_node(clist
, NULL
, NULL
,
3799 text
, FOLDER_SPACING
,
3803 gtk_cmctree_node_set_row_data(clist
, nodeGroup
, group
);
3804 gtk_sctree_sort_node(clist
, NULL
);
3806 /* Free up the list */
3807 mgu_clear_list( items
);
3808 g_list_free( items
);
3812 * Search ctree widget callback function.
3813 * \param pA Pointer to node.
3814 * \param pB Pointer to data item being sought.
3815 * \return Zero (0) if group found.
3817 static int addressbook_treenode_find_group_cb( gconstpointer pA
, gconstpointer pB
) {
3820 aoA
= ( AddressObject
* ) pA
;
3821 if( aoA
->type
== ADDR_ITEM_GROUP
) {
3822 ItemGroup
*group
, *grp
;
3824 grp
= ADAPTER_GROUP(aoA
)->itemGroup
;
3825 group
= ( ItemGroup
* ) pB
;
3826 if( grp
== group
) return 0; /* Found group */
3832 * Remove folder and group nodes from tree widget for items contained ("cut")
3835 static void addressbook_treenode_remove_item( void ) {
3837 AddrSelectItem
*cutItem
;
3838 AddressCache
*cache
;
3839 AddrItemObject
*aio
;
3840 GtkCMCTree
*ctree
= GTK_CMCTREE( addrbook
.ctree
);
3843 node
= _clipBoard_
->objectList
;
3845 cutItem
= node
->data
;
3846 node
= g_list_next( node
);
3847 cache
= addrindex_get_cache(
3848 _clipBoard_
->addressIndex
, cutItem
->cacheID
);
3849 if( cache
== NULL
) continue;
3850 aio
= addrcache_get_object( cache
, cutItem
->uid
);
3853 if( ADDRITEM_TYPE(aio
) == ITEMTYPE_FOLDER
) {
3856 folder
= ( ItemFolder
* ) aio
;
3857 tn
= gtk_cmctree_find_by_row_data_custom(
3858 ctree
, NULL
, folder
,
3859 addressbook_treenode_find_folder_cb
);
3861 else if( ADDRITEM_TYPE(aio
) == ITEMTYPE_GROUP
) {
3864 group
= ( ItemGroup
* ) aio
;
3865 tn
= gtk_cmctree_find_by_row_data_custom(
3867 addressbook_treenode_find_group_cb
);
3871 /* Free up adapter and remove node. */
3872 gtk_cmctree_remove_node( ctree
, tn
);
3879 * Find parent datasource for specified tree node.
3880 * \param node Node to test.
3881 * \return Data source, or NULL if not found.
3883 static AddressDataSource
*addressbook_find_datasource( GtkCMCTreeNode
*node
) {
3884 AddressDataSource
*ds
= NULL
;
3887 cm_return_val_if_fail(addrbook
.ctree
!= NULL
, NULL
);
3890 if( GTK_CMCTREE_ROW(node
)->level
< 2 ) return NULL
;
3891 ao
= gtk_cmctree_node_get_row_data( GTK_CMCTREE(addrbook
.ctree
), node
);
3893 /* g_print( "ao->type = %d\n", ao->type ); */
3894 if( ao
->type
== ADDR_DATASOURCE
) {
3895 AdapterDSource
*ads
= ADAPTER_DSOURCE(ao
);
3896 /* g_print( "found it\n" ); */
3897 ds
= ads
->dataSource
;
3901 node
= GTK_CMCTREE_ROW(node
)->parent
;
3907 * Load address list widget with children of specified object.
3908 * \param obj Parent object to be loaded.
3910 static void addressbook_set_clist( AddressObject
*obj
, gboolean refresh
) {
3911 GtkCMCTree
*ctreelist
= GTK_CMCTREE(addrbook
.clist
);
3912 GtkCMCList
*clist
= GTK_CMCLIST(addrbook
.clist
);
3913 AddressDataSource
*ds
= NULL
;
3914 AdapterDSource
*ads
= NULL
;
3915 static AddressObject
*last_obj
= NULL
;
3917 if (addrbook
.clist
== NULL
) {
3920 if (obj
== last_obj
&& !refresh
)
3925 gtk_cmclist_clear(clist
);
3929 if( obj
->type
== ADDR_INTERFACE
) {
3930 /* g_print( "set_clist: loading datasource...\n" ); */
3931 /* addressbook_node_load_datasource( GTK_CMCTREE(clist), obj ); */
3935 gtk_cmclist_freeze(clist
);
3936 gtk_cmclist_clear(clist
);
3938 if( obj
->type
== ADDR_DATASOURCE
) {
3939 ads
= ADAPTER_DSOURCE(obj
);
3940 ds
= ads
->dataSource
;
3942 /* Load root folder */
3943 ItemFolder
*rootFolder
= NULL
;
3944 rootFolder
= addrindex_ds_get_root_folder( ds
);
3945 addressbook_folder_load_person(
3946 ctreelist
, rootFolder
);
3947 addressbook_folder_load_group(
3948 ctreelist
, rootFolder
);
3952 if( obj
->type
== ADDR_ITEM_GROUP
) {
3954 ItemGroup
*itemGroup
= ADAPTER_GROUP(obj
)->itemGroup
;
3955 addressbook_load_group( ctreelist
, itemGroup
);
3957 else if( obj
->type
== ADDR_ITEM_FOLDER
) {
3959 ItemFolder
*itemFolder
= ADAPTER_FOLDER(obj
)->itemFolder
;
3960 addressbook_folder_load_person( ctreelist
, itemFolder
);
3961 addressbook_folder_load_group( ctreelist
, itemFolder
);
3964 gtk_sctree_sort_recursive(GTK_CMCTREE(clist
), NULL
);
3965 clist
->focus_row
= -1;
3966 gtk_cmclist_thaw(clist
);
3970 * Call back function to free adaptor. Call back is setup by function
3971 * gtk_cmctree_node_set_row_data_full() when node is populated. This function is
3972 * called when the address book tree widget node is removed by calling
3973 * function gtk_cmctree_remove_node().
3975 * \param data Tree node's row data.
3977 static void addressbook_free_treenode( gpointer data
) {
3980 ao
= ( AddressObject
* ) data
;
3981 if( ao
== NULL
) return;
3982 if( ao
->type
== ADDR_INTERFACE
) {
3983 AdapterInterface
*ai
= ADAPTER_INTERFACE(ao
);
3984 addrbookctl_free_interface( ai
);
3986 else if( ao
->type
== ADDR_DATASOURCE
) {
3987 AdapterDSource
*ads
= ADAPTER_DSOURCE(ao
);
3988 addrbookctl_free_datasource( ads
);
3990 else if( ao
->type
== ADDR_ITEM_FOLDER
) {
3991 AdapterFolder
*af
= ADAPTER_FOLDER(ao
);
3992 addrbookctl_free_folder( af
);
3994 else if( ao
->type
== ADDR_ITEM_GROUP
) {
3995 AdapterGroup
*ag
= ADAPTER_GROUP(ao
);
3996 addrbookctl_free_group( ag
);
4001 * Create new adaptor for specified data source.
4003 AdapterDSource
*addressbook_create_ds_adapter( AddressDataSource
*ds
,
4004 AddressObjectType otype
, gchar
*name
)
4006 AdapterDSource
*adapter
= g_new0( AdapterDSource
, 1 );
4007 ADDRESS_OBJECT(adapter
)->type
= ADDR_DATASOURCE
;
4008 ADDRESS_OBJECT_NAME(adapter
) = g_strdup( name
);
4009 adapter
->dataSource
= ds
;
4010 adapter
->subType
= otype
;
4014 void addressbook_ads_set_name( AdapterDSource
*adapter
, gchar
*value
) {
4015 ADDRESS_OBJECT_NAME(adapter
) =
4016 mgu_replace_string( ADDRESS_OBJECT_NAME(adapter
), value
);
4020 * Load tree from address index with the initial data.
4022 static void addressbook_load_tree( void ) {
4023 GtkCMCTree
*ctree
= GTK_CMCTREE( addrbook
.ctree
);
4024 GList
*nodeIf
, *nodeDS
;
4025 AdapterInterface
*adapter
;
4026 AddressInterface
*iface
;
4027 AddressTypeControlItem
*atci
;
4028 AddressDataSource
*ds
;
4029 AdapterDSource
*ads
;
4030 GtkCMCTreeNode
*node
, *newNode
;
4033 nodeIf
= _addressInterfaceList_
;
4035 adapter
= nodeIf
->data
;
4036 node
= adapter
->treeNode
;
4037 iface
= adapter
->interface
;
4038 atci
= adapter
->atci
;
4040 if( iface
->useInterface
) {
4041 /* Load data sources below interface node */
4042 nodeDS
= iface
->listSource
;
4045 name
= addrindex_ds_get_name( ds
);
4046 ads
= addressbook_create_ds_adapter(
4047 ds
, atci
->objectType
, name
);
4048 newNode
= addressbook_add_object(
4049 node
, ADDRESS_OBJECT(ads
) );
4050 if (newNode
== NULL
) {
4051 g_message("error adding addressbook object\n");
4053 nodeDS
= g_list_next( nodeDS
);
4055 gtk_cmctree_expand( ctree
, node
);
4058 nodeIf
= g_list_next( nodeIf
);
4063 * Convert the old address book to new format.
4065 static gboolean
addressbook_convert( AddressIndex
*addrIndex
) {
4066 gboolean retVal
= FALSE
;
4067 gboolean errFlag
= TRUE
;
4070 /* Read old address book, performing conversion */
4071 debug_print( "Reading and converting old address book...\n" );
4072 addrindex_set_file_name( addrIndex
, ADDRESSBOOK_OLD_FILE
);
4073 addrindex_read_data( addrIndex
);
4074 if( addrIndex
->retVal
== MGU_NO_FILE
) {
4075 /* We do not have a file - new user */
4076 debug_print( "New user... create new books...\n" );
4077 addrindex_create_new_books( addrIndex
);
4078 if( addrIndex
->retVal
== MGU_SUCCESS
) {
4079 /* Save index file */
4080 addrindex_set_file_name( addrIndex
, ADDRESSBOOK_INDEX_FILE
);
4081 addrindex_save_data( addrIndex
);
4082 if( addrIndex
->retVal
== MGU_SUCCESS
) {
4087 msg
= _( "New user, could not save index file." );
4091 msg
= _( "New user, could not save address book files." );
4095 /* We have an old file */
4096 if( addrIndex
->wasConverted
) {
4097 /* Converted successfully - save address index */
4098 addrindex_set_file_name( addrIndex
, ADDRESSBOOK_INDEX_FILE
);
4099 addrindex_save_data( addrIndex
);
4100 if( addrIndex
->retVal
== MGU_SUCCESS
) {
4101 msg
= _( "Old address book converted successfully." );
4106 msg
= _("Old address book converted,\n"
4107 "could not save new address index file." );
4111 /* File conversion failed - just create new books */
4112 debug_print( "File conversion failed... just create new books...\n" );
4113 addrindex_create_new_books( addrIndex
);
4114 if( addrIndex
->retVal
== MGU_SUCCESS
) {
4116 addrindex_set_file_name( addrIndex
, ADDRESSBOOK_INDEX_FILE
);
4117 addrindex_save_data( addrIndex
);
4118 if( addrIndex
->retVal
== MGU_SUCCESS
) {
4119 msg
= _("Could not convert address book,\n"
4120 "but created empty new address book files." );
4125 msg
= _("Could not convert address book,\n"
4126 "could not save new address index file." );
4130 msg
= _("Could not convert address book\n"
4131 "and could not create new address book files." );
4136 debug_print( "Error\n%s\n", msg
);
4137 alertpanel_full(_("Addressbook conversion error"), msg
,
4138 GTK_STOCK_CLOSE
, NULL
, NULL
, FALSE
,
4139 NULL
, ALERT_ERROR
, G_ALERTDEFAULT
);
4142 debug_print( "Warning\n%s\n", msg
);
4143 alertpanel_full(_("Addressbook conversion error"), msg
,
4144 GTK_STOCK_CLOSE
, NULL
, NULL
, FALSE
,
4145 NULL
, ALERT_WARNING
, G_ALERTDEFAULT
);
4151 static gboolean
migrate_addrbook(const gchar
*origdir
, const gchar
*destdir
)
4155 gboolean failed
= FALSE
;
4156 GError
*error
= NULL
;
4158 if( ( dp
= g_dir_open( origdir
, 0, &error
) ) == NULL
) {
4159 debug_print("opening '%s' failed: %d (%s)\n", origdir
,
4160 error
->code
, error
->message
);
4161 g_error_free(error
);
4165 while( ( d
= g_dir_read_name( dp
) ) != NULL
) {
4166 if (strncmp(d
, "addrbook-", strlen("addrbook-")))
4169 gchar
*orig_file
= g_strconcat(origdir
, G_DIR_SEPARATOR_S
,
4171 gchar
*dest_file
= g_strconcat(destdir
, G_DIR_SEPARATOR_S
,
4173 if (copy_file(orig_file
, dest_file
, FALSE
) < 0) {
4186 /* all copies succeeded, we can remove source files */
4187 if( ( dp
= g_dir_open( origdir
, 0, &error
) ) == NULL
) {
4188 debug_print("opening '%s' failed: %d (%s)\n", origdir
,
4189 error
->code
, error
->message
);
4190 g_error_free(error
);
4193 while( ( d
= g_dir_read_name( dp
) ) != NULL
) {
4194 if (strncmp(d
, "addrbook-", strlen("addrbook-")))
4197 gchar
*orig_file
= g_strconcat(origdir
, G_DIR_SEPARATOR_S
,
4199 claws_unlink(orig_file
);
4209 void addressbook_read_file( void ) {
4210 AddressIndex
*addrIndex
= NULL
;
4211 gchar
*indexdir
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
, ADDRBOOK_DIR
, NULL
);
4213 debug_print( "Reading address index...\n" );
4214 if( _addressIndex_
) {
4215 debug_print( "address book already read!!!\n" );
4219 addrIndex
= addrindex_create_index();
4220 addrindex_initialize();
4222 /* Use new address book index. */
4224 if ( !is_dir_exist(indexdir
) ) {
4225 if ( make_dir(indexdir
) < 0 ) {
4226 addrindex_set_file_path( addrIndex
, get_rc_dir() );
4227 g_warning( "couldn't create dir '%s'", indexdir
);
4229 if (!migrate_addrbook(get_rc_dir(), indexdir
)) {
4230 remove_dir_recursive(indexdir
);
4231 addrindex_set_file_path( addrIndex
, get_rc_dir() );
4232 g_error("couldn't migrate dir %s", indexdir
);
4234 addrindex_set_file_path( addrIndex
, indexdir
);
4238 addrindex_set_file_path( addrIndex
, indexdir
);
4241 addrindex_set_file_name( addrIndex
, ADDRESSBOOK_INDEX_FILE
);
4242 addrindex_read_data( addrIndex
);
4243 if( addrIndex
->retVal
== MGU_NO_FILE
) {
4244 /* Conversion required */
4245 debug_print( "Converting...\n" );
4246 if( addressbook_convert( addrIndex
) ) {
4247 _addressIndex_
= addrIndex
;
4250 else if( addrIndex
->retVal
== MGU_SUCCESS
) {
4251 _addressIndex_
= addrIndex
;
4254 /* Error reading address book */
4255 debug_print( "Could not read address index.\n" );
4256 addrindex_print_index( addrIndex
, stdout
);
4257 alertpanel_full(_("Addressbook Error"),
4258 _("Could not read address index"),
4259 GTK_STOCK_CLOSE
, NULL
, NULL
, FALSE
,
4260 NULL
, ALERT_ERROR
, G_ALERTDEFAULT
);
4262 debug_print( "done.\n" );
4266 * Add object into the address index tree widget.
4267 * Enter: node Parent node.
4268 * obj Object to add.
4269 * Return: Node that was added, or NULL if object not added.
4271 static GtkCMCTreeNode
*addressbook_add_object(GtkCMCTreeNode
*node
,
4274 GtkCMCTree
*ctree
= GTK_CMCTREE(addrbook
.ctree
);
4275 GtkCMCTreeNode
*added
;
4276 AddressObject
*pobj
;
4277 AddressObjectType otype
;
4278 AddressTypeControlItem
*atci
= NULL
;
4280 cm_return_val_if_fail(node
!= NULL
, NULL
);
4281 cm_return_val_if_fail(obj
!= NULL
, NULL
);
4283 pobj
= gtk_cmctree_node_get_row_data(ctree
, node
);
4284 cm_return_val_if_fail(pobj
!= NULL
, NULL
);
4286 /* Determine object type to be displayed */
4287 if( obj
->type
== ADDR_DATASOURCE
) {
4288 otype
= ADAPTER_DSOURCE(obj
)->subType
;
4294 /* Handle any special conditions. */
4296 atci
= addrbookctl_lookup( otype
);
4298 if( atci
->showInTree
) {
4299 /* Add object to tree */
4302 added
= gtk_sctree_insert_node( ctree
, node
, NULL
, name
, FOLDER_SPACING
,
4303 atci
->iconXpm
, atci
->iconXpmOpen
,
4304 atci
->treeLeaf
, atci
->treeExpand
);
4305 gtk_cmctree_node_set_row_data_full( ctree
, added
, obj
,
4306 addressbook_free_treenode
);
4310 gtk_sctree_sort_node(ctree
, node
);
4316 * Add group into the address index tree.
4317 * \param node Parent node.
4318 * \param ds Data source.
4319 * \param itemGroup Group to add.
4320 * \return Inserted node.
4322 static GtkCMCTreeNode
*addressbook_node_add_group(
4323 GtkCMCTreeNode
*node
, AddressDataSource
*ds
,
4324 ItemGroup
*itemGroup
)
4326 GtkCMCTree
*ctree
= GTK_CMCTREE(addrbook
.ctree
);
4327 GtkCMCTreeNode
*newNode
;
4328 AdapterGroup
*adapter
;
4329 AddressTypeControlItem
*atci
= NULL
;
4332 if( ds
== NULL
) return NULL
;
4333 if( node
== NULL
|| itemGroup
== NULL
) return NULL
;
4335 name
= &itemGroup
->obj
.name
;
4337 atci
= addrbookctl_lookup( ADDR_ITEM_GROUP
);
4339 adapter
= g_new0( AdapterGroup
, 1 );
4340 ADDRESS_OBJECT_TYPE(adapter
) = ADDR_ITEM_GROUP
;
4341 ADDRESS_OBJECT_NAME(adapter
) = g_strdup( ADDRITEM_NAME(itemGroup
) );
4342 adapter
->itemGroup
= itemGroup
;
4344 newNode
= gtk_sctree_insert_node( ctree
, node
, NULL
, name
, FOLDER_SPACING
,
4345 atci
->iconXpm
, atci
->iconXpm
,
4346 atci
->treeLeaf
, atci
->treeExpand
);
4347 gtk_cmctree_node_set_row_data_full( ctree
, newNode
, adapter
,
4348 addressbook_free_treenode
);
4349 gtk_sctree_sort_node( ctree
, node
);
4354 * Add folder into the address index tree. Only visible folders are loaded into
4355 * the address index tree. Note that the root folder is not inserted into the
4358 * \param node Parent node.
4359 * \param ds Data source.
4360 * \param itemFolder Folder to add.
4361 * \param otype Object type to display.
4362 * \return Inserted node for the folder.
4364 static GtkCMCTreeNode
*addressbook_node_add_folder(
4365 GtkCMCTreeNode
*node
, AddressDataSource
*ds
,
4366 ItemFolder
*itemFolder
, AddressObjectType otype
)
4368 GtkCMCTree
*ctree
= GTK_CMCTREE(addrbook
.ctree
);
4369 GtkCMCTreeNode
*newNode
= NULL
;
4370 AdapterFolder
*adapter
;
4371 AddressTypeControlItem
*atci
= NULL
;
4372 GList
*listItems
= NULL
;
4374 ItemFolder
*rootFolder
;
4376 /* Only visible folders */
4377 if( itemFolder
== NULL
|| itemFolder
->isHidden
)
4382 if( node
== NULL
|| itemFolder
== NULL
)
4385 /* Determine object type */
4386 atci
= addrbookctl_lookup( otype
);
4390 rootFolder
= addrindex_ds_get_root_folder( ds
);
4391 if( itemFolder
== rootFolder
) {
4395 adapter
= g_new0( AdapterFolder
, 1 );
4396 ADDRESS_OBJECT_TYPE(adapter
) = ADDR_ITEM_FOLDER
;
4397 ADDRESS_OBJECT_NAME(adapter
) = g_strdup( ADDRITEM_NAME(itemFolder
) );
4398 adapter
->itemFolder
= itemFolder
;
4400 name
= ADDRITEM_NAME(itemFolder
);
4401 newNode
= gtk_sctree_insert_node( ctree
, node
, NULL
, &name
, FOLDER_SPACING
,
4402 atci
->iconXpm
, atci
->iconXpm
,
4403 atci
->treeLeaf
, atci
->treeExpand
);
4405 gtk_cmctree_node_set_row_data_full( ctree
, newNode
, adapter
,
4406 addressbook_free_treenode
);
4410 listItems
= itemFolder
->listFolder
;
4411 while( listItems
) {
4412 ItemFolder
*item
= listItems
->data
;
4413 addressbook_node_add_folder( newNode
, ds
, item
, otype
);
4414 listItems
= g_list_next( listItems
);
4416 listItems
= itemFolder
->listGroup
;
4417 while( listItems
) {
4418 ItemGroup
*item
= listItems
->data
;
4419 addressbook_node_add_group( newNode
, ds
, item
);
4420 listItems
= g_list_next( listItems
);
4422 gtk_sctree_sort_node( ctree
, node
);
4426 void addressbook_export_to_file( void ) {
4427 if( _addressIndex_
) {
4428 /* Save all new address book data */
4429 debug_print( "Saving address books...\n" );
4430 addrindex_save_all_books( _addressIndex_
);
4432 debug_print( "Exporting addressbook to file...\n" );
4433 addrindex_save_data( _addressIndex_
);
4434 if( _addressIndex_
->retVal
!= MGU_SUCCESS
) {
4435 addrindex_print_index( _addressIndex_
, stdout
);
4438 /* Notify address completion of new data */
4439 invalidate_address_completion();
4443 static gboolean
addressbook_entry_key_pressed(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
4445 if (event
&& (event
->keyval
== GDK_KEY_Return
|| event
->keyval
== GDK_KEY_KP_Enter
))
4446 addressbook_lup_clicked(NULL
, NULL
);
4451 * Comparison using cell contents (text in first column). Used for sort
4452 * address index widget.
4454 static gint
addressbook_treenode_compare_func(
4455 GtkCMCList
*clist
, gconstpointer ptr1
, gconstpointer ptr2
)
4457 GtkCMCell
*cell1
= ((GtkCMCListRow
*)ptr1
)->cell
;
4458 GtkCMCell
*cell2
= ((GtkCMCListRow
*)ptr2
)->cell
;
4459 gchar
*name1
= NULL
, *name2
= NULL
;
4460 if( cell1
) name1
= cell1
->u
.text
;
4461 if( cell2
) name2
= cell2
->u
.text
;
4462 if( ! name1
) return ( name2
!= NULL
);
4463 if( ! name2
) return -1;
4464 return g_utf8_collate( name1
, name2
);
4467 static void addressbook_new_book_cb( GtkAction
*action
, gpointer data
) {
4468 AdapterDSource
*ads
;
4469 AdapterInterface
*adapter
;
4470 GtkCMCTreeNode
*newNode
;
4472 adapter
= addrbookctl_find_interface( ADDR_IF_BOOK
);
4473 if( adapter
== NULL
) return;
4474 ads
= addressbook_edit_book( _addressIndex_
, NULL
);
4476 newNode
= addressbook_add_object( adapter
->treeNode
, ADDRESS_OBJECT(ads
) );
4478 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), newNode
);
4479 addrbook
.treeSelected
= newNode
;
4484 static void addressbook_new_vcard_cb( GtkAction
*action
, gpointer data
) {
4485 AdapterDSource
*ads
;
4486 AdapterInterface
*adapter
;
4487 GtkCMCTreeNode
*newNode
;
4489 adapter
= addrbookctl_find_interface( ADDR_IF_VCARD
);
4490 if( adapter
== NULL
) return;
4491 ads
= addressbook_edit_vcard( _addressIndex_
, NULL
);
4493 newNode
= addressbook_add_object( adapter
->treeNode
, ADDRESS_OBJECT(ads
) );
4495 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), newNode
);
4496 addrbook
.treeSelected
= newNode
;
4502 static void addressbook_new_jpilot_cb( GtkAction
*action
, gpointer data
) {
4503 AdapterDSource
*ads
;
4504 AdapterInterface
*adapter
;
4505 AddressInterface
*iface
;
4506 GtkCMCTreeNode
*newNode
;
4508 adapter
= addrbookctl_find_interface( ADDR_IF_JPILOT
);
4509 if( adapter
== NULL
) return;
4510 iface
= adapter
->interface
;
4511 if( ! iface
->haveLibrary
) return;
4512 ads
= addressbook_edit_jpilot( _addressIndex_
, NULL
);
4514 newNode
= addressbook_add_object( adapter
->treeNode
, ADDRESS_OBJECT(ads
) );
4516 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), newNode
);
4517 addrbook
.treeSelected
= newNode
;
4524 static void addressbook_new_ldap_cb( GtkAction
*action
, gpointer data
) {
4525 AdapterDSource
*ads
;
4526 AdapterInterface
*adapter
;
4527 AddressInterface
*iface
;
4528 GtkCMCTreeNode
*newNode
;
4530 adapter
= addrbookctl_find_interface( ADDR_IF_LDAP
);
4531 if( adapter
== NULL
) return;
4532 iface
= adapter
->interface
;
4533 if( ! iface
->haveLibrary
) return;
4534 ads
= addressbook_edit_ldap( _addressIndex_
, NULL
);
4536 newNode
= addressbook_add_object( adapter
->treeNode
, ADDRESS_OBJECT(ads
) );
4538 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), newNode
);
4539 addrbook
.treeSelected
= newNode
;
4546 * Display address search status message.
4547 * \param queryType Query type.
4548 * \param status Status/Error code.
4550 static void addressbook_search_message( gint queryType
, gint sts
) {
4552 *addressbook_msgbuf
= '\0';
4554 if( sts
!= MGU_SUCCESS
) {
4555 if( queryType
== ADDRQUERY_LDAP
) {
4557 desc
= addressbook_err2string( _lutErrorsLDAP_
, sts
);
4562 g_snprintf( addressbook_msgbuf
,
4563 sizeof(addressbook_msgbuf
), "%s", desc
);
4564 addressbook_status_show( addressbook_msgbuf
);
4567 addressbook_status_show( "" );
4572 * Refresh addressbook by forcing refresh of current selected object in
4575 static void addressbook_refresh_current( void ) {
4579 ctree
= GTK_CMCTREE(addrbook
.ctree
);
4580 obj
= gtk_cmctree_node_get_row_data( ctree
, addrbook
.treeSelected
);
4581 if( obj
== NULL
) return;
4582 addressbook_set_clist( obj
, TRUE
);
4586 * Message that is displayed whilst a query is executing in a background
4589 static gchar
*_tempMessage_
= N_( "Busy searching..." );
4592 * Address search idle function. This function is called during UI idle time
4593 * while a search is in progress.
4595 * \param data Idler data.
4597 static void addressbook_search_idle( gpointer data
) {
4601 queryID = GPOINTER_TO_INT( data );
4602 g_print( "addressbook_ldap_idle... queryID=%d\n", queryID );
4607 * Search completion callback function. This removes the query from the idle
4610 * \param sender Sender of query.
4611 * \param queryID Query ID of search request.
4612 * \param status Search status.
4613 * \param data Query data.
4615 static void addressbook_search_callback_end(
4616 gpointer sender
, gint queryID
, gint status
, gpointer data
)
4620 AddrQueryObject
*aqo
;
4622 /* Remove idler function */
4623 ptrQID
= GINT_TO_POINTER( queryID
);
4625 g_idle_remove_by_data( ptrQID
);
4628 /* Refresh addressbook contents */
4629 addressbook_refresh_current();
4630 req
= qrymgr_find_request( queryID
);
4632 aqo
= ( AddrQueryObject
* ) req
->queryList
->data
;
4633 addressbook_search_message( aqo
->queryType
, status
);
4636 /* Stop the search */
4637 addrindex_stop_search( queryID
);
4643 * \param ds Data source to search.
4644 * \param searchTerm String to lookup.
4645 * \param pNode Parent data source node.
4647 static void addressbook_perform_search(
4648 AddressDataSource
*ds
, gchar
*searchTerm
,
4649 GtkCMCTreeNode
*pNode
)
4657 if( *searchTerm
== '\0' || strlen( searchTerm
) < 1 ) return;
4659 if( !ds
|| ds
->type
!= ADDR_IF_LDAP
) return;
4661 /* Create a folder for the search results */
4662 name
= g_strdup_printf( _queryFolderLabel_
, searchTerm
);
4663 folder
= addressbook_setup_subf(ds
, name
, pNode
);
4666 /* Setup the search */
4667 queryID
= addrindex_setup_explicit_search(
4668 ds
, searchTerm
, folder
, addressbook_search_callback_end
, NULL
);
4669 if( queryID
== 0 ) return;
4671 /* Set up idler function */
4672 idleID
= g_idle_add(
4673 (GSourceFunc
) addressbook_search_idle
,
4674 GINT_TO_POINTER( queryID
) );
4676 g_message("error adding addressbook_search_idle\n");
4679 /* Start search, sit back and wait for something to happen */
4680 addrindex_start_search( queryID
);
4682 addressbook_status_show( _tempMessage_
);
4686 * Lookup button handler. Address search is only performed against
4687 * address interfaces for external queries.
4689 * \param button Lookup button widget.
4690 * \param data Data object.
4692 static void addressbook_lup_clicked( GtkButton
*button
, gpointer data
) {
4695 AddressDataSource
*ds
;
4696 AddressInterface
*iface
;
4698 GtkCMCTreeNode
*node
, *parentNode
;
4700 node
= addrbook
.treeSelected
;
4701 if( ! node
) return;
4702 if( GTK_CMCTREE_ROW(node
)->level
== 1 ) return;
4704 ctree
= GTK_CMCTREE(addrbook
.ctree
);
4705 obj
= gtk_cmctree_node_get_row_data( ctree
, node
);
4706 if( obj
== NULL
) return;
4708 if (obj
->type
!= ADDR_DATASOURCE
||
4709 ADAPTER_DSOURCE(obj
)->subType
!= ADDR_LDAP
) {
4710 addressbook_set_clist(
4711 gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook
.ctree
),
4712 addrbook
.treeSelected
),
4716 ds
= addressbook_find_datasource( node
);
4717 if( ds
== NULL
) return;
4719 /* We must have a datasource that is an external interface */
4720 iface
= ds
->interface
;
4721 if( ! iface
->haveLibrary
) return;
4722 if( ! iface
->externalQuery
) return;
4725 gtk_editable_get_chars( GTK_EDITABLE(addrbook
.entry
), 0, -1 );
4726 g_strchomp( searchTerm
);
4728 if( obj
->type
== ADDR_ITEM_FOLDER
) {
4729 parentNode
= GTK_CMCTREE_ROW(node
)->parent
;
4734 addressbook_perform_search( ds
, searchTerm
, parentNode
);
4736 gtk_widget_grab_focus( addrbook
.entry
);
4738 g_free( searchTerm
);
4741 static void addressbook_close_clicked( GtkButton
*button
, gpointer data
) {
4742 addressbook_close();
4747 * Browse address entry for highlighted entry.
4749 static void addressbook_browse_entry_cb( GtkAction
*action
, gpointer data
)
4751 GtkCMCTree
*clist
= GTK_CMCTREE(addrbook
.clist
);
4753 AddressDataSource
*ds
;
4754 AddressInterface
*iface
;
4758 if(addrbook
.listSelected
== NULL
)
4761 obj
= gtk_cmctree_node_get_row_data(clist
, addrbook
.listSelected
);
4765 ds
= addressbook_find_datasource(GTK_CMCTREE_NODE(addrbook
.treeSelected
));
4769 iface
= ds
->interface
;
4770 if(!iface
|| !iface
->haveLibrary
)
4774 if (obj
->type
== ADDR_ITEM_EMAIL
) {
4775 email
= ( ItemEMail
* ) obj
;
4777 person
= (ItemPerson
*) ADDRITEM_PARENT(email
);
4779 else if (obj
->type
== ADDR_ITEM_PERSON
) {
4780 person
= (ItemPerson
*) obj
;
4787 if( iface
&& iface
->type
== ADDR_IF_LDAP
) {
4788 browseldap_entry(ds
, person
->externalID
);
4793 /* **********************************************************************
4794 * Build lookup tables.
4795 * ***********************************************************************
4799 * Remap object types.
4800 * Enter: abType AddressObjectType (used in tree node).
4801 * Return: ItemObjectType (used in address cache data).
4803 ItemObjectType
addressbook_type2item( AddressObjectType abType
) {
4804 ItemObjectType ioType
;
4807 case ADDR_ITEM_PERSON
: ioType
= ITEMTYPE_PERSON
; break;
4808 case ADDR_ITEM_EMAIL
: ioType
= ITEMTYPE_EMAIL
; break;
4809 case ADDR_ITEM_FOLDER
: ioType
= ITEMTYPE_FOLDER
; break;
4810 case ADDR_ITEM_GROUP
: ioType
= ITEMTYPE_GROUP
; break;
4811 case ADDR_DATASOURCE
: ioType
= ITEMTYPE_DATASOURCE
; break;
4812 default: ioType
= ITEMTYPE_NONE
; break;
4817 #define UPDATE_ICON_ATCI(id,icon,iconopen) { \
4818 atci = addrbookctl_lookup(id); \
4820 atci->iconXpm = icon; \
4821 atci->iconXpmOpen = iconopen; \
4823 g_warning("can't get atci %d", id); \
4828 * Build table that controls the rendering of object types.
4830 static void addrbookctl_build_icons( GtkWidget
*window
) {
4831 AddressTypeControlItem
*atci
;
4835 g_object_unref(interfacexpm
);
4837 g_object_unref(folderxpm
);
4839 g_object_unref(folderopenxpm
);
4841 g_object_unref(groupxpm
);
4843 g_object_unref(vcardxpm
);
4845 g_object_unref(bookxpm
);
4847 g_object_unref(addressxpm
);
4849 g_object_unref(jpilotxpm
);
4851 g_object_unref(categoryxpm
);
4853 g_object_unref(ldapxpm
);
4855 g_object_unref(addrsearchxpm
);
4856 stock_pixbuf_gdk(STOCK_PIXMAP_INTERFACE
, &interfacexpm
);
4857 stock_pixbuf_gdk(STOCK_PIXMAP_DIR_CLOSE
, &folderxpm
);
4858 stock_pixbuf_gdk(STOCK_PIXMAP_DIR_OPEN
, &folderopenxpm
);
4859 stock_pixbuf_gdk(STOCK_PIXMAP_GROUP
, &groupxpm
);
4860 stock_pixbuf_gdk(STOCK_PIXMAP_VCARD
, &vcardxpm
);
4861 stock_pixbuf_gdk(STOCK_PIXMAP_BOOK
, &bookxpm
);
4862 stock_pixbuf_gdk(STOCK_PIXMAP_ADDRESS
, &addressxpm
);
4863 stock_pixbuf_gdk(STOCK_PIXMAP_JPILOT
, &jpilotxpm
);
4864 stock_pixbuf_gdk(STOCK_PIXMAP_CATEGORY
, &categoryxpm
);
4865 stock_pixbuf_gdk(STOCK_PIXMAP_LDAP
, &ldapxpm
);
4866 stock_pixbuf_gdk(STOCK_PIXMAP_ADDRESS_SEARCH
, &addrsearchxpm
);
4868 UPDATE_ICON_ATCI(ADDR_INTERFACE
,folderxpm
,folderopenxpm
);
4869 UPDATE_ICON_ATCI(ADDR_BOOK
,bookxpm
,bookxpm
);
4870 UPDATE_ICON_ATCI(ADDR_ITEM_PERSON
,NULL
,NULL
);
4871 UPDATE_ICON_ATCI(ADDR_ITEM_EMAIL
,addressxpm
,addressxpm
);
4872 UPDATE_ICON_ATCI(ADDR_ITEM_GROUP
,groupxpm
,groupxpm
);
4873 UPDATE_ICON_ATCI(ADDR_ITEM_FOLDER
,folderxpm
,folderopenxpm
);
4874 UPDATE_ICON_ATCI(ADDR_VCARD
,vcardxpm
,vcardxpm
);
4875 UPDATE_ICON_ATCI(ADDR_JPILOT
,jpilotxpm
,jpilotxpm
);
4876 UPDATE_ICON_ATCI(ADDR_CATEGORY
,categoryxpm
,categoryxpm
);
4877 UPDATE_ICON_ATCI(ADDR_LDAP
,ldapxpm
,ldapxpm
);
4878 UPDATE_ICON_ATCI(ADDR_LDAP_QUERY
,addrsearchxpm
,addrsearchxpm
);
4883 * Build table that controls the rendering of object types.
4885 static void addrbookctl_build_map( GtkWidget
*window
) {
4886 AddressTypeControlItem
*atci
;
4888 _addressBookTypeHash_
= g_hash_table_new( g_int_hash
, g_int_equal
);
4889 _addressBookTypeList_
= NULL
;
4892 atci
= g_new0( AddressTypeControlItem
, 1 );
4893 atci
->objectType
= ADDR_INTERFACE
;
4894 atci
->interfaceType
= ADDR_IF_NONE
;
4895 atci
->showInTree
= TRUE
;
4896 atci
->treeExpand
= TRUE
;
4897 atci
->treeLeaf
= FALSE
;
4898 atci
->displayName
= _( "Interface" );
4899 atci
->menuCommand
= NULL
;
4900 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4901 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4904 atci
= g_new0( AddressTypeControlItem
, 1 );
4905 atci
->objectType
= ADDR_BOOK
;
4906 atci
->interfaceType
= ADDR_IF_BOOK
;
4907 atci
->showInTree
= TRUE
;
4908 atci
->treeExpand
= TRUE
;
4909 atci
->treeLeaf
= FALSE
;
4910 atci
->displayName
= _("Address Books");
4911 atci
->menuCommand
= "Menu/Book/NewBook";
4912 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4913 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4916 atci
= g_new0( AddressTypeControlItem
, 1 );
4917 atci
->objectType
= ADDR_ITEM_PERSON
;
4918 atci
->interfaceType
= ADDR_IF_NONE
;
4919 atci
->showInTree
= FALSE
;
4920 atci
->treeExpand
= FALSE
;
4921 atci
->treeLeaf
= FALSE
;
4922 atci
->displayName
= _( "Person" );
4923 atci
->menuCommand
= NULL
;
4924 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4925 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4928 atci
= g_new0( AddressTypeControlItem
, 1 );
4929 atci
->objectType
= ADDR_ITEM_EMAIL
;
4930 atci
->interfaceType
= ADDR_IF_NONE
;
4931 atci
->showInTree
= FALSE
;
4932 atci
->treeExpand
= FALSE
;
4933 atci
->treeLeaf
= TRUE
;
4934 atci
->displayName
= _( "Email Address" );
4935 atci
->menuCommand
= NULL
;
4936 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4937 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4940 atci
= g_new0( AddressTypeControlItem
, 1 );
4941 atci
->objectType
= ADDR_ITEM_GROUP
;
4942 atci
->interfaceType
= ADDR_IF_BOOK
;
4943 atci
->showInTree
= TRUE
;
4944 atci
->treeExpand
= FALSE
;
4945 atci
->treeLeaf
= FALSE
;
4946 atci
->displayName
= _( "Group" );
4947 atci
->menuCommand
= NULL
;
4948 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4949 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4952 atci
= g_new0( AddressTypeControlItem
, 1 );
4953 atci
->objectType
= ADDR_ITEM_FOLDER
;
4954 atci
->interfaceType
= ADDR_IF_BOOK
;
4955 atci
->showInTree
= TRUE
;
4956 atci
->treeExpand
= FALSE
;
4957 atci
->treeLeaf
= FALSE
;
4958 atci
->displayName
= _( "Folder" );
4959 atci
->menuCommand
= NULL
;
4960 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4961 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4964 atci
= g_new0( AddressTypeControlItem
, 1 );
4965 atci
->objectType
= ADDR_VCARD
;
4966 atci
->interfaceType
= ADDR_IF_VCARD
;
4967 atci
->showInTree
= TRUE
;
4968 atci
->treeExpand
= TRUE
;
4969 atci
->treeLeaf
= TRUE
;
4970 atci
->displayName
= _( "vCard" );
4971 atci
->menuCommand
= "Menu/Book/NewVCard";
4972 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4973 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4976 atci
= g_new0( AddressTypeControlItem
, 1 );
4977 atci
->objectType
= ADDR_JPILOT
;
4978 atci
->interfaceType
= ADDR_IF_JPILOT
;
4979 atci
->showInTree
= TRUE
;
4980 atci
->treeExpand
= TRUE
;
4981 atci
->treeLeaf
= FALSE
;
4982 atci
->displayName
= _( "JPilot" );
4983 atci
->menuCommand
= "Menu/Book/NewJPilot";
4984 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4985 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
4988 atci
= g_new0( AddressTypeControlItem
, 1 );
4989 atci
->objectType
= ADDR_CATEGORY
;
4990 atci
->interfaceType
= ADDR_IF_JPILOT
;
4991 atci
->showInTree
= TRUE
;
4992 atci
->treeExpand
= TRUE
;
4993 atci
->treeLeaf
= TRUE
;
4994 atci
->displayName
= _( "JPilot" );
4995 atci
->menuCommand
= NULL
;
4996 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
4997 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
5000 atci
= g_new0( AddressTypeControlItem
, 1 );
5001 atci
->objectType
= ADDR_LDAP
;
5002 atci
->interfaceType
= ADDR_IF_LDAP
;
5003 atci
->showInTree
= TRUE
;
5004 atci
->treeExpand
= TRUE
;
5005 atci
->treeLeaf
= FALSE
;
5006 atci
->displayName
= _( "LDAP servers" );
5007 atci
->menuCommand
= "Menu/Book/NewLDAPServer";
5008 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
5009 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
5012 atci
= g_new0( AddressTypeControlItem
, 1 );
5013 atci
->objectType
= ADDR_LDAP_QUERY
;
5014 atci
->interfaceType
= ADDR_IF_LDAP
;
5015 atci
->showInTree
= TRUE
;
5016 atci
->treeExpand
= FALSE
;
5017 atci
->treeLeaf
= TRUE
;
5018 atci
->displayName
= _( "LDAP Query" );
5019 atci
->menuCommand
= NULL
;
5020 g_hash_table_insert( _addressBookTypeHash_
, &atci
->objectType
, atci
);
5021 _addressBookTypeList_
= g_list_append( _addressBookTypeList_
, atci
);
5023 addrbookctl_build_icons(window
);
5026 void addressbook_reflect_prefs_pixmap_theme(void)
5028 if (addrbook
.window
)
5029 addrbookctl_build_icons(addrbook
.window
);
5033 * Search for specified object type.
5035 static AddressTypeControlItem
*addrbookctl_lookup( gint ot
) {
5037 return ( AddressTypeControlItem
* ) g_hash_table_lookup( _addressBookTypeHash_
, &objType
);
5041 * Search for specified interface type.
5043 static AddressTypeControlItem
*addrbookctl_lookup_iface( AddressIfType ifType
) {
5044 GList
*node
= _addressBookTypeList_
;
5046 AddressTypeControlItem
*atci
= node
->data
;
5047 if( atci
->interfaceType
== ifType
) return atci
;
5048 node
= g_list_next( node
);
5053 static void addrbookctl_free_address( AddressObject
*obj
) {
5054 g_free( obj
->name
);
5055 obj
->type
= ADDR_NONE
;
5059 static void addrbookctl_free_interface( AdapterInterface
*adapter
) {
5060 addrbookctl_free_address( ADDRESS_OBJECT(adapter
) );
5061 adapter
->interface
= NULL
;
5062 adapter
->interfaceType
= ADDR_IF_NONE
;
5063 adapter
->atci
= NULL
;
5064 adapter
->enabled
= FALSE
;
5065 adapter
->haveLibrary
= FALSE
;
5066 adapter
->treeNode
= NULL
;
5070 static void addrbookctl_free_datasource( AdapterDSource
*adapter
) {
5071 addrbookctl_free_address( ADDRESS_OBJECT(adapter
) );
5072 adapter
->dataSource
= NULL
;
5073 adapter
->subType
= ADDR_NONE
;
5077 static void addrbookctl_free_folder( AdapterFolder
*adapter
) {
5078 addrbookctl_free_address( ADDRESS_OBJECT(adapter
) );
5079 adapter
->itemFolder
= NULL
;
5083 static void addrbookctl_free_group( AdapterGroup
*adapter
) {
5084 addrbookctl_free_address( ADDRESS_OBJECT(adapter
) );
5085 adapter
->itemGroup
= NULL
;
5090 * Build GUI interface list.
5092 static void addrbookctl_build_iflist( void ) {
5093 AddressTypeControlItem
*atci
;
5094 AdapterInterface
*adapter
;
5097 if( _addressIndex_
== NULL
) {
5098 _addressIndex_
= addrindex_create_index();
5099 if( _clipBoard_
== NULL
) {
5100 _clipBoard_
= addrclip_create();
5102 addrclip_set_index( _clipBoard_
, _addressIndex_
);
5104 _addressInterfaceList_
= NULL
;
5105 list
= addrindex_get_interface_list( _addressIndex_
);
5107 AddressInterface
*interface
= list
->data
;
5108 atci
= addrbookctl_lookup_iface( interface
->type
);
5110 adapter
= g_new0( AdapterInterface
, 1 );
5111 adapter
->interfaceType
= interface
->type
;
5112 adapter
->atci
= atci
;
5113 adapter
->interface
= interface
;
5114 adapter
->treeNode
= NULL
;
5115 adapter
->enabled
= TRUE
;
5116 adapter
->haveLibrary
= interface
->haveLibrary
;
5117 ADDRESS_OBJECT(adapter
)->type
= ADDR_INTERFACE
;
5118 ADDRESS_OBJECT_NAME(adapter
) = g_strdup( atci
->displayName
);
5119 _addressInterfaceList_
=
5120 g_list_append( _addressInterfaceList_
, adapter
);
5122 list
= g_list_next( list
);
5127 * Find GUI interface type specified interface type.
5128 * \param ifType Interface type.
5129 * \return Interface item, or NULL if not found.
5131 static AdapterInterface
*addrbookctl_find_interface( AddressIfType ifType
) {
5132 GList
*node
= _addressInterfaceList_
;
5134 AdapterInterface
*adapter
= node
->data
;
5135 if( adapter
->interfaceType
== ifType
) return adapter
;
5136 node
= g_list_next( node
);
5142 * Build interface list selection.
5144 static void addrbookctl_build_ifselect( void ) {
5145 GList
*newList
= NULL
;
5150 gchar
*endptr
= NULL
;
5151 /* gboolean enabled; */
5152 AdapterInterface
*adapter
;
5154 selectStr
= g_strdup( ADDRESSBOOK_IFACE_SELECTION
);
5157 splitStr
= g_strsplit( selectStr
, ",", -1 );
5158 for( i
= 0; i
< ADDRESSBOOK_MAX_IFACE
; i
++ ) {
5160 /* g_print( "%d : %s\n", i, splitStr[i] ); */
5161 ifType
= strtol( splitStr
[i
], &endptr
, 10 );
5164 if( strcmp( endptr, "/n" ) == 0 ) {
5169 /* g_print( "\t%d : %s\n", ifType, enabled ? "yes" : "no" ); */
5170 adapter
= addrbookctl_find_interface( ifType
);
5172 newList
= g_list_append( newList
, adapter
);
5179 /* g_print( "i=%d\n", i ); */
5180 g_strfreev( splitStr
);
5181 g_free( selectStr
);
5183 /* Replace existing list */
5184 mgu_clear_list( _addressIFaceSelection_
);
5185 g_list_free( _addressIFaceSelection_
);
5186 _addressIFaceSelection_
= newList
;
5190 /* ***********************************************************************
5191 * Add sender to address book.
5192 * ***********************************************************************
5196 * This function is used by the Add sender to address book function.
5198 gboolean
addressbook_add_contact(
5199 const gchar
*name
, const gchar
*address
, const gchar
*remarks
,
5200 GdkPixbuf
*picture
)
5202 debug_print( "addressbook_add_contact: name/address: %s - %s\n", name
, address
);
5203 if( addressadd_selection( _addressIndex_
, name
, address
, remarks
, picture
) ) {
5204 debug_print( "addressbook_add_contact - added\n" );
5205 addressbook_refresh();
5210 /* ***********************************************************************
5211 * Book/folder selection.
5212 * ***********************************************************************
5216 * This function is used by the matcher dialog to select a book/folder.
5218 gchar
*addressbook_folder_selection( const gchar
*folderpath
)
5220 AddressBookFile
*book
= NULL
;
5221 ItemFolder
*folder
= NULL
;
5224 cm_return_val_if_fail( folderpath
!= NULL
, NULL
);
5226 if ( addressbook_foldersel_selection( _addressIndex_
, &book
, &folder
, folderpath
)
5228 if ( folder
!= NULL
) {
5230 gchar
*oldtmp
= NULL
;
5231 AddrItemObject
*obj
= NULL
;
5233 /* walk thru folder->parent to build the full folder path */
5234 /* TODO: wwp: optimize this */
5236 tmp
= g_strdup(obj
->uid
);
5237 while ( obj
->parent
) {
5239 if ( obj
->name
!= NULL
) {
5240 oldtmp
= g_strdup(tmp
);
5242 tmp
= g_strdup_printf("%s/%s", obj
->uid
, oldtmp
);
5246 path
= g_strdup_printf("%s/%s", book
->fileName
, tmp
);
5249 path
= g_strdup_printf("%s", book
->fileName
);
5251 debug_print( "addressbook_foldersel: %s\n", path
?path
:"(null)");
5257 /* ***********************************************************************
5258 * Book/folder checking.
5259 * ***********************************************************************
5262 static FolderInfo
*addressbook_peek_subfolder_exists_create_folderinfo( AddressBookFile
*abf
, ItemFolder
*folder
)
5264 FolderInfo
*fi
= g_new0( FolderInfo
, 1 );
5266 fi
->folder
= folder
;
5270 static void addressbook_peek_subfolder_exists_load_folder( ItemFolder
*parentFolder
,
5271 FolderInfo
*fiParent
, FolderPathMatch
*match
)
5277 FolderPathMatch
*nextmatch
= NULL
;
5282 list
= parentFolder
->listFolder
;
5284 folder
= list
->data
;
5285 fName
= g_strdup( ADDRITEM_NAME(folder
) );
5287 /* match folder name, match pointer will be set to NULL if next recursive call
5288 doesn't need to match subfolder name */
5289 if ( match
!= NULL
&&
5290 match
->matched
== FALSE
) {
5291 if ( strcmp(match
->folder_path
[match
->index
], folder
->obj
.uid
) == 0 ) {
5292 /* folder name matches, prepare next subfolder match */
5293 debug_print("matched folder name '%s'\n", fName
);
5295 if ( match
->folder_path
[match
->index
] == NULL
) {
5296 /* we've matched all elements */
5297 match
->matched
= TRUE
;
5298 match
->folder
= folder
;
5299 debug_print("book/folder path matched!\n");
5301 /* keep on matching */
5309 fi
= addressbook_peek_subfolder_exists_create_folderinfo( fiParent
->book
, folder
);
5310 addressbook_peek_subfolder_exists_load_folder( folder
, fi
, nextmatch
);
5312 list
= g_list_next( list
);
5317 * This function is used by to check if a matcher book/folder path corresponds to an
5318 existing addressbook book/folder ("" or "Any" are considered as valid, NULL invalid).
5319 Caution: returned book and folder pointers can be NULL even when returning TRUE:
5320 if book AND folder are NULL this means that folderpath was empty or Any.
5321 If folderpath is a simple book name (without folder), book will not be NULL and folder
5322 will be NULL. It's not expected to return book as NULL and folder as non NULL.
5325 gboolean
addressbook_peek_folder_exists( gchar
*folderpath
,
5326 AddressDataSource
**book
,
5327 ItemFolder
**folder
)
5329 AddressDataSource
*ds
;
5330 GList
*list
, *nodeDS
;
5331 ItemFolder
*rootFolder
;
5332 AddressBookFile
*abf
;
5334 FolderPathMatch folder_path_match
= { NULL
, FALSE
, 0, NULL
, NULL
};
5341 if ( folderpath
== NULL
)
5344 if ( strcasecmp(folderpath
, "Any") == 0 || *folderpath
== '\0' )
5347 /* split the folder path we've received, we'll try to match this path, subpath by
5348 subpath against the book/folder structure in order */
5349 folder_path_match
.folder_path
= g_strsplit( folderpath
, "/", 256 );
5350 if (!folder_path_match
.folder_path
)
5353 list
= addrindex_get_interface_list( _addressIndex_
);
5354 while ( list
&& !folder_path_match
.matched
) {
5355 AddressInterface
*interface
= list
->data
;
5356 if ( interface
&& interface
->type
== ADDR_IF_BOOK
) {
5357 nodeDS
= interface
->listSource
;
5358 while ( nodeDS
&& !folder_path_match
.matched
) {
5361 /* Read address book */
5362 if( ! addrindex_ds_get_read_flag( ds
) ) {
5363 addrindex_ds_read_data( ds
);
5366 /* Add node for address book */
5367 abf
= ds
->rawDataSource
;
5369 /* match book name */
5370 if ( abf
&& abf
->fileName
&&
5371 strcmp(folder_path_match
.folder_path
[0], abf
->fileName
) == 0 ) {
5373 debug_print("matched book name '%s'\n", abf
->fileName
);
5374 folder_path_match
.book
= ds
;
5376 if ( folder_path_match
.folder_path
[1] == NULL
) {
5377 /* no folder part to match */
5379 folder_path_match
.matched
= TRUE
;
5380 folder_path_match
.folder
= NULL
;
5381 debug_print("book path matched!\n");
5384 /* match folder part */
5386 fi
= addressbook_peek_subfolder_exists_create_folderinfo( abf
, NULL
);
5387 rootFolder
= addrindex_ds_get_root_folder( ds
);
5389 /* prepare for recursive call */
5390 folder_path_match
.index
= 1;
5391 /* this call will set folder_path_match.matched and folder_path_match.folder */
5392 addressbook_peek_subfolder_exists_load_folder( rootFolder
, fi
, &folder_path_match
);
5397 nodeDS
= g_list_next( nodeDS
);
5400 list
= g_list_next( list
);
5403 g_strfreev( folder_path_match
.folder_path
);
5406 *book
= folder_path_match
.book
;
5408 *folder
= folder_path_match
.folder
;
5409 return folder_path_match
.matched
;
5413 /* **********************************************************************
5415 * ***********************************************************************
5421 static void addressbook_import_ldif_cb( GtkAction
*action
, gpointer data
) {
5422 AddressDataSource
*ds
= NULL
;
5423 AdapterDSource
*ads
= NULL
;
5424 AddressBookFile
*abf
= NULL
;
5425 AdapterInterface
*adapter
;
5426 GtkCMCTreeNode
*newNode
;
5428 adapter
= addrbookctl_find_interface( ADDR_IF_BOOK
);
5430 if( adapter
->treeNode
) {
5431 abf
= addressbook_imp_ldif( _addressIndex_
);
5433 ds
= addrindex_index_add_datasource(
5434 _addressIndex_
, ADDR_IF_BOOK
, abf
);
5435 ads
= addressbook_create_ds_adapter(
5436 ds
, ADDR_BOOK
, NULL
);
5437 addressbook_ads_set_name(
5438 ads
, addrbook_get_name( abf
) );
5439 newNode
= addressbook_add_object(
5441 ADDRESS_OBJECT(ads
) );
5443 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
),
5445 addrbook
.treeSelected
= newNode
;
5448 /* Notify address completion */
5449 invalidate_address_completion();
5458 static void addressbook_import_mutt_cb( GtkAction
*action
, gpointer data
) {
5459 AddressDataSource
*ds
= NULL
;
5460 AdapterDSource
*ads
= NULL
;
5461 AddressBookFile
*abf
= NULL
;
5462 AdapterInterface
*adapter
;
5463 GtkCMCTreeNode
*newNode
;
5465 adapter
= addrbookctl_find_interface( ADDR_IF_BOOK
);
5467 if( adapter
->treeNode
) {
5468 abf
= addressbook_imp_mutt( _addressIndex_
);
5470 ds
= addrindex_index_add_datasource(
5471 _addressIndex_
, ADDR_IF_BOOK
, abf
);
5472 ads
= addressbook_create_ds_adapter(
5473 ds
, ADDR_BOOK
, NULL
);
5474 addressbook_ads_set_name(
5475 ads
, addrbook_get_name( abf
) );
5476 newNode
= addressbook_add_object(
5478 ADDRESS_OBJECT(ads
) );
5480 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
),
5482 addrbook
.treeSelected
= newNode
;
5485 /* Notify address completion */
5486 invalidate_address_completion();
5495 static void addressbook_import_pine_cb( GtkAction
*action
, gpointer data
) {
5496 AddressDataSource
*ds
= NULL
;
5497 AdapterDSource
*ads
= NULL
;
5498 AddressBookFile
*abf
= NULL
;
5499 AdapterInterface
*adapter
;
5500 GtkCMCTreeNode
*newNode
;
5502 adapter
= addrbookctl_find_interface( ADDR_IF_BOOK
);
5504 if( adapter
->treeNode
) {
5505 abf
= addressbook_imp_pine( _addressIndex_
);
5507 ds
= addrindex_index_add_datasource(
5508 _addressIndex_
, ADDR_IF_BOOK
, abf
);
5509 ads
= addressbook_create_ds_adapter(
5510 ds
, ADDR_BOOK
, NULL
);
5511 addressbook_ads_set_name(
5512 ads
, addrbook_get_name( abf
) );
5513 newNode
= addressbook_add_object(
5515 ADDRESS_OBJECT(ads
) );
5517 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
),
5519 addrbook
.treeSelected
= newNode
;
5522 /* Notify address completion */
5523 invalidate_address_completion();
5530 * Harvest addresses.
5531 * \param folderItem Folder to import.
5532 * \param sourceInd Source indicator: FALSE - Folder, TRUE - Messages.
5533 * \param msgList List of message numbers, or NULL to process folder.
5535 void addressbook_harvest(
5536 FolderItem
*folderItem
, gboolean sourceInd
, GList
*msgList
)
5538 AddressDataSource
*ds
= NULL
;
5539 AdapterDSource
*ads
= NULL
;
5540 AddressBookFile
*abf
= NULL
;
5541 AdapterInterface
*adapter
;
5542 GtkCMCTreeNode
*newNode
;
5544 abf
= addrgather_dlg_execute(
5545 folderItem
, _addressIndex_
, sourceInd
, msgList
);
5547 ds
= addrindex_index_add_datasource(
5548 _addressIndex_
, ADDR_IF_BOOK
, abf
);
5550 adapter
= addrbookctl_find_interface( ADDR_IF_BOOK
);
5552 if( adapter
->treeNode
) {
5553 ads
= addressbook_create_ds_adapter(
5554 ds
, ADDR_BOOK
, addrbook_get_name( abf
) );
5555 newNode
= addressbook_add_object(
5557 ADDRESS_OBJECT(ads
) );
5558 if (newNode
== NULL
) {
5559 g_message("error adding addressbook object\n");
5564 /* Notify address completion */
5565 invalidate_address_completion();
5572 static void addressbook_export_html_cb( GtkAction
*action
, gpointer data
) {
5573 GtkCMCTree
*ctree
= GTK_CMCTREE(addrbook
.ctree
);
5575 AddressDataSource
*ds
= NULL
;
5576 AddrBookBase
*adbase
;
5577 AddressCache
*cache
;
5578 GtkCMCTreeNode
*node
= NULL
;
5580 if( ! addrbook
.treeSelected
) return;
5581 node
= addrbook
.treeSelected
;
5582 if( GTK_CMCTREE_ROW(node
)->level
== 1 ) return;
5583 obj
= gtk_cmctree_node_get_row_data( ctree
, node
);
5584 if( obj
== NULL
) return;
5586 ds
= addressbook_find_datasource( node
);
5587 if( ds
== NULL
) return;
5588 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
5589 cache
= adbase
->addressCache
;
5590 addressbook_exp_html( cache
);
5596 static void addressbook_export_ldif_cb( GtkAction
*action
, gpointer data
) {
5597 GtkCMCTree
*ctree
= GTK_CMCTREE(addrbook
.ctree
);
5599 AddressDataSource
*ds
= NULL
;
5600 AddrBookBase
*adbase
;
5601 AddressCache
*cache
;
5602 GtkCMCTreeNode
*node
= NULL
;
5604 if( ! addrbook
.treeSelected
) return;
5605 node
= addrbook
.treeSelected
;
5606 if( GTK_CMCTREE_ROW(node
)->level
== 1 ) return;
5607 obj
= gtk_cmctree_node_get_row_data( ctree
, node
);
5608 if( obj
== NULL
) return;
5610 ds
= addressbook_find_datasource( node
);
5611 if( ds
== NULL
) return;
5612 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
5613 cache
= adbase
->addressCache
;
5614 addressbook_exp_ldif( cache
);
5617 static void addressbook_find_duplicates_cb(GtkAction
*action
, gpointer data
)
5619 addrduplicates_find(GTK_WINDOW(addrbook
.window
));
5622 static void addressbook_edit_custom_attr_cb(GtkAction
*action
, gpointer data
)
5624 addressbook_custom_attr_edit();
5627 static void addressbook_start_drag(GtkWidget
*widget
, gint button
,
5631 GdkDragContext
*context
;
5632 if (addressbook_target_list
== NULL
)
5633 addressbook_target_list
= gtk_target_list_new(
5634 addressbook_drag_types
, 1);
5635 context
= gtk_drag_begin(widget
, addressbook_target_list
,
5636 GDK_ACTION_MOVE
|GDK_ACTION_COPY
|GDK_ACTION_DEFAULT
, button
, event
);
5637 gtk_drag_set_icon_default(context
);
5640 static void addressbook_drag_data_get(GtkWidget
*widget
,
5641 GdkDragContext
*drag_context
,
5642 GtkSelectionData
*selection_data
,
5647 AddrItemObject
*aio
= NULL
;
5648 AddressObject
*pobj
= NULL
;
5649 AdapterDSource
*ads
= NULL
;
5650 AddressDataSource
*ds
= NULL
;
5653 pobj
= gtk_cmctree_node_get_row_data( GTK_CMCTREE(addrbook
.ctree
), addrbook
.treeSelected
);
5655 if( pobj
== NULL
) return;
5657 if( pobj
->type
== ADDR_DATASOURCE
) {
5658 ads
= ADAPTER_DSOURCE(pobj
);
5659 ds
= ads
->dataSource
;
5660 } else if (pobj
->type
== ADDR_ITEM_GROUP
) {
5665 else if( pobj
->type
!= ADDR_INTERFACE
) {
5666 ds
= addressbook_find_datasource( addrbook
.treeSelected
);
5672 for(cur
= GTK_CMCLIST(addrbook
.clist
)->selection
; cur
; cur
= cur
->next
) {
5673 aio
= (AddrItemObject
*)gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook
.clist
),
5674 GTK_CMCTREE_NODE(cur
->data
));
5675 while (aio
&& aio
->type
!= ITEMTYPE_PERSON
) {
5680 if (aio
&& aio
->type
== ITEMTYPE_PERSON
) {
5681 if( ds
&& ds
->interface
&& ds
->interface
->readOnly
)
5682 gtk_selection_data_set(selection_data
,
5683 gtk_selection_data_get_target(selection_data
), 8,
5684 (const guchar
*)"Dummy_addr_copy", 15);
5686 gtk_selection_data_set(selection_data
,
5687 gtk_selection_data_get_target(selection_data
), 8,
5688 (const guchar
*)"Dummy_addr_move", 15);
5692 static gboolean
addressbook_drag_motion_cb(GtkWidget
*widget
,
5693 GdkDragContext
*context
,
5699 GtkAllocation allocation
;
5700 GtkRequisition requisition
;
5702 GtkCMCTreeNode
*node
= NULL
;
5703 gboolean acceptable
= FALSE
;
5704 gtk_widget_get_allocation(GTK_WIDGET(addrbook
.ctree
), &allocation
);
5705 gint height
= allocation
.height
;
5706 gtk_widget_get_requisition(GTK_WIDGET(addrbook
.ctree
), &requisition
);
5707 gint total_height
= requisition
.height
;
5708 GtkAdjustment
*pos
= gtk_scrolled_window_get_vadjustment(
5709 GTK_SCROLLED_WINDOW(addrbook
.ctree_swin
));
5710 gfloat vpos
= gtk_adjustment_get_value(pos
);
5712 if (gtk_cmclist_get_selection_info
5713 (GTK_CMCLIST(widget
), x
- 24, y
- 24, &row
, &column
)) {
5715 if (y
> height
- 24 && height
+ vpos
< total_height
) {
5716 gtk_adjustment_set_value(pos
, (vpos
+5 > height
? height
: vpos
+5));
5717 gtk_adjustment_changed(pos
);
5719 if (y
< 24 && y
> 0) {
5720 gtk_adjustment_set_value(pos
, (vpos
-5 < 0 ? 0 : vpos
-5));
5721 gtk_adjustment_changed(pos
);
5723 node
= gtk_cmctree_node_nth(GTK_CMCTREE(widget
), row
);
5726 AddressObject
*obj
= gtk_cmctree_node_get_row_data(GTK_CMCTREE(widget
), node
);
5727 if( obj
->type
== ADDR_ITEM_FOLDER
5728 || obj
->type
== ADDR_ITEM_GROUP
)
5731 AdapterDSource
*ads
= NULL
;
5732 AddressDataSource
*ds
= NULL
;
5733 ads
= ADAPTER_DSOURCE(obj
);
5734 if (ads
== NULL
){ return FALSE
;}
5735 ds
= ads
->dataSource
;
5736 if (ds
== NULL
) { return FALSE
;}
5744 g_signal_handlers_block_by_func
5746 G_CALLBACK(addressbook_tree_selected
), NULL
);
5747 gtk_sctree_select( GTK_SCTREE(widget
), node
);
5748 g_signal_handlers_unblock_by_func
5750 G_CALLBACK(addressbook_tree_selected
), NULL
);
5751 gdk_drag_status(context
,
5752 (gdk_drag_context_get_actions(context
) == GDK_ACTION_COPY
?
5753 GDK_ACTION_COPY
: GDK_ACTION_MOVE
) , time
);
5755 gdk_drag_status(context
, 0, time
);
5760 static void addressbook_drag_leave_cb(GtkWidget
*widget
,
5761 GdkDragContext
*context
,
5765 if (addrbook
.treeSelected
) {
5766 g_signal_handlers_block_by_func
5768 G_CALLBACK(addressbook_tree_selected
), NULL
);
5769 gtk_sctree_select( GTK_SCTREE(widget
), addrbook
.opened
);
5770 g_signal_handlers_unblock_by_func
5772 G_CALLBACK(addressbook_tree_selected
), NULL
);
5777 static void addressbook_drag_received_cb(GtkWidget
*widget
,
5778 GdkDragContext
*drag_context
,
5781 GtkSelectionData
*data
,
5787 GtkCMCTreeNode
*node
;
5788 GtkCMCTreeNode
*lastopened
= addrbook
.opened
;
5790 if (!strncmp(gtk_selection_data_get_data(data
), "Dummy_addr", 10)) {
5791 if (gtk_cmclist_get_selection_info
5792 (GTK_CMCLIST(widget
), x
- 24, y
- 24, &row
, &column
) == 0) {
5796 node
= gtk_cmctree_node_nth(GTK_CMCTREE(widget
), row
);
5797 if( !node
|| !gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook
.ctree
), node
))
5800 gtk_cmclist_freeze(GTK_CMCLIST(addrbook
.clist
));
5801 if (gdk_drag_context_get_selected_action(drag_context
) == GDK_ACTION_COPY
||
5802 !strcmp(gtk_selection_data_get_data(data
), "Dummy_addr_copy"))
5803 addressbook_clip_copy_cb(NULL
, NULL
);
5805 addressbook_clip_cut_cb(NULL
, NULL
);
5806 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), node
);
5807 addressbook_clip_paste_cb(NULL
,NULL
);
5808 gtk_sctree_select( GTK_SCTREE(addrbook
.ctree
), lastopened
);
5809 gtk_cmclist_thaw(GTK_CMCLIST(addrbook
.clist
));
5810 gtk_drag_finish(drag_context
, TRUE
, TRUE
, time
);