2005-02-03 [paul] 1.0.0cvs25.3
[claws.git] / src / editaddress.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2003 Hiroyuki Yamamoto
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 2 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, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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 <gdk/gdkkeysyms.h>
28 #include <gtk/gtkwindow.h>
29 #include <gtk/gtksignal.h>
30 #include <gtk/gtklabel.h>
31 #include <gtk/gtkvbox.h>
32 #include <gtk/gtkentry.h>
33 #include <gtk/gtktable.h>
34
35 #include "intl.h"
36 #include "mgutils.h"
37 #include "addressbook.h"
38 #include "addressitem.h"
39 #include "addritem.h"
40 #include "addrbook.h"
41 #include "manage_window.h"
42 #include "gtkutils.h"
43 #include "codeconv.h"
44
45 #include "prefs_common.h"
46
47 static struct _PersonEdit_dlg {
48         GtkWidget *window;
49         GtkWidget *notebook;
50         GtkWidget *ok_btn;
51         GtkWidget *cancel_btn;
52         GtkWidget *statusbar;
53         gint status_cid;
54
55         /* Basic data tab */
56         GtkWidget *entry_name;
57         GtkWidget *entry_first;
58         GtkWidget *entry_last;
59         GtkWidget *entry_nick;
60
61         /* EMail data tab */
62         GtkWidget *entry_email;
63         GtkWidget *entry_alias;
64         GtkWidget *entry_remarks;
65         GtkWidget *clist_email;
66
67         /* Attribute data tab */
68         GtkWidget *entry_atname;
69         GtkWidget *entry_atvalue;
70         GtkWidget *clist_attrib;
71
72         gint rowIndEMail;
73         gint rowIndAttrib;
74         gboolean editNew;
75
76 } personeditdlg;
77
78 typedef enum {
79         EMAIL_COL_EMAIL   = 0,
80         EMAIL_COL_ALIAS   = 1,
81         EMAIL_COL_REMARKS = 2
82 } PersonEditEMailColumnPos;
83
84 typedef enum {
85         ATTRIB_COL_NAME    = 0,
86         ATTRIB_COL_VALUE   = 1
87 } PersonEditAttribColumnPos;
88
89 #define EDITPERSON_WIDTH      520
90 #define EDITPERSON_HEIGHT     340
91
92 #define EMAIL_N_COLS          3
93 #define EMAIL_COL_WIDTH_EMAIL 180
94 #define EMAIL_COL_WIDTH_ALIAS 80
95
96 #define ATTRIB_N_COLS          2
97 #define ATTRIB_COL_WIDTH_NAME  120
98 #define ATTRIB_COL_WIDTH_VALUE 180
99
100 #define PAGE_BASIC             0
101 #define PAGE_EMAIL             1
102 #define PAGE_ATTRIBUTES        2
103
104 static void edit_person_status_show( gchar *msg ) {
105         if( personeditdlg.statusbar != NULL ) {
106                 gtk_statusbar_pop( GTK_STATUSBAR(personeditdlg.statusbar), personeditdlg.status_cid );
107                 if( msg ) {
108                         gtk_statusbar_push( GTK_STATUSBAR(personeditdlg.statusbar), personeditdlg.status_cid, msg );
109                 }
110         }
111 }
112
113 static void edit_person_ok(GtkWidget *widget, gboolean *cancelled) {
114         *cancelled = FALSE;
115         gtk_main_quit();
116 }
117
118 static void edit_person_cancel(GtkWidget *widget, gboolean *cancelled) {
119         *cancelled = TRUE;
120         gtk_main_quit();
121 }
122
123 static gint edit_person_delete_event(GtkWidget *widget, GdkEventAny *event, gboolean *cancelled) {
124         *cancelled = TRUE;
125         gtk_main_quit();
126         return TRUE;
127 }
128
129 static gboolean edit_person_key_pressed(GtkWidget *widget, GdkEventKey *event, gboolean *cancelled) {
130         if (event && event->keyval == GDK_Escape) {
131                 *cancelled = TRUE;
132                 gtk_main_quit();
133         }
134         return FALSE;
135 }
136
137 static gchar *_title_new_ = NULL;
138 static gchar *_title_edit_ = NULL;
139
140 static void edit_person_set_window_title( gint pageNum ) {
141         gchar *sTitle;
142
143         if( _title_new_ == NULL ) {
144                 _title_new_ = g_strdup( _("Add New Person") );
145                 _title_edit_ = g_strdup( _("Edit Person Details") );
146         }
147
148         if( pageNum == PAGE_BASIC ) {
149                 if( personeditdlg.editNew ) {
150                         gtk_window_set_title( GTK_WINDOW(personeditdlg.window), _title_new_ );
151                 }
152                 else {
153                         gtk_window_set_title( GTK_WINDOW(personeditdlg.window), _title_edit_ );
154                 }
155         }
156         else {
157                 if( personeditdlg.entry_name == NULL ) {
158                         sTitle = g_strdup( _title_edit_ );
159                 }
160                 else {
161                         gchar *name;
162                         name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_name), 0, -1 );
163                         sTitle = g_strdup_printf( "%s - %s", _title_edit_, name );
164                         g_free( name );
165                 }
166                 gtk_window_set_title( GTK_WINDOW(personeditdlg.window), sTitle );
167                 g_free( sTitle );
168         }
169 }
170
171 static void edit_person_email_clear( gpointer data ) {
172         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_email), "" );
173         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_alias), "" );
174         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_remarks), "" );
175 }
176
177 static void edit_person_attrib_clear( gpointer data ) {
178         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atname), "" );
179         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atvalue), "" );
180 }
181
182 static void edit_person_switch_page( GtkNotebook *notebook, GtkNotebookPage *page,
183                                         gint pageNum, gpointer user_data)
184 {
185         edit_person_set_window_title( pageNum );
186         edit_person_status_show( "" );
187 }
188
189 /*
190 * Load clist with a copy of person's email addresses.
191 */
192 static void edit_person_load_email( ItemPerson *person ) {
193         GList *node = person->listEMail;
194         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
195         gchar *text[ EMAIL_N_COLS ];
196         while( node ) {
197                 ItemEMail *emorig = ( ItemEMail * ) node->data;
198                 ItemEMail *email = addritem_copyfull_item_email( emorig );
199                 gint row;
200                 text[ EMAIL_COL_EMAIL   ] = email->address;
201                 text[ EMAIL_COL_ALIAS   ] = email->obj.name;
202                 text[ EMAIL_COL_REMARKS ] = email->remarks;
203
204                 row = gtk_clist_append( clist, text );
205                 gtk_clist_set_row_data( clist, row, email );
206                 node = g_list_next( node );
207         }
208 }
209
210 static void edit_person_email_list_selected( GtkCList *clist, gint row, gint column, GdkEvent *event, gpointer data ) {
211         ItemEMail *email = gtk_clist_get_row_data( clist, row );
212         if( email ) {
213                 if( email->address )
214                         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_email), email->address );
215                 if( ADDRITEM_NAME(email) )
216                         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_alias), ADDRITEM_NAME(email) );
217                 if( email->remarks )
218                         gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_remarks), email->remarks );
219         }
220         personeditdlg.rowIndEMail = row;
221         edit_person_status_show( NULL );
222 }
223
224 static void edit_person_email_move( gint dir ) {
225         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
226         gint row = personeditdlg.rowIndEMail + dir;
227         ItemEMail *email = gtk_clist_get_row_data( clist, row );
228         if( email ) {
229                 gtk_clist_row_move( clist, personeditdlg.rowIndEMail, row );
230                 personeditdlg.rowIndEMail = row;
231         }
232         edit_person_email_clear( NULL );
233         edit_person_status_show( NULL );
234 }
235
236 static void edit_person_email_move_up( gpointer data ) {
237         edit_person_email_move( -1 );
238 }
239
240 static void edit_person_email_move_down( gpointer data ) {
241         edit_person_email_move( +1 );
242 }
243
244 static void edit_person_email_delete( gpointer data ) {
245         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
246         gint row = personeditdlg.rowIndEMail;
247         ItemEMail *email = gtk_clist_get_row_data( clist, row );
248         edit_person_email_clear( NULL );
249         if( email ) {
250                 /* Remove list entry */
251                 gtk_clist_remove( clist, row );
252                 addritem_free_item_email( email );
253                 email = NULL;
254         }
255
256         /* Position hilite bar */
257         email = gtk_clist_get_row_data( clist, row );
258         if( ! email ) {
259                 personeditdlg.rowIndEMail = -1 + row;
260         }
261         edit_person_status_show( NULL );
262 }
263
264 static ItemEMail *edit_person_email_edit( gboolean *error, ItemEMail *email ) {
265         ItemEMail *retVal = NULL;
266         gchar *sEmail, *sAlias, *sRemarks, *sEmail_;
267
268         *error = TRUE;
269         sEmail_ = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_email), 0, -1 );
270         sAlias = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_alias), 0, -1 );
271         sRemarks = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_remarks), 0, -1 );
272         sEmail = mgu_email_check_empty( sEmail_ );
273         g_free( sEmail_ );
274
275         if( sEmail ) {
276                 if( email == NULL ) {
277                         email = addritem_create_item_email();
278                 }
279                 addritem_email_set_address( email, sEmail );
280                 addritem_email_set_alias( email, sAlias );
281                 addritem_email_set_remarks( email, sRemarks );
282                 retVal = email;
283                 *error = FALSE;
284         }
285         else {
286                 edit_person_status_show( _( "An E-Mail address must be supplied." ) );
287         }
288
289         g_free( sEmail );
290         g_free( sAlias );
291         g_free( sRemarks );
292
293         return retVal;
294 }
295
296 static void edit_person_email_modify( gpointer data ) {
297         gboolean errFlg = FALSE;
298         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
299         gint row = personeditdlg.rowIndEMail;
300         ItemEMail *email = gtk_clist_get_row_data( clist, row );
301         if( email ) {
302                 edit_person_email_edit( &errFlg, email );
303                 if( ! errFlg ) {
304                         gtk_clist_set_text( clist, row, EMAIL_COL_EMAIL, email->address );
305                         gtk_clist_set_text( clist, row, EMAIL_COL_ALIAS, email->obj.name );
306                         gtk_clist_set_text( clist, row, EMAIL_COL_REMARKS, email->remarks );
307                         edit_person_email_clear( NULL );
308                 }
309         }
310 }
311
312 static void edit_person_email_add( gpointer data ) {
313         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
314         gboolean errFlg = FALSE;
315         ItemEMail *email = NULL;
316         gint row = personeditdlg.rowIndEMail;
317         if( gtk_clist_get_row_data( clist, row ) == NULL ) row = 0;
318
319         email = edit_person_email_edit( &errFlg, NULL );
320         if( ! errFlg ) {
321                 gchar *text[ EMAIL_N_COLS ];
322                 text[ EMAIL_COL_EMAIL   ] = email->address;
323                 text[ EMAIL_COL_ALIAS   ] = email->obj.name;
324                 text[ EMAIL_COL_REMARKS ] = email->remarks;
325
326                 row = gtk_clist_insert( clist, 1 + row, text );
327                 gtk_clist_set_row_data( clist, row, email );
328                 gtk_clist_select_row( clist, row, 0 );
329                 edit_person_email_clear( NULL );
330         }
331 }
332
333 /*
334 * Comparison using cell contents (text in first column). Used for sort
335 * address index widget.
336 */
337 static gint edit_person_attrib_compare_func(
338         GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2 )
339 {
340         GtkCell *cell1 = ((GtkCListRow *)ptr1)->cell;
341         GtkCell *cell2 = ((GtkCListRow *)ptr2)->cell;
342         gchar *name1 = NULL, *name2 = NULL;
343
344         if( cell1 ) name1 = cell1->u.text;
345         if( cell2 ) name2 = cell2->u.text;
346         if( ! name1 ) return ( name2 != NULL );
347         if( ! name2 ) return -1;
348         return g_utf8_collate( name1, name2 );
349 }
350
351 /*
352 * Load clist with a copy of person's email addresses.
353 */
354 static void edit_person_load_attrib( ItemPerson *person ) {
355         GList *node = person->listAttrib;
356         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
357         gchar *text[ ATTRIB_N_COLS ];
358         while( node ) {
359                 UserAttribute *atorig = ( UserAttribute * ) node->data;
360                 UserAttribute *attrib = addritem_copy_attribute( atorig );
361                 gint row;
362                 text[ ATTRIB_COL_NAME  ] = attrib->name;
363                 text[ ATTRIB_COL_VALUE ] = attrib->value;
364
365                 row = gtk_clist_append( clist, text );
366                 gtk_clist_set_row_data( clist, row, attrib );
367                 node = g_list_next( node );
368         }
369 }
370
371 static void edit_person_attrib_list_selected( GtkCList *clist, gint row, gint column, GdkEvent *event, gpointer data ) {
372         UserAttribute *attrib = gtk_clist_get_row_data( clist, row );
373         if( attrib ) {
374                 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atname), attrib->name );
375                 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atvalue), attrib->value );
376         }
377         personeditdlg.rowIndAttrib = row;
378         edit_person_status_show( NULL );
379 }
380
381 static void edit_person_attrib_delete( gpointer data ) {
382         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
383         gint row = personeditdlg.rowIndAttrib;
384         UserAttribute *attrib = gtk_clist_get_row_data( clist, row );
385         edit_person_attrib_clear( NULL );
386         if( attrib ) {
387                 /* Remove list entry */
388                 gtk_clist_remove( clist, row );
389                 addritem_free_attribute( attrib );
390                 attrib = NULL;
391         }
392
393         /* Position hilite bar */
394         attrib = gtk_clist_get_row_data( clist, row );
395         if( ! attrib ) {
396                 personeditdlg.rowIndAttrib = -1 + row;
397         }
398         edit_person_status_show( NULL );
399 }
400
401 static UserAttribute *edit_person_attrib_edit( gboolean *error, UserAttribute *attrib ) {
402         UserAttribute *retVal = NULL;
403         gchar *sName, *sValue, *sName_, *sValue_;
404
405         *error = TRUE;
406         sName_ = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_atname), 0, -1 );
407         sValue_ = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_atvalue), 0, -1 );
408         sName = mgu_email_check_empty( sName_ );
409         sValue = mgu_email_check_empty( sValue_ );
410         g_free( sName_ );
411         g_free( sValue_ );
412
413         if( sName && sValue ) {
414                 if( attrib == NULL ) {
415                         attrib = addritem_create_attribute();
416                 }
417                 addritem_attrib_set_name( attrib, sName );
418                 addritem_attrib_set_value( attrib, sValue );
419                 retVal = attrib;
420                 *error = FALSE;
421         }
422         else {
423                 edit_person_status_show( _( "A Name and Value must be supplied." ) );
424         }
425
426         g_free( sName );
427         g_free( sValue );
428
429         return retVal;
430 }
431
432 static void edit_person_attrib_modify( gpointer data ) {
433         gboolean errFlg = FALSE;
434         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
435         gint row = personeditdlg.rowIndAttrib;
436         UserAttribute *attrib = gtk_clist_get_row_data( clist, row );
437         if( attrib ) {
438                 edit_person_attrib_edit( &errFlg, attrib );
439                 if( ! errFlg ) {
440                         gtk_clist_set_text( clist, row, ATTRIB_COL_NAME, attrib->name );
441                         gtk_clist_set_text( clist, row, ATTRIB_COL_VALUE, attrib->value );
442                         edit_person_attrib_clear( NULL );
443                 }
444         }
445 }
446
447 static void edit_person_attrib_add( gpointer data ) {
448         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
449         gboolean errFlg = FALSE;
450         UserAttribute *attrib = NULL;
451         gint row = personeditdlg.rowIndAttrib;
452         if( gtk_clist_get_row_data( clist, row ) == NULL ) row = 0;
453
454         attrib = edit_person_attrib_edit( &errFlg, NULL );
455         if( ! errFlg ) {
456                 gchar *text[ EMAIL_N_COLS ];
457                 text[ ATTRIB_COL_NAME  ] = attrib->name;
458                 text[ ATTRIB_COL_VALUE ] = attrib->value;
459
460                 row = gtk_clist_insert( clist, 1 + row, text );
461                 gtk_clist_set_row_data( clist, row, attrib );
462                 gtk_clist_select_row( clist, row, 0 );
463                 edit_person_attrib_clear( NULL );
464         }
465 }
466
467 static void addressbook_edit_person_dialog_create( gboolean *cancelled ) {
468         GtkWidget *window;
469         GtkWidget *vbox;
470         GtkWidget *vnbox;
471         GtkWidget *notebook;
472         GtkWidget *hbbox;
473         GtkWidget *ok_btn;
474         GtkWidget *cancel_btn;
475         GtkWidget *hsbox;
476         GtkWidget *statusbar;
477
478         window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
479         gtk_widget_set_size_request(window, EDITPERSON_WIDTH, EDITPERSON_HEIGHT );
480         /* gtk_container_set_border_width(GTK_CONTAINER(window), 0); */
481         gtk_window_set_title(GTK_WINDOW(window), _("Edit Person Data"));
482         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
483         gtk_window_set_modal(GTK_WINDOW(window), TRUE); 
484         g_signal_connect(G_OBJECT(window), "delete_event",
485                          G_CALLBACK(edit_person_delete_event),
486                          cancelled);
487         g_signal_connect(G_OBJECT(window), "key_press_event",
488                          G_CALLBACK(edit_person_key_pressed),
489                          cancelled);
490
491         vbox = gtk_vbox_new(FALSE, 4);
492         /* gtk_container_set_border_width(GTK_CONTAINER(vbox), BORDER_WIDTH); */
493         gtk_widget_show(vbox);
494         gtk_container_add(GTK_CONTAINER(window), vbox);
495
496         vnbox = gtk_vbox_new(FALSE, 4);
497         gtk_container_set_border_width(GTK_CONTAINER(vnbox), 4);
498         gtk_widget_show(vnbox);
499         gtk_box_pack_start(GTK_BOX(vbox), vnbox, TRUE, TRUE, 0);
500
501         /* Notebook */
502         notebook = gtk_notebook_new();
503         gtk_widget_show(notebook);
504         gtk_box_pack_start(GTK_BOX(vnbox), notebook, TRUE, TRUE, 0);
505         gtk_container_set_border_width(GTK_CONTAINER(notebook), 6);
506
507         /* Status line */
508         hsbox = gtk_hbox_new(FALSE, 0);
509         gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, BORDER_WIDTH);
510         statusbar = gtk_statusbar_new();
511         gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, BORDER_WIDTH);
512
513         /* Button panel */
514         gtkut_stock_button_set_create(&hbbox, &ok_btn, GTK_STOCK_OK,
515                                       &cancel_btn, GTK_STOCK_CANCEL,
516                                       NULL, NULL);
517         gtk_box_pack_end(GTK_BOX(vnbox), hbbox, FALSE, FALSE, 0);
518         gtk_widget_grab_default(ok_btn);
519
520         g_signal_connect(G_OBJECT(ok_btn), "clicked",
521                          G_CALLBACK(edit_person_ok), cancelled);
522         g_signal_connect(G_OBJECT(cancel_btn), "clicked",
523                          G_CALLBACK(edit_person_cancel), cancelled);
524         g_signal_connect(G_OBJECT(notebook), "switch_page",
525                          G_CALLBACK(edit_person_switch_page), NULL );
526
527         gtk_widget_show_all(vbox);
528
529         personeditdlg.window     = window;
530         personeditdlg.notebook   = notebook;
531         personeditdlg.ok_btn     = ok_btn;
532         personeditdlg.cancel_btn = cancel_btn;
533         personeditdlg.statusbar  = statusbar;
534         personeditdlg.status_cid = gtk_statusbar_get_context_id( GTK_STATUSBAR(statusbar), "Edit Person Dialog" );
535
536 }
537
538 static void addressbook_edit_person_page_basic( gint pageNum, gchar *pageLbl ) {
539         GtkWidget *vbox;
540         GtkWidget *table;
541         GtkWidget *label;
542         GtkWidget *entry_name;
543         GtkWidget *entry_fn;
544         GtkWidget *entry_ln;
545         GtkWidget *entry_nn;
546         const gchar *locale;
547         gint top = 0;
548
549         vbox = gtk_vbox_new( FALSE, 8 );
550         gtk_widget_show( vbox );
551         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
552         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
553
554         label = gtk_label_new( pageLbl );
555         gtk_widget_show( label );
556         gtk_notebook_set_tab_label(
557                 GTK_NOTEBOOK( personeditdlg.notebook ),
558                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
559
560         table = gtk_table_new( 4, 3, FALSE);
561         gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
562         gtk_container_set_border_width( GTK_CONTAINER(table), 8 );
563         gtk_table_set_row_spacings(GTK_TABLE(table), 8);
564         gtk_table_set_col_spacings(GTK_TABLE(table), 8);
565
566 #define ATTACH_ROW(text, entry) \
567 { \
568         label = gtk_label_new(text); \
569         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), \
570                          GTK_FILL, 0, 0, 0); \
571         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); \
572  \
573         entry = gtk_entry_new(); \
574         gtk_table_attach(GTK_TABLE(table), entry, 1, 2, top, (top + 1), \
575                          GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0); \
576         top++; \
577 }
578
579         ATTACH_ROW(_("Display Name"), entry_name);
580         locale = conv_get_current_locale();
581         if (locale &&
582             (!g_ascii_strncasecmp(locale, "ja", 2) ||
583              !g_ascii_strncasecmp(locale, "ko", 2) ||
584              !g_ascii_strncasecmp(locale, "zh", 2))) {
585                 ATTACH_ROW(_("Last Name"), entry_ln);
586                 ATTACH_ROW(_("First Name"), entry_fn);
587         } else {
588                 ATTACH_ROW(_("First Name"), entry_fn);
589                 ATTACH_ROW(_("Last Name"), entry_ln);
590         }
591         ATTACH_ROW(_("Nickname"), entry_nn);
592
593 #undef ATTACH_ROW
594
595         gtk_widget_show_all(vbox);
596
597         personeditdlg.entry_name  = entry_name;
598         personeditdlg.entry_first = entry_fn;
599         personeditdlg.entry_last  = entry_ln;
600         personeditdlg.entry_nick  = entry_nn;
601 }
602
603 static void addressbook_edit_person_page_email( gint pageNum, gchar *pageLbl ) {
604         GtkWidget *vbox;
605         GtkWidget *hbox;
606         GtkWidget *vboxl;
607         GtkWidget *vboxb;
608         GtkWidget *vbuttonbox;
609         GtkWidget *buttonUp;
610         GtkWidget *buttonDown;
611         GtkWidget *buttonDel;
612         GtkWidget *buttonMod;
613         GtkWidget *buttonAdd;
614         GtkWidget *buttonClr;
615
616         GtkWidget *table;
617         GtkWidget *label;
618         GtkWidget *clist_swin;
619         GtkWidget *clist;
620         GtkWidget *entry_email;
621         GtkWidget *entry_alias;
622         GtkWidget *entry_remarks;
623         gint top;
624
625         gchar *titles[ EMAIL_N_COLS ];
626         gint i;
627
628         titles[ EMAIL_COL_EMAIL   ] = _("E-Mail Address");
629         titles[ EMAIL_COL_ALIAS   ] = _("Alias");
630         titles[ EMAIL_COL_REMARKS ] = _("Remarks");
631
632         vbox = gtk_vbox_new( FALSE, 8 );
633         gtk_widget_show( vbox );
634         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
635         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
636
637         label = gtk_label_new( pageLbl );
638         gtk_widget_show( label );
639         gtk_notebook_set_tab_label(
640                 GTK_NOTEBOOK( personeditdlg.notebook ),
641                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
642
643         /* Split into two areas */
644         hbox = gtk_hbox_new( FALSE, 0 );
645         gtk_container_add( GTK_CONTAINER( vbox ), hbox );
646
647         /* Address list */
648         vboxl = gtk_vbox_new( FALSE, 4 );
649         gtk_container_add( GTK_CONTAINER( hbox ), vboxl );
650         gtk_container_set_border_width( GTK_CONTAINER(vboxl), 4 );
651
652         clist_swin = gtk_scrolled_window_new( NULL, NULL );
653         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
654         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
655                                        GTK_POLICY_AUTOMATIC,
656                                        GTK_POLICY_AUTOMATIC);
657
658         clist = gtk_clist_new_with_titles( EMAIL_N_COLS, titles );
659         gtk_container_add( GTK_CONTAINER(clist_swin), clist );
660         gtk_clist_set_selection_mode( GTK_CLIST(clist), GTK_SELECTION_BROWSE );
661         gtk_clist_set_column_width( GTK_CLIST(clist), EMAIL_COL_EMAIL, EMAIL_COL_WIDTH_EMAIL );
662         gtk_clist_set_column_width( GTK_CLIST(clist), EMAIL_COL_ALIAS, EMAIL_COL_WIDTH_ALIAS );
663
664         for( i = 0; i < EMAIL_N_COLS; i++ )
665                 GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button, GTK_CAN_FOCUS);
666
667         /* Data entry area */
668         table = gtk_table_new( 4, 2, FALSE);
669         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
670         gtk_container_set_border_width( GTK_CONTAINER(table), 4 );
671         gtk_table_set_row_spacings(GTK_TABLE(table), 4);
672         gtk_table_set_col_spacings(GTK_TABLE(table), 4);
673
674         /* First row */
675         top = 0;
676         label = gtk_label_new(_("E-Mail Address"));
677         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
678         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
679
680         entry_email = gtk_entry_new();
681         gtk_table_attach(GTK_TABLE(table), entry_email, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
682
683         /* Next row */
684         ++top;
685         label = gtk_label_new(_("Alias"));
686         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
687         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
688
689         entry_alias = gtk_entry_new();
690         gtk_table_attach(GTK_TABLE(table), entry_alias, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
691
692         /* Next row */
693         ++top;
694         label = gtk_label_new(_("Remarks"));
695         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
696         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
697
698         entry_remarks = gtk_entry_new();
699         gtk_table_attach(GTK_TABLE(table), entry_remarks, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
700
701         /* Button box */
702         vboxb = gtk_vbox_new( FALSE, 4 );
703         gtk_box_pack_start(GTK_BOX(hbox), vboxb, FALSE, FALSE, 2);
704
705         vbuttonbox = gtk_vbutton_box_new();
706         gtk_button_box_set_layout( GTK_BUTTON_BOX(vbuttonbox), GTK_BUTTONBOX_START );
707         gtk_box_set_spacing( GTK_BOX(vbuttonbox), 8 );
708         gtk_container_set_border_width( GTK_CONTAINER(vbuttonbox), 4 );
709         gtk_container_add( GTK_CONTAINER(vboxb), vbuttonbox );
710
711         /* Buttons */
712         buttonUp = gtk_button_new_with_label( _( "Move Up" ) );
713         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonUp );
714
715         buttonDown = gtk_button_new_with_label( _( "Move Down" ) );
716         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDown );
717
718         buttonDel = gtk_button_new_with_label( _( "Delete" ) );
719         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDel );
720
721         buttonMod = gtk_button_new_with_label( _( "Modify" ) );
722         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonMod );
723
724         buttonAdd = gtk_button_new_with_label( _( "Add" ) );
725         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonAdd );
726
727         buttonClr = gtk_button_new_with_label( _( "Clear" ) );
728         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonClr );
729
730         gtk_widget_show_all(vbox);
731
732         /* Event handlers */
733         g_signal_connect( G_OBJECT(clist), "select_row",
734                           G_CALLBACK( edit_person_email_list_selected), NULL );
735         g_signal_connect( G_OBJECT(buttonUp), "clicked",
736                           G_CALLBACK( edit_person_email_move_up ), NULL );
737         g_signal_connect( G_OBJECT(buttonDown), "clicked",
738                           G_CALLBACK( edit_person_email_move_down ), NULL );
739         g_signal_connect( G_OBJECT(buttonDel), "clicked",
740                           G_CALLBACK( edit_person_email_delete ), NULL );
741         g_signal_connect( G_OBJECT(buttonMod), "clicked",
742                           G_CALLBACK( edit_person_email_modify ), NULL );
743         g_signal_connect( G_OBJECT(buttonAdd), "clicked",
744                           G_CALLBACK( edit_person_email_add ), NULL );
745         g_signal_connect( G_OBJECT(buttonClr), "clicked",
746                           G_CALLBACK( edit_person_email_clear ), NULL );
747
748         personeditdlg.clist_email   = clist;
749         personeditdlg.entry_email   = entry_email;
750         personeditdlg.entry_alias   = entry_alias;
751         personeditdlg.entry_remarks = entry_remarks;
752 }
753
754 static void addressbook_edit_person_page_attrib( gint pageNum, gchar *pageLbl ) {
755         GtkWidget *vbox;
756         GtkWidget *hbox;
757         GtkWidget *vboxl;
758         GtkWidget *vboxb;
759         GtkWidget *vbuttonbox;
760         GtkWidget *buttonDel;
761         GtkWidget *buttonMod;
762         GtkWidget *buttonAdd;
763         GtkWidget *buttonClr;
764
765         GtkWidget *table;
766         GtkWidget *label;
767         GtkWidget *clist_swin;
768         GtkWidget *clist;
769         GtkWidget *entry_name;
770         GtkWidget *entry_value;
771         gint top;
772
773         gchar *titles[ ATTRIB_N_COLS ];
774         gint i;
775
776         titles[ ATTRIB_COL_NAME  ] = _("Name");
777         titles[ ATTRIB_COL_VALUE ] = _("Value");
778
779         vbox = gtk_vbox_new( FALSE, 8 );
780         gtk_widget_show( vbox );
781         gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox );
782         gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
783
784         label = gtk_label_new( pageLbl );
785         gtk_widget_show( label );
786         gtk_notebook_set_tab_label(
787                 GTK_NOTEBOOK( personeditdlg.notebook ),
788                 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label );
789
790         /* Split into two areas */
791         hbox = gtk_hbox_new( FALSE, 0 );
792         gtk_container_add( GTK_CONTAINER( vbox ), hbox );
793
794         /* Attribute list */
795         vboxl = gtk_vbox_new( FALSE, 4 );
796         gtk_container_add( GTK_CONTAINER( hbox ), vboxl );
797         gtk_container_set_border_width( GTK_CONTAINER(vboxl), 4 );
798
799         clist_swin = gtk_scrolled_window_new( NULL, NULL );
800         gtk_container_add( GTK_CONTAINER(vboxl), clist_swin );
801         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
802                                        GTK_POLICY_AUTOMATIC,
803                                        GTK_POLICY_AUTOMATIC);
804
805         clist = gtk_clist_new_with_titles( ATTRIB_N_COLS, titles );
806         gtk_container_add( GTK_CONTAINER(clist_swin), clist );
807         gtk_clist_set_selection_mode( GTK_CLIST(clist), GTK_SELECTION_BROWSE );
808         gtk_clist_set_column_width( GTK_CLIST(clist), ATTRIB_COL_NAME, ATTRIB_COL_WIDTH_NAME );
809         gtk_clist_set_column_width( GTK_CLIST(clist), ATTRIB_COL_VALUE, ATTRIB_COL_WIDTH_VALUE );
810         gtk_clist_set_compare_func( GTK_CLIST(clist), edit_person_attrib_compare_func );
811         gtk_clist_set_auto_sort( GTK_CLIST(clist), TRUE );
812
813         for( i = 0; i < ATTRIB_N_COLS; i++ )
814                 GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button, GTK_CAN_FOCUS);
815
816         /* Data entry area */
817         table = gtk_table_new( 4, 2, FALSE);
818         gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
819         gtk_container_set_border_width( GTK_CONTAINER(table), 4 );
820         gtk_table_set_row_spacings(GTK_TABLE(table), 4);
821         gtk_table_set_col_spacings(GTK_TABLE(table), 4);
822
823         /* First row */
824         top = 0;
825         label = gtk_label_new(_("Name"));
826         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
827         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
828
829         entry_name = gtk_entry_new();
830         gtk_table_attach(GTK_TABLE(table), entry_name, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
831
832         /* Next row */
833         ++top;
834         label = gtk_label_new(_("Value"));
835         gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
836         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
837
838         entry_value = gtk_entry_new();
839         gtk_table_attach(GTK_TABLE(table), entry_value, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
840
841         /* Button box */
842         vboxb = gtk_vbox_new( FALSE, 4 );
843         gtk_box_pack_start(GTK_BOX(hbox), vboxb, FALSE, FALSE, 2);
844
845         vbuttonbox = gtk_vbutton_box_new();
846         gtk_button_box_set_layout( GTK_BUTTON_BOX(vbuttonbox), GTK_BUTTONBOX_START );
847         gtk_box_set_spacing( GTK_BOX(vbuttonbox), 8 );
848         gtk_container_set_border_width( GTK_CONTAINER(vbuttonbox), 4 );
849         gtk_container_add( GTK_CONTAINER(vboxb), vbuttonbox );
850
851         /* Buttons */
852         buttonDel = gtk_button_new_with_label( _( "Delete" ) );
853         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDel );
854
855         buttonMod = gtk_button_new_with_label( _( "Modify" ) );
856         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonMod );
857
858         buttonAdd = gtk_button_new_with_label( _( "Add" ) );
859         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonAdd );
860
861         buttonClr = gtk_button_new_with_label( _( "Clear" ) );
862         gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonClr );
863
864         gtk_widget_show_all(vbox);
865
866         /* Event handlers */
867         g_signal_connect( G_OBJECT(clist), "select_row",
868                           G_CALLBACK( edit_person_attrib_list_selected), NULL );
869         g_signal_connect( G_OBJECT(buttonDel), "clicked",
870                           G_CALLBACK( edit_person_attrib_delete ), NULL );
871         g_signal_connect( G_OBJECT(buttonMod), "clicked",
872                           G_CALLBACK( edit_person_attrib_modify ), NULL );
873         g_signal_connect( G_OBJECT(buttonAdd), "clicked",
874                           G_CALLBACK( edit_person_attrib_add ), NULL );
875         g_signal_connect( G_OBJECT(buttonClr), "clicked",
876                           G_CALLBACK( edit_person_attrib_clear ), NULL );
877
878         personeditdlg.clist_attrib  = clist;
879         personeditdlg.entry_atname  = entry_name;
880         personeditdlg.entry_atvalue = entry_value;
881 }
882
883 static void addressbook_edit_person_create( gboolean *cancelled ) {
884         addressbook_edit_person_dialog_create( cancelled );
885         addressbook_edit_person_page_basic( PAGE_BASIC, _( "Basic Data" ) );
886         addressbook_edit_person_page_email( PAGE_EMAIL, _( "E-Mail Address" ) );
887         addressbook_edit_person_page_attrib( PAGE_ATTRIBUTES, _( "User Attributes" ) );
888         gtk_widget_show_all( personeditdlg.window );
889 }
890
891 /*
892 * Return list of email items.
893 */
894 static GList *edit_person_build_email_list() {
895         GtkCList *clist = GTK_CLIST(personeditdlg.clist_email);
896         GList *listEMail = NULL;
897         ItemEMail *email;
898         gint row = 0;
899         while( (email = gtk_clist_get_row_data( clist, row )) ) {
900                 listEMail = g_list_append( listEMail, email );
901                 row++;
902         }
903         return listEMail;
904 }
905
906 /*
907 * Return list of attributes.
908 */
909 static GList *edit_person_build_attrib_list() {
910         GtkCList *clist = GTK_CLIST(personeditdlg.clist_attrib);
911         GList *listAttrib = NULL;
912         UserAttribute *attrib;
913         gint row = 0;
914         while( (attrib = gtk_clist_get_row_data( clist, row )) ) {
915                 listAttrib = g_list_append( listAttrib, attrib );
916                 row++;
917         }
918         return listAttrib;
919 }
920
921 /*
922 * Edit person.
923 * Enter: abf    Address book.
924 *        parent Parent folder for person (or NULL if adding to root folder). Argument is
925 *               only required for new objects).
926 *        person Person to edit, or NULL for a new person object.
927 *        pgMail If TRUE, E-Mail page will be activated.
928 * Return: Edited object, or NULL if cancelled.
929 */
930 ItemPerson *addressbook_edit_person( AddressBookFile *abf, ItemFolder *parent, ItemPerson *person, gboolean pgMail ) {
931         static gboolean cancelled;
932         GList *listEMail = NULL;
933         GList *listAttrib = NULL;
934         gchar *cn = NULL;
935
936         if (!personeditdlg.window)
937                 addressbook_edit_person_create(&cancelled);
938         gtk_widget_grab_focus(personeditdlg.ok_btn);
939         gtk_widget_grab_focus(personeditdlg.entry_name);
940         gtk_widget_show(personeditdlg.window);
941         manage_window_set_transient(GTK_WINDOW(personeditdlg.window));
942
943         /* Clear all fields */
944         personeditdlg.rowIndEMail = -1;
945         personeditdlg.rowIndAttrib = -1;
946         edit_person_status_show( "" );
947         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_email) );
948         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_attrib) );
949         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_name), "" );
950         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_first), "" );
951         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_last), "" );
952         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), "" );
953
954         personeditdlg.editNew = FALSE;
955         if( person ) {
956                 if( ADDRITEM_NAME(person) )
957                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_name), ADDRITEM_NAME(person) );
958                 if( person->firstName )
959                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_first), person->firstName );
960                 if( person->lastName )
961                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_last), person->lastName );
962                 if( person->nickName )
963                         gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), person->nickName );
964                 edit_person_load_email( person );
965                 edit_person_load_attrib( person );
966         }
967         else {
968                 personeditdlg.editNew = TRUE;
969         }
970
971         /* Select appropriate start page */
972         if( pgMail ) {
973                 gtk_notebook_set_current_page( GTK_NOTEBOOK(personeditdlg.notebook), PAGE_EMAIL );
974         }
975         else {
976                 gtk_notebook_set_current_page( GTK_NOTEBOOK(personeditdlg.notebook), PAGE_BASIC );
977         }
978
979         gtk_clist_select_row( GTK_CLIST(personeditdlg.clist_email), 0, 0 );
980         gtk_clist_select_row( GTK_CLIST(personeditdlg.clist_attrib), 0, 0 );
981         edit_person_email_clear( NULL );
982         if (person)
983                 edit_person_email_list_selected(GTK_CLIST(personeditdlg.clist_email), 0, 0, NULL, NULL);
984
985         edit_person_attrib_clear( NULL );
986
987         gtk_main();
988         gtk_widget_hide( personeditdlg.window );
989
990         listEMail = edit_person_build_email_list();
991         listAttrib = edit_person_build_attrib_list();
992         if( cancelled ) {
993                 addritem_free_list_email( listEMail );
994                 addritem_free_list_attribute( listAttrib );
995                 gtk_clist_clear( GTK_CLIST(personeditdlg.clist_email) );
996                 gtk_clist_clear( GTK_CLIST(personeditdlg.clist_attrib) );
997                 return NULL;
998         }
999
1000         cn = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_name), 0, -1 );
1001         if( person ) {
1002                 /* Update email/attribute list for existing person */
1003                 addrbook_update_address_list( abf, person, listEMail );
1004                 addrbook_update_attrib_list( abf, person, listAttrib );
1005         }
1006         else {
1007                 /* Create new person and email/attribute list */
1008                 if( cn == NULL || *cn == '\0' ) {
1009                         /* Wasting our time */
1010                         if( listEMail == NULL && listAttrib == NULL ) cancelled = TRUE;
1011                 }
1012                 if( ! cancelled ) {
1013                         person = addrbook_add_address_list( abf, parent, listEMail );
1014                         addrbook_add_attrib_list( abf, person, listAttrib );
1015                 }
1016         }
1017         listEMail = NULL;
1018         listAttrib = NULL;
1019
1020         if( ! cancelled ) {
1021                 /* Set person stuff */
1022                 gchar *name;
1023                 addritem_person_set_common_name( person, cn );
1024                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_first), 0, -1 );
1025                 addritem_person_set_first_name( person, name );
1026                 g_free( name );
1027                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_last), 0, -1 );
1028                 addritem_person_set_last_name( person, name );
1029                 g_free( name );
1030                 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_nick), 0, -1 );
1031                 addritem_person_set_nick_name( person, name );
1032                 g_free( name );
1033         }
1034         g_free( cn );
1035
1036         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_email) );
1037         gtk_clist_clear( GTK_CLIST(personeditdlg.clist_attrib) );
1038
1039         return person;
1040 }
1041
1042 /*
1043 * End of Source.
1044 */
1045