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