2007-11-27 [wwp] 3.1.0cvs32
[claws.git] / src / editaddress.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
4  *
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.
9  *
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.
14  *
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/>.
17  * 
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "defs.h"
25
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <gtk/gtkwindow.h>
30 #include <gtk/gtksignal.h>
31 #include <gtk/gtklabel.h>
32 #include <gtk/gtkvbox.h>
33 #include <gtk/gtkentry.h>
34 #include <gtk/gtktable.h>
35
36 #include "alertpanel.h"
37 #include "mgutils.h"
38 #include "addressbook.h"
39 #include "addressitem.h"
40 #include "addritem.h"
41 #include "addrbook.h"
42 #include "manage_window.h"
43 #include "gtkutils.h"
44 #include "filesel.h"
45 #include "codeconv.h"
46 #include "editaddress.h"
47 #include "editaddress_other_attributes_ldap.h"
48 #include "prefs_common.h"
49 #include "menu.h"
50
51 /* transient data */
52 static struct _PersonEdit_dlg personeditdlg;
53 static AddressBookFile *current_abf = NULL;
54 static ItemPerson *current_person = NULL;
55 static ItemFolder *current_parent_folder = NULL;
56 static EditAddressPostUpdateCallback edit_person_close_post_update_cb = NULL;
57
58 typedef enum {
59         EMAIL_COL_EMAIL   = 0,
60         EMAIL_COL_ALIAS   = 1,
61         EMAIL_COL_REMARKS = 2
62 } PersonEditEMailColumnPos;
63
64 typedef enum {
65         ATTRIB_COL_NAME    = 0,
66         ATTRIB_COL_VALUE   = 1
67 } PersonEditAttribColumnPos;
68
69 #define EDITPERSON_WIDTH      520
70 #define EDITPERSON_HEIGHT     320
71
72 #ifndef MAEMO
73 # define EMAIL_N_COLS          3
74 # define EMAIL_COL_WIDTH_EMAIL 180
75 # define EMAIL_COL_WIDTH_ALIAS 80
76 #else
77 # define EMAIL_N_COLS          1
78 # define EMAIL_COL_WIDTH_EMAIL 130
79 # define EMAIL_COL_WIDTH_ALIAS 130
80 #endif
81
82 #ifndef MAEMO
83 # define ATTRIB_N_COLS          2
84 # define ATTRIB_COL_WIDTH_NAME  240
85 # define ATTRIB_COL_WIDTH_VALUE 0
86 #else
87 # define ATTRIB_N_COLS          2
88 # define ATTRIB_COL_WIDTH_NAME  120
89 # define ATTRIB_COL_WIDTH_VALUE 120
90 #endif
91
92 #define PAGE_BASIC             0
93 #define PAGE_EMAIL             1
94 #define PAGE_ATTRIBUTES        2
95
96 static gboolean addressbook_edit_person_close( gboolean cancelled );
97 static GList *edit_person_build_email_list();
98 static GList *edit_person_build_attrib_list();
99
100 static gchar* edit_person_get_common_name_from_widgets(void)
101 {
102         gchar *cn = NULL; /* cn must be freed by caller */
103
104 #ifndef MAEMO
105         {
106                 cn = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_name), 0, -1 );
107                 if ( cn == NULL || *cn == '\0' ) {
108                         gchar *first = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_first), 0, -1 );
109                         gchar *last = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_last), 0, -1 );
110                         cn = g_strdup_printf("%s%s%s", first?first:"", (first && last && *first && *last)?" ":"", last?last:"");
111                         g_free(first);
112                         g_free(last);
113                 }
114                 if ( cn == NULL || *cn == '\0' ) {
115                         g_free(cn);
116                         cn = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_nick), 0, -1 );;
117                 }
118         }
119 #else
120         {
121                 gchar *first = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_first), 0, -1 );
122                 gchar *last = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_last), 0, -1 );
123                 cn = g_strdup_printf("%s%s%s", first?first:"", (first && last && *first && *last)?" ":"", last?last:"");
124                 g_free(first);
125                 g_free(last);
126         }
127 #endif
128         if ( cn != NULL )
129                 g_strstrip(cn);
130         return cn;
131 }
132
133 static void edit_person_status_show( gchar *msg ) {
134         if( personeditdlg.statusbar != NULL ) {
135                 gtk_statusbar_pop( GTK_STATUSBAR(personeditdlg.statusbar), personeditdlg.status_cid );
136                 if( msg ) {
137                         gtk_statusbar_push( GTK_STATUSBAR(personeditdlg.statusbar), personeditdlg.status_cid, msg );
138                 }
139         }
140 }
141
142 static void edit_person_cancel(GtkWidget *widget, gboolean *cancelled) {
143         *cancelled = TRUE;
144         if (prefs_common.addressbook_use_editaddress_dialog)
145                 gtk_main_quit();
146         else
147                 addressbook_edit_person_close( *cancelled );
148 }
149
150 static void edit_person_ok(GtkWidget *widget, gboolean *cancelled) {
151         GList *listEMail = edit_person_build_email_list();
152         GList *listAttrib = edit_person_build_attrib_list();
153         gchar *cn = edit_person_get_common_name_from_widgets();
154
155         if( (cn == NULL || *cn == '\0') && listEMail == NULL && listAttrib == NULL ) {
156                 gint val;
157
158                 val = alertpanel( _("Add New Person"),
159                                 _("Adding a new person requires at least one of the\n"
160                                   "information above to be set:\n"
161 #ifndef MAEMO
162                                   " - Display Name\n"
163 #endif
164                                   " - First Name\n"
165                                   " - Last Name\n"
166 #ifndef MAEMO
167                                   " - Nickname\n"
168 #endif
169                                   " - any email address\n"
170                                   " - any additional attribute\n\n"
171                                   "Click OK to keep editing this contact.\n"
172                                   "Click Cancel to close without saving."),
173                                 GTK_STOCK_CANCEL, "+"GTK_STOCK_OK, NULL );
174                 if( val == G_ALERTALTERNATE ) {
175                         edit_person_cancel(widget, cancelled);
176                 }
177                 g_free( cn );
178                 return;
179         }
180         g_free( cn );
181
182         *cancelled = FALSE;
183         if (prefs_common.addressbook_use_editaddress_dialog)
184                 gtk_main_quit();
185         else
186                 addressbook_edit_person_close( *cancelled );
187 }
188
189 static gint edit_person_delete_event(GtkWidget *widget, GdkEventAny *event, gboolean *cancelled) {
190         *cancelled = TRUE;
191         if (prefs_common.addressbook_use_editaddress_dialog)
192                 gtk_main_quit();
193         else
194                 addressbook_edit_person_close( *cancelled );
195         return TRUE;
196 }
197
198 static gboolean edit_person_key_pressed(GtkWidget *widget, GdkEventKey *event, gboolean *cancelled) {
199         if (prefs_common.addressbook_use_editaddress_dialog) {
200         if (event && event->keyval == GDK_Escape) {
201                 *cancelled = TRUE;
202                 gtk_main_quit();
203         }
204         }
205         return FALSE;
206 }
207
208 static gchar *_title_new_ = NULL;
209 static gchar *_title_edit_ = NULL;
210
211 static void edit_person_set_widgets_title( gchar *text )
212 {
213         gchar *label = NULL;
214
215         g_return_if_fail( text != NULL );
216
217         gtk_label_set_text(GTK_LABEL(personeditdlg.title), "");
218         label = g_markup_printf_escaped("<b>%s</b>", text);
219         gtk_label_set_markup(GTK_LABEL(personeditdlg.title), label);
220         g_free(label);
221 }
222
223 static void edit_person_set_window_title( gint pageNum ) {
224         gchar *sTitle;
225
226         if( _title_new_ == NULL ) {
227                 _title_new_ = g_strdup( _("Add New Person") );
228                 _title_edit_ = g_strdup( _("Edit Person Details") );
229         }
230
231         if( pageNum == PAGE_BASIC ) {
232                 if( personeditdlg.editNew ) {
233                         if (prefs_common.addressbook_use_editaddress_dialog)
234                                 gtk_window_set_title( GTK_WINDOW(personeditdlg.container), _title_new_ );
235                         else
236                                 edit_person_set_widgets_title( _title_new_ );
237                 }
238                 else {
239                         if (prefs_common.addressbook_use_editaddress_dialog)
240                                 gtk_window_set_title( GTK_WINDOW(personeditdlg.container), _title_edit_ );
241                         else
242                                 edit_person_set_widgets_title( _title_edit_ );
243                 }
244         }
245         else {
246                 if( personeditdlg.entry_name == NULL ) {
247                         sTitle = g_strdup( _title_edit_ );
248                 }
249                 else {
250                         gchar *name;
251                         name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_name), 0, -1 );
252                         g_strstrip(name);
253                         if ( *name != '\0' )
254                                 sTitle = g_strdup_printf( "%s - %s", _title_edit_, name );
255                         else
256                                 sTitle = g_strdup( _title_edit_ );
257                         g_free( name );
258                 }
259                 if (prefs_common.addressbook_use_editaddress_dialog)
260                         gtk_window_set_title( GTK_WINDOW(personeditdlg.container), sTitle );
261                 else
262                         edit_person_set_widgets_title( sTitle );
263                 g_free( sTitle );
264         }
265 }
266
267 static void edit_person_email_clear( gpointer data ) {
268         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_email), "" );
269         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_alias), "" );
270         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_remarks), "" );
271 }
272
273 static void edit_person_attrib_clear( gpointer data ) {
274         if (!personeditdlg.ldap) {
275                 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atname), "" );
276                 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atvalue), "" );
277         }
278 }
279
280 static void edit_person_switch_page( GtkNotebook *notebook, GtkNotebookPage *page,
281                                         gint pageNum, gpointer user_data)
282 {
283         edit_person_set_window_title( pageNum );
284         edit_person_status_show( "" );
285 }
286
287 /*
288 * Load clist with a copy of person's email addresses.
289 */
290 static void edit_person_load_email( ItemPerson *person ) {
291         GList *node = person->listEMail;
292         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
293         gchar *text[ EMAIL_N_COLS ];
294         while( node ) {
295                 ItemEMail *emorig = ( ItemEMail * ) node->data;
296                 ItemEMail *email = addritem_copyfull_item_email( emorig );
297                 gint row;
298                 text[ EMAIL_COL_EMAIL   ] = email->address;
299 #ifndef MAEMO
300                 text[ EMAIL_COL_ALIAS   ] = email->obj.name;
301                 text[ EMAIL_COL_REMARKS ] = email->remarks;
302 #endif
303                 row = gtk_clist_append( clist, text );
304                 gtk_clist_set_row_data( clist, row, email );
305                 node = g_list_next( node );
306         }
307 }
308
309 static void edit_person_email_list_selected( GtkCList *clist, gint row, gint column, GdkEvent *event, gpointer data ) {
310         ItemEMail *email = gtk_clist_get_row_data( clist, row );
311         if( email ) {
312                 if( email->address )
313                         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_email), email->address );
314                 if( ADDRITEM_NAME(email) )
315                         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_alias), ADDRITEM_NAME(email) );
316                 if( email->remarks )
317                         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_remarks), email->remarks );
318                 if (!personeditdlg.read_only) {
319                         gtk_widget_set_sensitive(personeditdlg.email_del, TRUE);
320                         gtk_widget_set_sensitive(personeditdlg.email_up, row > 0);
321                         gtk_widget_set_sensitive(personeditdlg.email_down, gtk_clist_get_row_data(clist, row + 1) != NULL);
322                 }
323         } else {
324                 gtk_widget_set_sensitive(personeditdlg.email_del, FALSE);
325                 gtk_widget_set_sensitive(personeditdlg.email_up, FALSE);
326                 gtk_widget_set_sensitive(personeditdlg.email_down, FALSE);
327         }
328         personeditdlg.rowIndEMail = row;
329         edit_person_status_show( NULL );
330 }
331
332 static void edit_person_email_move( gint dir ) {
333         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
334         gint row = personeditdlg.rowIndEMail + dir;
335         ItemEMail *email = gtk_clist_get_row_data( clist, row );
336         if( email ) {
337                 gtk_clist_row_move( clist, personeditdlg.rowIndEMail, row );
338                 personeditdlg.rowIndEMail = row;
339                 if (!personeditdlg.read_only) {
340                         gtk_widget_set_sensitive(personeditdlg.email_up, row > 0);
341                         gtk_widget_set_sensitive(personeditdlg.email_down, gtk_clist_get_row_data(clist, row + 1) != NULL);
342                 }
343         } else {
344                 gtk_widget_set_sensitive(personeditdlg.email_up, FALSE);
345                 gtk_widget_set_sensitive(personeditdlg.email_down, FALSE);
346         }
347         edit_person_email_clear( NULL );
348         edit_person_status_show( NULL );
349 }
350
351 static void edit_person_email_move_up( gpointer data ) {
352         edit_person_email_move( -1 );
353 }
354
355 static void edit_person_email_move_down( gpointer data ) {
356         edit_person_email_move( +1 );
357 }
358
359 static void edit_person_email_delete( gpointer data ) {
360         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
361         gint row = personeditdlg.rowIndEMail;
362         ItemEMail *email = gtk_clist_get_row_data( clist, row );
363         edit_person_email_clear( NULL );
364         if( email ) {
365                 /* Remove list entry */
366                 gtk_clist_remove( clist, row );
367                 addritem_free_item_email( email );
368                 email = NULL;
369         }
370
371         /* Position hilite bar */
372         email = gtk_clist_get_row_data( clist, row );
373         if( ! email ) {
374                 personeditdlg.rowIndEMail = -1 + row;
375         }
376         if (!personeditdlg.read_only) {
377                 gtk_widget_set_sensitive(personeditdlg.email_del, gtk_clist_get_row_data(clist, 0) != NULL);
378                 gtk_widget_set_sensitive(personeditdlg.email_up, gtk_clist_get_row_data(clist, personeditdlg.rowIndEMail + 1) != NULL);
379                 gtk_widget_set_sensitive(personeditdlg.email_down, gtk_clist_get_row_data(clist, personeditdlg.rowIndEMail - 1) != NULL);
380         }
381         edit_person_status_show( NULL );
382 }
383
384 static ItemEMail *edit_person_email_edit( gboolean *error, ItemEMail *email ) {
385         ItemEMail *retVal = NULL;
386         gchar *sEmail, *sAlias, *sRemarks, *sEmail_;
387
388         *error = TRUE;
389         sEmail_ = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_email), 0, -1 );
390         sAlias = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_alias), 0, -1 );
391         sRemarks = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_remarks), 0, -1 );
392         sEmail = mgu_email_check_empty( sEmail_ );
393         g_free( sEmail_ );
394
395         if( sEmail ) {
396                 if( email == NULL ) {
397                         email = addritem_create_item_email();
398                 }
399                 addritem_email_set_address( email, sEmail );
400                 addritem_email_set_alias( email, sAlias );
401                 addritem_email_set_remarks( email, sRemarks );
402                 retVal = email;
403                 *error = FALSE;
404         }
405         else {
406                 edit_person_status_show( _( "An Email address must be supplied." ) );
407         }
408
409         g_free( sEmail );
410         g_free( sAlias );
411         g_free( sRemarks );
412
413         return retVal;
414 }
415
416 static void edit_person_email_modify( gpointer data ) {
417         gboolean errFlg = FALSE;
418         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
419         gint row = personeditdlg.rowIndEMail;
420         ItemEMail *email = gtk_clist_get_row_data( clist, row );
421         if( email ) {
422                 edit_person_email_edit( &errFlg, email );
423                 if( ! errFlg ) {
424                         gtk_clist_set_text( clist, row, EMAIL_COL_EMAIL, email->address );
425                         gtk_clist_set_text( clist, row, EMAIL_COL_ALIAS, email->obj.name );
426                         gtk_clist_set_text( clist, row, EMAIL_COL_REMARKS, email->remarks );
427                         edit_person_email_clear( NULL );
428                 }
429         }
430 }
431
432 static void edit_person_email_add( gpointer data ) {
433         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
434         gboolean errFlg = FALSE;
435         ItemEMail *email = NULL;
436         gint row = personeditdlg.rowIndEMail;
437         if( gtk_clist_get_row_data( clist, row ) == NULL ) row = 0;
438
439         email = edit_person_email_edit( &errFlg, NULL );
440         if( ! errFlg ) {
441                 gchar *text[ EMAIL_N_COLS ];
442                 text[ EMAIL_COL_EMAIL   ] = email->address;
443 #ifndef MAEMO
444                 text[ EMAIL_COL_ALIAS   ] = email->obj.name;
445                 text[ EMAIL_COL_REMARKS ] = email->remarks;
446 #endif
447                 row = gtk_clist_insert( clist, 1 + row, text );
448                 gtk_clist_set_row_data( clist, row, email );
449                 gtk_clist_select_row( clist, row, 0 );
450                 edit_person_email_clear( NULL );
451         }
452 }
453
454 /*
455 * Comparison using cell contents (text in first column). Used for sort
456 * address index widget.
457 */
458 static gint edit_person_attrib_compare_func(
459         GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2 )
460 {
461         GtkCell *cell1 = ((GtkCListRow *)ptr1)->cell;
462         GtkCell *cell2 = ((GtkCListRow *)ptr2)->cell;
463         gchar *name1 = NULL, *name2 = NULL;
464
465         if( cell1 ) name1 = cell1->u.text;
466         if( cell2 ) name2 = cell2->u.text;
467         if( ! name1 ) return ( name2 != NULL );
468         if( ! name2 ) return -1;
469         return g_utf8_collate( name1, name2 );
470 }
471
472 static gboolean list_find_attribute(const gchar *attr)
473 {
474         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
475         UserAttribute *attrib;
476         gint row = 0;
477         while( (attrib = gtk_clist_get_row_data( clist, row )) ) {
478                 if (!g_ascii_strcasecmp(attrib->name, attr)) {
479                         gtk_clist_select_row(clist, row, 0);
480                         return TRUE;
481                 }
482                 row++;
483         }
484         return FALSE;
485 }
486
487 static gboolean list_find_email(const gchar *addr)
488 {
489         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
490         ItemEMail *email;
491         gint row = 0;
492         while( (email = gtk_clist_get_row_data( clist, row )) ) {
493                 if (!g_ascii_strcasecmp(email->address, addr)) {
494                         gtk_clist_select_row(clist, row, 0);
495                         return TRUE;
496                 }
497                 row++;
498         }
499         return FALSE;
500 }
501
502 /*
503 * Load clist with a copy of person's email addresses.
504 */
505 static void edit_person_load_attrib( ItemPerson *person ) {
506         GList *node = person->listAttrib;
507         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
508         gchar *text[ ATTRIB_N_COLS ];
509         while( node ) {
510                 UserAttribute *atorig = ( UserAttribute * ) node->data;
511                 UserAttribute *attrib = addritem_copy_attribute( atorig );
512                 gint row;
513                 debug_print("name: %s value: %s\n", attrib->name, attrib->value);
514                 text[ ATTRIB_COL_NAME  ] = attrib->name;
515                 text[ ATTRIB_COL_VALUE ] = attrib->value;
516
517                 row = gtk_clist_append( clist, text );
518                 gtk_clist_set_row_data( clist, row, attrib );
519                 node = g_list_next( node );
520         }
521 }
522
523 static void edit_person_attrib_list_selected( GtkCList *clist, gint row, gint column, GdkEvent *event, gpointer data ) {
524         UserAttribute *attrib = gtk_clist_get_row_data( clist, row );
525         if( attrib && !personeditdlg.read_only && !personeditdlg.ldap ) {
526                 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atname), attrib->name );
527                 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atvalue), attrib->value );
528                 gtk_widget_set_sensitive(personeditdlg.attrib_del, TRUE);
529         } else {
530                 gtk_widget_set_sensitive(personeditdlg.attrib_del, FALSE);
531         }
532         personeditdlg.rowIndAttrib = row;
533         edit_person_status_show( NULL );
534 }
535
536 static void edit_person_attrib_delete( gpointer data ) {
537         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
538         gint row = personeditdlg.rowIndAttrib;
539         UserAttribute *attrib = gtk_clist_get_row_data( clist, row );
540         edit_person_attrib_clear( NULL );
541         if( attrib ) {
542                 /* Remove list entry */
543                 gtk_clist_remove( clist, row );
544                 addritem_free_attribute( attrib );
545                 attrib = NULL;
546         }
547
548         /* Position hilite bar */
549         attrib = gtk_clist_get_row_data( clist, row );
550         if( ! attrib ) {
551                 personeditdlg.rowIndAttrib = -1 + row;
552         } 
553         
554         if (!personeditdlg.read_only && !personeditdlg.ldap)
555                 gtk_widget_set_sensitive(personeditdlg.attrib_del, gtk_clist_get_row_data(clist, 0) != NULL);
556         
557         edit_person_status_show( NULL );
558 }
559
560 static UserAttribute *edit_person_attrib_edit( gboolean *error, UserAttribute *attrib ) {
561         UserAttribute *retVal = NULL;
562         gchar *sName, *sValue, *sName_, *sValue_;
563
564         *error = TRUE;
565         sName_ = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_atname), 0, -1 );
566         sValue_ = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_atvalue), 0, -1 );
567         sName = mgu_email_check_empty( sName_ );
568         sValue = mgu_email_check_empty( sValue_ );
569         g_free( sName_ );
570         g_free( sValue_ );
571
572         if( sName && sValue ) {
573                 if( attrib == NULL ) {
574                         attrib = addritem_create_attribute();
575                 }
576                 addritem_attrib_set_name( attrib, sName );
577                 addritem_attrib_set_value( attrib, sValue );
578                 retVal = attrib;
579                 *error = FALSE;
580         }
581         else {
582                 edit_person_status_show( _( "A Name and Value must be supplied." ) );
583         }
584
585         g_free( sName );
586         g_free( sValue );
587
588         return retVal;
589 }
590
591 static void edit_person_attrib_modify( gpointer data ) {
592         gboolean errFlg = FALSE;
593         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
594         gint row = personeditdlg.rowIndAttrib;
595         UserAttribute *attrib = gtk_clist_get_row_data( clist, row );
596         if( attrib ) {
597                 edit_person_attrib_edit( &errFlg, attrib );
598                 if( ! errFlg ) {
599                         gtk_clist_set_text( clist, row, ATTRIB_COL_NAME, attrib->name );
600                         gtk_clist_set_text( clist, row, ATTRIB_COL_VALUE, attrib->value );
601                         edit_person_attrib_clear( NULL );
602                 }
603         }
604 }
605
606 static void edit_person_attrib_add( gpointer data ) {
607         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
608         gboolean errFlg = FALSE;
609         UserAttribute *attrib = NULL;
610         gint row = personeditdlg.rowIndAttrib;
611         if( gtk_clist_get_row_data( clist, row ) == NULL ) row = 0;
612
613         attrib = edit_person_attrib_edit( &errFlg, NULL );
614         if( ! errFlg ) {
615                 gchar *text[ ATTRIB_N_COLS ];
616                 text[ ATTRIB_COL_NAME  ] = attrib->name;
617                 text[ ATTRIB_COL_VALUE ] = attrib->value;
618
619                 row = gtk_clist_insert( clist, 1 + row, text );
620                 gtk_clist_set_row_data( clist, row, attrib );
621                 gtk_clist_select_row( clist, row, 0 );
622                 edit_person_attrib_clear( NULL );
623         }
624 }
625
626 /*!
627  *\brief        Save Gtk object size to prefs dataset
628  */
629 static void edit_person_size_allocate_cb(GtkWidget *widget,
630                                          GtkAllocation *allocation)
631 {
632         g_return_if_fail(allocation != NULL);
633
634         prefs_common.addressbookeditpersonwin_width = allocation->width;
635         prefs_common.addressbookeditpersonwin_height = allocation->height;
636 }
637
638 /* build edit person widgets, return a pointer to the main container of the widgetset (a vbox) */
639 static GtkWidget* addressbook_edit_person_widgets_create( GtkWidget* container, gboolean *cancelled )
640 {
641         GtkWidget *vbox;
642         GtkWidget *vnbox;
643         GtkWidget *notebook;
644         GtkWidget *hbbox;
645         GtkWidget *ok_btn;
646         GtkWidget *cancel_btn;
647
648         vbox = gtk_vbox_new(FALSE, 4);
649          gtk_container_set_border_width(GTK_CONTAINER(vbox), BORDER_WIDTH); 
650         gtk_widget_show(vbox);
651         gtk_container_add(GTK_CONTAINER(container), vbox);
652
653         vnbox = gtk_vbox_new(FALSE, 4);
654         gtk_container_set_border_width(GTK_CONTAINER(vnbox), 4);
655         gtk_widget_show(vnbox);
656         gtk_box_pack_start(GTK_BOX(vbox), vnbox, TRUE, TRUE, 0);
657
658         /* Notebook */
659         notebook = gtk_notebook_new();
660         gtk_widget_show(notebook);
661         gtk_box_pack_start(GTK_BOX(vnbox), notebook, TRUE, TRUE, 0);
662         gtk_container_set_border_width(GTK_CONTAINER(notebook), 6);
663
664         /* Button panel */
665         if (prefs_common.addressbook_use_editaddress_dialog)
666         gtkut_stock_button_set_create(&hbbox, &cancel_btn, GTK_STOCK_CANCEL,
667                                       &ok_btn, GTK_STOCK_OK,
668                                       NULL, NULL);
669         else
670                 gtkut_stock_with_text_button_set_create(&hbbox,
671                                           &cancel_btn, GTK_STOCK_CANCEL, _("Discard"),
672                                       &ok_btn, GTK_STOCK_OK, _("Apply"),
673                                       NULL, NULL, NULL);
674         gtk_box_pack_end(GTK_BOX(vnbox), hbbox, FALSE, FALSE, 0);
675         gtk_widget_grab_default(ok_btn);
676
677         g_signal_connect(G_OBJECT(ok_btn), "clicked",
678                          G_CALLBACK(edit_person_ok), cancelled);
679         g_signal_connect(G_OBJECT(cancel_btn), "clicked",
680                          G_CALLBACK(edit_person_cancel), cancelled);
681         g_signal_connect(G_OBJECT(notebook), "switch_page",
682                          G_CALLBACK(edit_person_switch_page), NULL );
683
684         gtk_widget_show_all(vbox);
685
686         personeditdlg.notebook   = notebook;
687         personeditdlg.ok_btn     = ok_btn;
688         personeditdlg.cancel_btn = cancel_btn;
689
690         return vbox;
691 }
692
693 static void addressbook_edit_person_dialog_create( gboolean *cancelled ) {
694         GtkWidget *window;
695         GtkWidget *hsbox;
696         GtkWidget *vbox;
697         GtkWidget *statusbar;
698         static GdkGeometry geometry;
699
700         window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "editaddress");
701         /* gtk_container_set_border_width(GTK_CONTAINER(window), 0); */
702         gtk_window_set_title(GTK_WINDOW(window), _("Edit Person Data"));
703         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
704         gtk_window_set_modal(GTK_WINDOW(window), TRUE); 
705         g_signal_connect(G_OBJECT(window), "delete_event",
706                          G_CALLBACK(edit_person_delete_event),
707                          cancelled);
708         g_signal_connect(G_OBJECT(window), "size_allocate",
709                          G_CALLBACK(edit_person_size_allocate_cb),
710                         cancelled);
711         g_signal_connect(G_OBJECT(window), "key_press_event",
712                          G_CALLBACK(edit_person_key_pressed),
713                          cancelled);
714
715         vbox = addressbook_edit_person_widgets_create(window, cancelled);
716
717         /* Status line */
718         hsbox = gtk_hbox_new(FALSE, 0);
719         gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, BORDER_WIDTH);
720         statusbar = gtk_statusbar_new();
721         gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, BORDER_WIDTH);
722
723         if (!geometry.min_height) {
724                 geometry.min_width = EDITPERSON_WIDTH;
725                 geometry.min_height = EDITPERSON_HEIGHT;
726         }
727
728         gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
729                                       GDK_HINT_MIN_SIZE);
730         gtk_widget_set_size_request(window, prefs_common.addressbookeditpersonwin_width,
731                                     prefs_common.addressbookeditpersonwin_height);
732
733         personeditdlg.container  = window;
734         personeditdlg.statusbar  = statusbar;
735         personeditdlg.status_cid = gtk_statusbar_get_context_id( GTK_STATUSBAR(statusbar), "Edit Person Dialog" );
736
737 }
738
739 /* parent must be a box */
740 static void addressbook_edit_person_widgetset_create( GtkWidget *parent, gboolean *cancelled )
741 {
742         GtkWidget *vbox;
743         GtkWidget *label;
744
745         if ( parent == NULL )
746                 g_warning("addressbook_edit_person_widgetset_create: parent is NULL");
747
748         vbox = gtk_vbox_new(FALSE, 0);
749         gtk_box_pack_end(GTK_BOX(parent), vbox, TRUE, TRUE, 0);
750
751         label = gtk_label_new(_("Edit Person Data"));
752         gtk_label_set_justify( GTK_LABEL(label), GTK_JUSTIFY_CENTER);
753         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
754
755         addressbook_edit_person_widgets_create(vbox, cancelled);
756
757         gtk_widget_set_size_request(vbox, EDITPERSON_WIDTH, EDITPERSON_HEIGHT);
758
759         personeditdlg.container = vbox;
760         personeditdlg.title = label;
761         personeditdlg.statusbar  = NULL;
762         personeditdlg.status_cid = 0;
763 }
764
765 void addressbook_edit_person_widgetset_hide( void )
766 {
767         if ( personeditdlg.container )
768                 gtk_widget_hide( personeditdlg.container );
769 }
770
771 static void addressbook_edit_person_set_picture(void)
772 {
773         GError *error = NULL;
774         gchar *filename;
775         int width, height, scalewidth, scaleheight;
776
777         if (personeditdlg.ldap)
778                 return;
779
780         if ( (filename = filesel_select_file_open(_("Choose a picture"), NULL)) ) {
781                 GdkPixbuf *pixbuf = NULL;
782                 gdk_pixbuf_get_file_info(filename, &width, &height);
783
784                 if ( width > 128 || height > 128 ) {
785                         if (width > height) {
786                                 scaleheight = (height * 128) / width;
787                                 scalewidth = 128;
788                         }
789                         else {
790                                 scalewidth = (width * 128) / height;
791                                 scaleheight = 128;
792                         }
793                         pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, 
794                                         scalewidth, scaleheight, TRUE, &error);
795                 } else {
796                         pixbuf = gdk_pixbuf_new_from_file(filename, &error);
797                 }
798                 if (error) {
799                         alertpanel_error(_("Failed to import image: \n%s"),
800                                         error->message);
801                         g_error_free(error);
802                         error = NULL;
803                         /* keep the previous picture if any */
804                         g_free(filename);
805                         if (pixbuf)
806                                 g_object_unref(pixbuf);
807                         return;
808                 }
809                 personeditdlg.picture_set = TRUE;
810                 menu_set_sensitive(personeditdlg.editaddr_popupfactory,
811                                 "/Unset picture", personeditdlg.picture_set);
812                 g_free(filename);
813                 gtk_image_set_from_pixbuf(GTK_IMAGE(personeditdlg.image), pixbuf);
814                 g_object_unref(pixbuf);
815         }
816 }       
817
818 static void addressbook_edit_person_clear_picture(void)
819 {
820         GdkPixbuf *pixbuf;
821
822         stock_pixbuf_gdk(NULL, STOCK_PIXMAP_ANONYMOUS, &pixbuf);
823         personeditdlg.picture_set = FALSE;
824         menu_set_sensitive(personeditdlg.editaddr_popupfactory,
825                         "/Unset picture", personeditdlg.picture_set);
826         gtk_image_set_from_pixbuf(GTK_IMAGE(personeditdlg.image), pixbuf);
827 }
828
829 static void addressbook_edit_person_set_picture_menu_cb (void *obj, guint action, void *data)
830 {
831         addressbook_edit_person_set_picture();
832 }
833
834 static void addressbook_edit_person_unset_picture_menu_cb (void *obj, guint action, void *data)
835 {
836         addressbook_edit_person_clear_picture();
837 }
838
839 static GtkItemFactoryEntry editaddr_popup_entries[] =
840 {
841         {N_("/_Set picture"),           NULL, addressbook_edit_person_set_picture_menu_cb, 0, NULL, NULL},
842         {N_("/_Unset picture"),         NULL, addressbook_edit_person_unset_picture_menu_cb, 0, NULL, NULL},
843 };
844
845 static void addressbook_edit_person_set_picture_cb(GtkWidget *widget, 
846                 GdkEventButton *event, gpointer data)
847 {       
848         if (event->button == 1) {
849                 addressbook_edit_person_set_picture();
850         } else {
851                 gtk_menu_popup(GTK_MENU(personeditdlg.editaddr_popupmenu), 
852                                NULL, NULL, NULL, NULL, 
853                                event->button, event->time);
854         }
855 }
856
857 static gboolean addressbook_edit_person_picture_popup_menu(GtkWidget *widget, gpointer data)
858 {
859         GdkEventButton event;
860         
861         event.button = 3;
862         event.time = gtk_get_current_event_time();
863         
864         addressbook_edit_person_set_picture_cb(NULL, &event, data);
865
866         return TRUE;
867 }
868
869 static void addressbook_edit_person_page_basic( gint pageNum, gchar *pageLbl ) {
870         GtkWidget *vbox;
871         GtkWidget *hbox;
872         GtkWidget *table;
873         GtkWidget *label;
874         GtkWidget *ebox_picture;
875         GtkWidget *frame_picture;
876         GtkWidget *entry_name;
877         GtkWidget *entry_fn;
878         GtkWidget *entry_ln;
879         GtkWidget *entry_nn;
880         const gchar *locale;
881         gint top = 0;
882         gint n_entries;
883         vbox = gtk_vbox_new( FALSE, 20 );
884         hbox = gtk_hbox_new( FALSE, 8 );
885
886         gtk_widget_show( vbox );        
887
888         /* set up picture context menu before we call addressbook_edit_person_clear_picture() */        
889         n_entries = sizeof(editaddr_popup_entries) /
890                 sizeof(editaddr_popup_entries[0]);
891         personeditdlg.editaddr_popupmenu = menu_create_items(editaddr_popup_entries, n_entries,
892                                       "<EditAddrPopupMenu>", &personeditdlg.editaddr_popupfactory,
893                                       NULL);
894
895         /* User's picture */
896         ebox_picture = gtk_event_box_new();
897         frame_picture = gtk_frame_new(_("Photo"));
898         
899         /* Room for a photo */
900         personeditdlg.image = gtk_image_new();
901         addressbook_edit_person_clear_picture();
902
903         gtk_container_add(GTK_CONTAINER(ebox_picture), personeditdlg.image);
904         gtk_container_add(GTK_CONTAINER(frame_picture), ebox_picture);  
905         gtk_container_add(GTK_CONTAINER( personeditdlg.notebook ), hbox );
906         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
907         gtk_container_set_border_width( GTK_CONTAINER (hbox), BORDER_WIDTH );
908
909         label = gtk_label_new_with_mnemonic( pageLbl );
910         gtk_widget_show( label );
911         
912         gtk_box_pack_start(GTK_BOX(hbox), frame_picture, TRUE, TRUE, 0);
913         
914         gtk_notebook_set_tab_label(
915                 GTK_NOTEBOOK( personeditdlg.notebook ),
916                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
917         
918 #ifndef MAEMO
919         g_signal_connect(G_OBJECT(ebox_picture), "popup-menu",
920                          G_CALLBACK(addressbook_edit_person_picture_popup_menu), NULL);
921 #else
922         gtk_widget_tap_and_hold_setup(GTK_WIDGET(ebox_picture), NULL, NULL,
923                         GTK_TAP_AND_HOLD_NONE | GTK_TAP_AND_HOLD_NO_INTERNALS);
924         g_signal_connect(G_OBJECT(ebox_picture), "tap-and-hold",
925                          G_CALLBACK(addressbook_edit_person_picture_popup_menu), NULL);
926 #endif
927         g_signal_connect(G_OBJECT(ebox_picture), "button_press_event", 
928                         G_CALLBACK(addressbook_edit_person_set_picture_cb), NULL);
929
930         table = gtk_table_new( 3, 3, FALSE);
931
932 #define ATTACH_ROW(text, entry) \
933 { \
934         label = gtk_label_new(text); \
935         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), \
936                          GTK_FILL, 0, 0, 0); \
937         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); \
938  \
939         entry = gtk_entry_new(); \
940         gtk_table_attach(GTK_TABLE(table), entry, 1, 2, top, (top + 1), \
941                          GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0); \
942         top++; \
943 }
944
945 #define ATTACH_HIDDEN_ROW(text, entry) \
946 { \
947         entry = gtk_entry_new(); \
948 }
949
950 #ifndef MAEMO
951         ATTACH_ROW(_("Display Name"), entry_name);
952 #else
953         ATTACH_HIDDEN_ROW(_("Display Name"), entry_name);
954 #endif
955         locale = conv_get_current_locale();
956         if (locale &&
957             (!g_ascii_strncasecmp(locale, "ja", 2) ||
958              !g_ascii_strncasecmp(locale, "ko", 2) ||
959              !g_ascii_strncasecmp(locale, "zh", 2))) {
960                 ATTACH_ROW(_("Last Name"), entry_ln);
961                 ATTACH_ROW(_("First Name"), entry_fn);
962         } else {
963                 ATTACH_ROW(_("First Name"), entry_fn);
964                 ATTACH_ROW(_("Last Name"), entry_ln);
965         }
966 #ifndef MAEMO
967         ATTACH_ROW(_("Nickname"), entry_nn);
968 #else
969         ATTACH_HIDDEN_ROW(_("Nickname"), entry_nn);
970 #endif
971
972 #undef ATTACH_ROW
973 #undef ATTACH_HIDDEN_ROW
974         gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
975         gtk_box_pack_end(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
976         gtk_container_set_border_width( GTK_CONTAINER(table), 8 );
977         gtk_table_set_row_spacings(GTK_TABLE(table), 15);
978         gtk_table_set_col_spacings(GTK_TABLE(table), 8);
979
980         gtk_widget_show_all(vbox);
981         personeditdlg.entry_name  = entry_name;
982         personeditdlg.entry_first = entry_fn;
983         personeditdlg.entry_last  = entry_ln;
984         personeditdlg.entry_nick  = entry_nn;
985 }
986
987 static gboolean email_adding = FALSE, email_saving = FALSE;
988
989 static void edit_person_entry_email_changed (GtkWidget *entry, gpointer data)
990 {
991         gboolean non_empty = gtk_clist_get_row_data(GTK_CLIST(personeditdlg.clist_email), 0) != NULL;
992
993         if (personeditdlg.read_only)
994                 return;
995
996         if (gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email)) == NULL
997         ||  strlen(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email))) == 0) {
998                 gtk_widget_set_sensitive(personeditdlg.email_add,FALSE);
999                 gtk_widget_set_sensitive(personeditdlg.email_mod,FALSE);
1000                 email_adding = FALSE;
1001                 email_saving = FALSE;
1002         } else if (list_find_email(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email)))) {
1003                 gtk_widget_set_sensitive(personeditdlg.email_add,FALSE);
1004                 gtk_widget_set_sensitive(personeditdlg.email_mod,non_empty);
1005                 email_adding = FALSE;
1006                 email_saving = non_empty;
1007         } else {
1008                 gtk_widget_set_sensitive(personeditdlg.email_add,TRUE);
1009                 gtk_widget_set_sensitive(personeditdlg.email_mod,non_empty);
1010                 email_adding = TRUE;
1011                 email_saving = non_empty;
1012         }
1013 }
1014
1015 static gboolean edit_person_entry_email_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
1016 {
1017         if (event && event->keyval == GDK_Return) {
1018                 if (email_saving)
1019                         edit_person_email_modify(NULL);         
1020                 else if (email_adding)
1021                         edit_person_email_add(NULL);
1022         }
1023         return FALSE;
1024 }
1025
1026
1027 static void addressbook_edit_person_page_email( gint pageNum, gchar *pageLbl ) {
1028         GtkWidget *vbox;
1029         GtkWidget *hbox;
1030         GtkWidget *vboxl;
1031         GtkWidget *vboxb;
1032         GtkWidget *vbuttonbox;
1033         GtkWidget *buttonUp;
1034         GtkWidget *buttonDown;
1035         GtkWidget *buttonDel;
1036         GtkWidget *buttonMod;
1037         GtkWidget *buttonAdd;
1038
1039         GtkWidget *table;
1040         GtkWidget *label;
1041         GtkWidget *clist_swin;
1042         GtkWidget *clist;
1043         GtkWidget *entry_email;
1044         GtkWidget *entry_alias;
1045         GtkWidget *entry_remarks;
1046         gint top;
1047
1048         gchar *titles[ EMAIL_N_COLS ];
1049         gint i;
1050
1051         titles[ EMAIL_COL_EMAIL   ] = _("Email Address");
1052 #ifndef MAEMO
1053         titles[ EMAIL_COL_ALIAS   ] = _("Alias");
1054         titles[ EMAIL_COL_REMARKS ] = _("Remarks");
1055 #endif
1056         vbox = gtk_vbox_new( FALSE, 8 );
1057         gtk_widget_show( vbox );
1058         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
1059         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
1060
1061         label = gtk_label_new_with_mnemonic( pageLbl );
1062         gtk_widget_show( label );
1063         gtk_notebook_set_tab_label(
1064                 GTK_NOTEBOOK( personeditdlg.notebook ),
1065                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
1066
1067         /* Split into two areas */
1068         hbox = gtk_hbox_new( FALSE, 0 );
1069         gtk_container_add( GTK_CONTAINER( vbox ), hbox );
1070
1071         /* Address list */
1072         vboxl = gtk_vbox_new( FALSE, 4 );
1073         gtk_container_add( GTK_CONTAINER( hbox ), vboxl );
1074         gtk_container_set_border_width( GTK_CONTAINER(vboxl), 4 );
1075
1076         clist_swin = gtk_scrolled_window_new( NULL, NULL );
1077         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
1078                                        GTK_POLICY_AUTOMATIC,
1079                                        GTK_POLICY_AUTOMATIC);
1080
1081         clist = gtk_clist_new_with_titles( EMAIL_N_COLS, titles );
1082
1083         gtk_container_add( GTK_CONTAINER(clist_swin), clist );
1084         gtk_clist_set_selection_mode( GTK_CLIST(clist), GTK_SELECTION_BROWSE );
1085         gtk_clist_set_column_width( GTK_CLIST(clist), EMAIL_COL_EMAIL, EMAIL_COL_WIDTH_EMAIL );
1086         gtk_clist_set_column_width( GTK_CLIST(clist), EMAIL_COL_ALIAS, EMAIL_COL_WIDTH_ALIAS );
1087
1088         for( i = 0; i < EMAIL_N_COLS; i++ )
1089                 GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button, GTK_CAN_FOCUS);
1090
1091         /* Data entry area */
1092         table = gtk_table_new( 4, 2, FALSE);
1093
1094 #ifndef MAEMO
1095         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
1096         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
1097 #else
1098         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
1099         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
1100         gtk_clist_column_titles_hide(GTK_CLIST(clist));
1101 #endif
1102         gtk_container_set_border_width( GTK_CONTAINER(table), 4 );
1103         gtk_table_set_row_spacings(GTK_TABLE(table), 4);
1104         gtk_table_set_col_spacings(GTK_TABLE(table), 4);
1105
1106         entry_email = gtk_entry_new();
1107         entry_alias = gtk_entry_new();
1108         entry_remarks = gtk_entry_new();
1109
1110         /* First row */
1111         top = 0;
1112         label = gtk_label_new(_("Email Address"));
1113         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
1114         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1115
1116         gtk_table_attach(GTK_TABLE(table), entry_email, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1117
1118 #ifndef MAEMO
1119         /* Next row */
1120         ++top;
1121         label = gtk_label_new(_("Alias"));
1122         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
1123         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1124
1125         gtk_table_attach(GTK_TABLE(table), entry_alias, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1126
1127         /* Next row */
1128         ++top;
1129         label = gtk_label_new(_("Remarks"));
1130         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
1131         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1132
1133         gtk_table_attach(GTK_TABLE(table), entry_remarks, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1134 #endif
1135
1136         /* Button box */
1137         vboxb = gtk_vbox_new( FALSE, 4 );
1138         gtk_box_pack_start(GTK_BOX(hbox), vboxb, FALSE, FALSE, 2);
1139
1140         vbuttonbox = gtk_vbutton_box_new();
1141         gtk_button_box_set_layout( GTK_BUTTON_BOX(vbuttonbox), GTK_BUTTONBOX_START );
1142         gtk_box_set_spacing( GTK_BOX(vbuttonbox), 8 );
1143         gtk_container_set_border_width( GTK_CONTAINER(vbuttonbox), 4 );
1144         gtk_container_add( GTK_CONTAINER(vboxb), vbuttonbox );
1145
1146         /* Buttons */
1147         buttonUp = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
1148         buttonDown = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
1149         buttonDel = gtk_button_new_from_stock(GTK_STOCK_DELETE);
1150         buttonMod = gtk_button_new_from_stock(GTK_STOCK_SAVE);
1151         buttonAdd = gtk_button_new_from_stock(GTK_STOCK_ADD);
1152         
1153
1154 #ifndef MAEMO
1155         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonUp );
1156
1157         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDown );
1158 #endif
1159         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDel );
1160
1161         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonMod );
1162
1163         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonAdd );
1164
1165         gtk_widget_show_all(vbox);
1166
1167         /* Event handlers */
1168         g_signal_connect( G_OBJECT(clist), "select_row",
1169                           G_CALLBACK( edit_person_email_list_selected), NULL );
1170         g_signal_connect( G_OBJECT(buttonUp), "clicked",
1171                           G_CALLBACK( edit_person_email_move_up ), NULL );
1172         g_signal_connect( G_OBJECT(buttonDown), "clicked",
1173                           G_CALLBACK( edit_person_email_move_down ), NULL );
1174         g_signal_connect( G_OBJECT(buttonDel), "clicked",
1175                           G_CALLBACK( edit_person_email_delete ), NULL );
1176         g_signal_connect( G_OBJECT(buttonMod), "clicked",
1177                           G_CALLBACK( edit_person_email_modify ), NULL );
1178         g_signal_connect( G_OBJECT(buttonAdd), "clicked",
1179                           G_CALLBACK( edit_person_email_add ), NULL );
1180         g_signal_connect(G_OBJECT(entry_email), "changed",
1181                          G_CALLBACK(edit_person_entry_email_changed), NULL);
1182         g_signal_connect(G_OBJECT(entry_email), "key_press_event",
1183                          G_CALLBACK(edit_person_entry_email_pressed), NULL);
1184         g_signal_connect(G_OBJECT(entry_alias), "key_press_event",
1185                          G_CALLBACK(edit_person_entry_email_pressed), NULL);
1186         g_signal_connect(G_OBJECT(entry_remarks), "key_press_event",
1187                          G_CALLBACK(edit_person_entry_email_pressed), NULL);
1188
1189         personeditdlg.clist_email   = clist;
1190         personeditdlg.entry_email   = entry_email;
1191         personeditdlg.entry_alias   = entry_alias;
1192         personeditdlg.entry_remarks = entry_remarks;
1193         personeditdlg.email_up = buttonUp;
1194         personeditdlg.email_down = buttonDown;
1195         personeditdlg.email_del = buttonDel;
1196         personeditdlg.email_mod = buttonMod;
1197         personeditdlg.email_add = buttonAdd;
1198 }
1199
1200 static gboolean attrib_adding = FALSE, attrib_saving = FALSE;
1201
1202 static void edit_person_entry_att_changed (GtkWidget *entry, gpointer data)
1203 {
1204         gboolean non_empty = gtk_clist_get_row_data(GTK_CLIST(personeditdlg.clist_attrib), 0) != NULL;
1205
1206         if (personeditdlg.read_only || personeditdlg.ldap)
1207                 return;
1208
1209         if (gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_atname)) == NULL
1210         ||  strlen(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_atname))) == 0) {
1211                 gtk_widget_set_sensitive(personeditdlg.attrib_add,FALSE);
1212                 gtk_widget_set_sensitive(personeditdlg.attrib_mod,FALSE);
1213                 attrib_adding = FALSE;
1214                 attrib_saving = FALSE;
1215         } else if (list_find_attribute(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_atname)))) {
1216                 gtk_widget_set_sensitive(personeditdlg.attrib_add,FALSE);
1217                 gtk_widget_set_sensitive(personeditdlg.attrib_mod,non_empty);
1218                 attrib_adding = FALSE;
1219                 attrib_saving = non_empty;
1220         } else {
1221                 gtk_widget_set_sensitive(personeditdlg.attrib_add,TRUE);
1222                 gtk_widget_set_sensitive(personeditdlg.attrib_mod,non_empty);
1223                 attrib_adding = TRUE;
1224                 attrib_saving = non_empty;
1225         }
1226 }
1227
1228 static gboolean edit_person_entry_att_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
1229 {
1230         if (event && event->keyval == GDK_Return) {
1231                 if (attrib_saving)
1232                         edit_person_attrib_modify(NULL);
1233                 else if (attrib_adding)
1234                         edit_person_attrib_add(NULL);
1235         }
1236         return FALSE;
1237 }
1238
1239 static void addressbook_edit_person_page_attrib( gint pageNum, gchar *pageLbl ) {
1240         GtkWidget *vbox;
1241         GtkWidget *hbox;
1242         GtkWidget *vboxl;
1243         GtkWidget *vboxb;
1244         GtkWidget *vbuttonbox;
1245         GtkWidget *buttonDel;
1246         GtkWidget *buttonMod;
1247         GtkWidget *buttonAdd;
1248
1249         GtkWidget *table;
1250         GtkWidget *label;
1251         GtkWidget *clist_swin;
1252         GtkWidget *clist;
1253         GtkWidget *entry_name;
1254         GtkWidget *entry_value;
1255         gint top;
1256
1257         gchar *titles[ ATTRIB_N_COLS ];
1258         gint i;
1259
1260         titles[ ATTRIB_COL_NAME  ] = _("Name");
1261         titles[ ATTRIB_COL_VALUE ] = _("Value");
1262
1263         vbox = gtk_vbox_new( FALSE, 8 );
1264         gtk_widget_show( vbox );
1265         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
1266         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
1267
1268         label = gtk_label_new_with_mnemonic( pageLbl );
1269         gtk_widget_show( label );
1270         gtk_notebook_set_tab_label(
1271                 GTK_NOTEBOOK( personeditdlg.notebook ),
1272                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
1273
1274         /* Split into two areas */
1275         hbox = gtk_hbox_new( FALSE, 0 );
1276         gtk_container_add( GTK_CONTAINER( vbox ), hbox );
1277
1278         /* Attribute list */
1279         vboxl = gtk_vbox_new( FALSE, 4 );
1280         gtk_container_add( GTK_CONTAINER( hbox ), vboxl );
1281         gtk_container_set_border_width( GTK_CONTAINER(vboxl), 4 );
1282
1283         clist_swin = gtk_scrolled_window_new( NULL, NULL );
1284         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
1285                                        GTK_POLICY_AUTOMATIC,
1286                                        GTK_POLICY_AUTOMATIC);
1287
1288         clist = gtk_clist_new_with_titles( ATTRIB_N_COLS, titles );
1289         gtk_container_add( GTK_CONTAINER(clist_swin), clist );
1290         gtk_clist_set_selection_mode( GTK_CLIST(clist), GTK_SELECTION_BROWSE );
1291         gtk_clist_set_compare_func( GTK_CLIST(clist), edit_person_attrib_compare_func );
1292         gtk_clist_set_auto_sort( GTK_CLIST(clist), TRUE );
1293         gtk_clist_set_column_width( GTK_CLIST(clist), ATTRIB_COL_NAME, ATTRIB_COL_WIDTH_NAME );
1294         gtk_clist_set_column_width( GTK_CLIST(clist), ATTRIB_COL_VALUE, ATTRIB_COL_WIDTH_VALUE );
1295
1296         for( i = 0; i < ATTRIB_N_COLS; i++ )
1297                 GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button, GTK_CAN_FOCUS);
1298
1299         /* Data entry area */
1300 #ifndef MAEMO
1301         table = gtk_table_new( 4, 2, FALSE);
1302         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
1303         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
1304 #else
1305         table = gtk_table_new( 2, 4, FALSE);
1306         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
1307         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
1308         gtk_clist_column_titles_hide(GTK_CLIST(clist));
1309 #endif
1310         gtk_container_set_border_width( GTK_CONTAINER(table), 4 );
1311         gtk_table_set_row_spacings(GTK_TABLE(table), 4);
1312         gtk_table_set_col_spacings(GTK_TABLE(table), 4);
1313
1314         /* First row */
1315         top = 0;
1316 #ifndef MAEMO
1317         label = gtk_label_new(_("Name"));
1318         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
1319         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1320
1321         entry_name = gtk_entry_new();
1322         gtk_table_attach(GTK_TABLE(table), entry_name, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1323
1324         /* Next row */
1325         ++top;
1326         label = gtk_label_new(_("Value"));
1327         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
1328         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1329
1330         entry_value = gtk_entry_new();
1331         gtk_table_attach(GTK_TABLE(table), entry_value, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1332 #else
1333         label = gtk_label_new(_("Name"));
1334         gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
1335         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1336
1337         entry_name = gtk_entry_new();
1338         gtk_table_attach(GTK_TABLE(table), entry_name, 1, 2, 0, 1, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1339
1340         /* Next row */
1341         ++top;
1342         label = gtk_label_new(_("Value"));
1343         gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, GTK_FILL, 0, 0, 0);
1344         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
1345
1346         entry_value = gtk_entry_new();
1347         gtk_table_attach(GTK_TABLE(table), entry_value, 3, 4, 0, 1, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
1348 #endif
1349         /* Button box */
1350         vboxb = gtk_vbox_new( FALSE, 4 );
1351         gtk_box_pack_start(GTK_BOX(hbox), vboxb, FALSE, FALSE, 2);
1352
1353         vbuttonbox = gtk_vbutton_box_new();
1354         gtk_button_box_set_layout( GTK_BUTTON_BOX(vbuttonbox), GTK_BUTTONBOX_START );
1355         gtk_box_set_spacing( GTK_BOX(vbuttonbox), 8 );
1356         gtk_container_set_border_width( GTK_CONTAINER(vbuttonbox), 4 );
1357         gtk_container_add( GTK_CONTAINER(vboxb), vbuttonbox );
1358
1359         /* Buttons */
1360         buttonDel = gtk_button_new_from_stock(GTK_STOCK_DELETE);
1361         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDel );
1362
1363         buttonMod = gtk_button_new_from_stock(GTK_STOCK_SAVE);
1364         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonMod );
1365
1366         buttonAdd = gtk_button_new_from_stock(GTK_STOCK_ADD);
1367         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonAdd );
1368         
1369         gtk_widget_set_sensitive(buttonDel,FALSE);
1370         gtk_widget_set_sensitive(buttonMod,FALSE);
1371         gtk_widget_set_sensitive(buttonAdd,FALSE);
1372
1373         gtk_widget_show_all(vbox);
1374
1375         /* Event handlers */
1376         g_signal_connect( G_OBJECT(clist), "select_row",
1377                           G_CALLBACK( edit_person_attrib_list_selected), NULL );
1378         g_signal_connect( G_OBJECT(buttonDel), "clicked",
1379                           G_CALLBACK( edit_person_attrib_delete ), NULL );
1380         g_signal_connect( G_OBJECT(buttonMod), "clicked",
1381                           G_CALLBACK( edit_person_attrib_modify ), NULL );
1382         g_signal_connect( G_OBJECT(buttonAdd), "clicked",
1383                           G_CALLBACK( edit_person_attrib_add ), NULL );
1384         g_signal_connect(G_OBJECT(entry_name), "changed",
1385                          G_CALLBACK(edit_person_entry_att_changed), NULL);
1386         g_signal_connect(G_OBJECT(entry_name), "key_press_event",
1387                          G_CALLBACK(edit_person_entry_att_pressed), NULL);
1388         g_signal_connect(G_OBJECT(entry_value), "key_press_event",
1389                          G_CALLBACK(edit_person_entry_att_pressed), NULL);
1390
1391         personeditdlg.clist_attrib  = clist;
1392         personeditdlg.entry_atname  = entry_name;
1393         personeditdlg.entry_atvalue = entry_value;
1394         personeditdlg.attrib_add = buttonAdd;
1395         personeditdlg.attrib_del = buttonDel;
1396         personeditdlg.attrib_mod = buttonMod;
1397 }
1398
1399 static void addressbook_edit_person_create( GtkWidget *parent, gboolean *cancelled ) {
1400         if (prefs_common.addressbook_use_editaddress_dialog)
1401                 addressbook_edit_person_dialog_create( cancelled );
1402         else
1403                 addressbook_edit_person_widgetset_create( parent, cancelled );
1404         addressbook_edit_person_page_basic( PAGE_BASIC, _( "_User Data" ) );
1405         addressbook_edit_person_page_email( PAGE_EMAIL, _( "_Email Addresses" ) );
1406 #ifdef USE_LDAP
1407         if (personeditdlg.ldap)
1408                 addressbook_edit_person_page_attrib_ldap(&personeditdlg, PAGE_ATTRIBUTES, _("O_ther Attributes"));
1409         else
1410 #endif
1411                 addressbook_edit_person_page_attrib( PAGE_ATTRIBUTES, _( "O_ther Attributes" ) );
1412         gtk_widget_show_all( personeditdlg.container );
1413 }
1414
1415 /*
1416 * Return list of email items.
1417 */
1418 static GList *edit_person_build_email_list() {
1419         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
1420         GList *listEMail = NULL;
1421         ItemEMail *email;
1422         gint row = 0;
1423         while( (email = gtk_clist_get_row_data( clist, row )) ) {
1424                 listEMail = g_list_append( listEMail, email );
1425                 row++;
1426         }
1427         return listEMail;
1428 }
1429
1430 /*
1431 * Return list of attributes.
1432 */
1433 static GList *edit_person_build_attrib_list() {
1434         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
1435         GList *listAttrib = NULL;
1436         UserAttribute *attrib;
1437         gint row = 0;
1438         while( (attrib = gtk_clist_get_row_data( clist, row )) ) {
1439                 listAttrib = g_list_append( listAttrib, attrib );
1440                 row++;
1441         }
1442         return listAttrib;
1443 }
1444
1445 static void update_sensitivity(void)
1446 {
1447         gtk_widget_set_sensitive(personeditdlg.entry_name,    !personeditdlg.read_only);
1448         gtk_widget_set_sensitive(personeditdlg.entry_first,   !personeditdlg.read_only);
1449         gtk_widget_set_sensitive(personeditdlg.entry_last,    !personeditdlg.read_only);
1450         gtk_widget_set_sensitive(personeditdlg.entry_nick,    !personeditdlg.read_only && !personeditdlg.ldap);
1451         gtk_widget_set_sensitive(personeditdlg.entry_email,   !personeditdlg.read_only);
1452         gtk_widget_set_sensitive(personeditdlg.entry_alias,   !personeditdlg.read_only && !personeditdlg.ldap);
1453         gtk_widget_set_sensitive(personeditdlg.entry_remarks, !personeditdlg.read_only && !personeditdlg.ldap);
1454         gtk_widget_set_sensitive(personeditdlg.email_up,      !personeditdlg.read_only);
1455         gtk_widget_set_sensitive(personeditdlg.email_down,    !personeditdlg.read_only);
1456         gtk_widget_set_sensitive(personeditdlg.email_del,     !personeditdlg.read_only);
1457         gtk_widget_set_sensitive(personeditdlg.email_mod,     !personeditdlg.read_only);
1458         gtk_widget_set_sensitive(personeditdlg.email_add,     !personeditdlg.read_only);
1459         gtk_widget_set_sensitive(personeditdlg.entry_atname,  !personeditdlg.read_only);
1460         gtk_widget_set_sensitive(personeditdlg.entry_atvalue, !personeditdlg.read_only);
1461         gtk_widget_set_sensitive(personeditdlg.attrib_add,    !personeditdlg.read_only);
1462         gtk_widget_set_sensitive(personeditdlg.attrib_del,    !personeditdlg.read_only);
1463         gtk_widget_set_sensitive(personeditdlg.attrib_mod,    !personeditdlg.read_only);
1464 }
1465
1466 static void addressbook_edit_person_flush_transient( void )
1467 {
1468         ItemPerson *person = current_person;
1469         EditAddressPostUpdateCallback callback = edit_person_close_post_update_cb;
1470
1471         /* reset transient data */
1472         current_abf = NULL;
1473         current_person = NULL;
1474         current_parent_folder = NULL;
1475         edit_person_close_post_update_cb = NULL;
1476
1477         /* post action to perform on addressbook side */
1478         if (callback)
1479                 callback( person );
1480 }
1481
1482 void addressbook_edit_person_invalidate( AddressBookFile *abf, ItemFolder *parent_folder,
1483                                                                                  ItemPerson *person )
1484 {
1485         if (current_abf == NULL &&
1486                 current_person == NULL &&
1487                 current_parent_folder == NULL)
1488                 /* edit address form is already hidden */
1489                 return;
1490
1491         /* unconditional invalidation or invalidating the currently edited item */
1492         if ( ( abf == NULL && person == NULL && parent_folder == NULL )
1493                 || (current_abf == abf ||
1494                         current_person == person ||
1495                         current_parent_folder == parent_folder))
1496                 addressbook_edit_person_close( TRUE );
1497 }
1498
1499 static gboolean addressbook_edit_person_close( gboolean cancelled )
1500 {
1501         GList *listEMail = NULL;
1502         GList *listAttrib = NULL;
1503         GError *error = NULL;
1504
1505         listEMail = edit_person_build_email_list();
1506         listAttrib = edit_person_build_attrib_list();
1507         if( cancelled ) {
1508                 addritem_free_list_email( listEMail );
1509                 addritem_free_list_attribute( listAttrib );
1510                 gtk_clist_clear( GTK_CLIST(personeditdlg.clist_email) );
1511                 gtk_clist_clear( GTK_CLIST(personeditdlg.clist_attrib) );
1512
1513                 if (!prefs_common.addressbook_use_editaddress_dialog)
1514                         gtk_widget_hide( personeditdlg.container );
1515
1516                 /* no callback, as we're discarding the form */
1517                 edit_person_close_post_update_cb = NULL;
1518                 addressbook_edit_person_flush_transient();
1519                 current_person = NULL;
1520
1521                 /* set focus to the address list (this is done by the post_update_cb usually) */
1522                 addressbook_address_list_set_focus();
1523                 return FALSE;
1524         }
1525
1526         if( current_person && current_abf ) {
1527                 /* Update email/attribute list for existing current_person */
1528                 addrbook_update_address_list( current_abf, current_person, listEMail );
1529                 addrbook_update_attrib_list( current_abf, current_person, listAttrib );
1530         }
1531         else {
1532                 /* Create new current_person and email/attribute list */
1533                 if( ! cancelled && current_abf ) {
1534                         current_person = addrbook_add_address_list( current_abf, current_parent_folder, listEMail );
1535                         addrbook_add_attrib_list( current_abf, current_person, listAttrib );
1536                 }
1537         }
1538         listEMail = NULL;
1539         listAttrib = NULL;
1540
1541         if( ! cancelled ) {
1542                 /* Set current_person stuff */          
1543
1544                 gchar *name;
1545                 gchar *cn = edit_person_get_common_name_from_widgets();
1546
1547                 addritem_person_set_common_name( current_person, cn );
1548                 g_free( cn );
1549
1550                 if (personeditdlg.picture_set) { 
1551                         GdkPixbuf * pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(personeditdlg.image));
1552
1553                         if (!current_person->picture)
1554                                 name = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S, ADDRBOOK_DIR, G_DIR_SEPARATOR_S, 
1555                                                 ADDRITEM_ID(current_person), ".png", NULL );
1556                         else 
1557                                 name = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S, ADDRBOOK_DIR, G_DIR_SEPARATOR_S, 
1558                                                 current_person->picture, ".png", NULL );
1559
1560                         gdk_pixbuf_save(pixbuf, name, "png", &error, NULL);
1561                         if (error) {
1562                                 alertpanel_error(_("Failed to save image: \n%s"),
1563                                                 error->message);
1564                                 g_error_free(error);
1565                         } else {
1566                                 debug_print("saved picture to %s\n", name);
1567                         }
1568                         if (!current_person->picture)
1569                                 addritem_person_set_picture( current_person, ADDRITEM_ID(current_person) ) ;
1570                         g_free( name );
1571                 } else {
1572                         if (!current_person->picture)
1573                                 name = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S, ADDRBOOK_DIR, G_DIR_SEPARATOR_S, 
1574                                                 ADDRITEM_ID(current_person), ".png", NULL );
1575                         else 
1576                                 name = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S, ADDRBOOK_DIR, G_DIR_SEPARATOR_S, 
1577                                                 current_person->picture, ".png", NULL );
1578                         g_unlink(name);
1579                         g_free(name);
1580                 }
1581                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_first), 0, -1 );
1582                 addritem_person_set_first_name( current_person, name );
1583                 g_free( name );
1584                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_last), 0, -1 );
1585                 addritem_person_set_last_name( current_person, name );
1586                 g_free( name );
1587                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_nick), 0, -1 );
1588                 addritem_person_set_nick_name( current_person, name );
1589                 g_free( name );
1590         }
1591
1592         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_email) );
1593         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_attrib) );
1594
1595         if (!prefs_common.addressbook_use_editaddress_dialog)
1596                 gtk_widget_hide( personeditdlg.container );
1597
1598         addressbook_edit_person_flush_transient();
1599
1600         return TRUE;
1601 }
1602  
1603 /*
1604 * Edit person.
1605 * Enter: abf    Address book.
1606 *        parent Parent folder for person (or NULL if adding to root folder). Argument is
1607 *               only required for new objects).
1608 *        person Person to edit, or NULL for a new person object.
1609 *        pgMail If TRUE, E-Mail page will be activated.
1610 * Return: Edited object, or NULL if cancelled.*/
1611 ItemPerson *addressbook_edit_person( AddressBookFile *abf, ItemFolder *parent_folder, ItemPerson *person,
1612                                                                          gboolean pgMail, GtkWidget *parent_container,
1613                                                                          void (*post_update_cb) (ItemPerson *person),
1614                                                                          gboolean get_focus) {
1615         static gboolean cancelled;
1616         GError *error = NULL;
1617         GdkPixbuf *pixbuf = NULL;
1618         /* set transient data */
1619         current_abf = abf;
1620         current_person = person;
1621         current_parent_folder = parent_folder;
1622         edit_person_close_post_update_cb = post_update_cb;
1623         personeditdlg.ldap = (abf && abf->type == ADBOOKTYPE_LDAP)? TRUE : FALSE;
1624
1625         if( personeditdlg.container ) {
1626                 gtk_widget_destroy(personeditdlg.container);
1627                 personeditdlg.container = NULL;
1628         }
1629         addressbook_edit_person_create(parent_container, &cancelled);
1630
1631         /* typically, get focus when dialog mode is enabled, or when editing a new address */
1632         if( get_focus ) {
1633                 gtk_widget_grab_focus(personeditdlg.ok_btn);
1634                 gtk_widget_grab_focus(personeditdlg.entry_name);
1635         }
1636         
1637         personeditdlg.read_only = (current_abf == NULL);
1638         update_sensitivity();
1639
1640         gtk_widget_show(personeditdlg.container);
1641         if (prefs_common.addressbook_use_editaddress_dialog)
1642                 manage_window_set_transient(GTK_WINDOW(personeditdlg.container));
1643         else
1644                 if (get_focus)
1645                         addressbook_address_list_disable_some_actions();
1646
1647         /* Clear all fields */
1648         personeditdlg.rowIndEMail = -1;
1649         personeditdlg.rowIndAttrib = -1;
1650         edit_person_status_show( "" );
1651         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_email) );
1652         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_attrib) );
1653         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_name), "" );
1654         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_first), "" );
1655         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_last), "" );
1656         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), "" );
1657
1658         personeditdlg.editNew = FALSE;
1659         if( current_person ) {
1660                 gchar *filename = NULL;
1661
1662                 if( ADDRITEM_NAME(current_person) )
1663                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_name), ADDRITEM_NAME(person) );
1664
1665                 menu_set_sensitive(personeditdlg.editaddr_popupfactory,
1666                                 "/Set picture", !personeditdlg.ldap);
1667                 menu_set_sensitive(personeditdlg.editaddr_popupfactory,
1668                                 "/Unset picture", !personeditdlg.ldap);
1669                 if( current_person->picture ) { 
1670                         filename = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S, ADDRBOOK_DIR, G_DIR_SEPARATOR_S, 
1671                                                         current_person->picture, ".png", NULL );
1672                         if (is_file_exist(filename)) {
1673                                 pixbuf = gdk_pixbuf_new_from_file(filename, &error);
1674                                 if (error) {
1675                                         debug_print("Failed to import image: \n%s",
1676                                                         error->message);
1677                                         g_error_free(error);
1678                                         goto no_img;
1679                                 }
1680                                 personeditdlg.picture_set = TRUE;
1681                                 menu_set_sensitive(personeditdlg.editaddr_popupfactory,
1682                                                 "/Unset picture", !personeditdlg.ldap && personeditdlg.picture_set);
1683                         } else {
1684                                 goto no_img;
1685                         }
1686                         gtk_image_set_from_pixbuf(GTK_IMAGE(personeditdlg.image), pixbuf);
1687                 } else {
1688 no_img:
1689                         addressbook_edit_person_clear_picture();
1690                 }
1691                 
1692                 g_free(filename);
1693                 if (pixbuf) {
1694                         g_object_unref(pixbuf);
1695                         pixbuf = NULL;
1696                 }
1697
1698                 if( current_person->firstName )
1699                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_first), current_person->firstName );
1700                 if( current_person->lastName )
1701                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_last), current_person->lastName );
1702                 if( current_person->nickName )
1703                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), current_person->nickName );
1704                 edit_person_load_email( current_person );
1705                 edit_person_load_attrib( current_person );
1706                 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_atvalue), "");
1707         }
1708         else {
1709                 personeditdlg.editNew = TRUE;
1710         }
1711
1712         /* Select appropriate start page */
1713         if( pgMail ) {
1714                 gtk_notebook_set_current_page( GTK_NOTEBOOK(personeditdlg.notebook), PAGE_EMAIL );
1715         }
1716         else {
1717                 gtk_notebook_set_current_page( GTK_NOTEBOOK(personeditdlg.notebook), PAGE_BASIC );
1718         }
1719
1720         gtk_clist_select_row( GTK_CLIST(personeditdlg.clist_email), 0, 0 );
1721         gtk_clist_select_row( GTK_CLIST(personeditdlg.clist_attrib), 0, 0 );
1722         edit_person_email_clear( NULL );
1723         if (current_person)
1724                 edit_person_email_list_selected(GTK_CLIST(personeditdlg.clist_email), 0, 0, NULL, NULL);
1725
1726         edit_person_attrib_clear( NULL );
1727
1728         if (prefs_common.addressbook_use_editaddress_dialog) {
1729                 gtk_main();
1730                 gtk_widget_hide( personeditdlg.container );
1731
1732                 if (!addressbook_edit_person_close( cancelled )) {
1733                         return NULL;
1734                 }
1735         }
1736         
1737         return person;
1738 }
1739
1740 /*
1741 * End of Source.
1742 */
1743