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