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