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