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