editaddress.c (43373B)
1 /* 2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client 3 * Copyright (C) 1999-2022 the Claws Mail team and Hiroyuki Yamamoto 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 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 #include "defs.h" 20 21 #include <glib.h> 22 #include <glib/gi18n.h> 23 #include <gdk/gdkkeysyms.h> 24 #include <gtk/gtk.h> 25 26 #include "alertpanel.h" 27 #include "stock_pixmap.h" 28 #include "addressbook.h" 29 #include "addressitem.h" 30 #include "addritem.h" 31 #include "addrbook.h" 32 #include "manage_window.h" 33 #include "gtkutils.h" 34 #include "filesel.h" 35 #include "codeconv.h" 36 #include "editaddress.h" 37 #include "prefs_common.h" 38 #include "menu.h" 39 #include "combobox.h" 40 #include "file-utils.h" 41 42 enum { 43 ATTRIB_COL_NAME, 44 ATTRIB_COL_VALUE, 45 ATTRIB_COL_PTR, 46 ATTRIB_N_COLS 47 }; 48 49 typedef struct _PersonEdit_dlg PersonEditDlg; 50 struct _PersonEdit_dlg { 51 GtkWidget *container; 52 GtkWidget *notebook; 53 GtkWidget *ok_btn; 54 GtkWidget *cancel_btn; 55 GtkWidget *statusbar; /* used when prefs_common.addressbook_use_editaddress_dialog is TRUE */ 56 GtkWidget *title; /* used when prefs_common.addressbook_use_editaddress_dialog is FALSE */ 57 gint status_cid; 58 59 /* User data tab */ 60 GtkWidget *image; 61 gboolean picture_set; 62 GtkWidget *entry_name; 63 GtkWidget *entry_first; 64 GtkWidget *entry_last; 65 GtkWidget *entry_nick; 66 67 /* EMail data tab */ 68 GtkWidget *entry_email; 69 GtkWidget *entry_alias; 70 GtkWidget *entry_remarks; 71 GtkWidget *view_email; 72 GtkWidget *email_up; 73 GtkWidget *email_down; 74 GtkWidget *email_del; 75 GtkWidget *email_mod; 76 GtkWidget *email_add; 77 78 gboolean editNew; 79 gboolean read_only; 80 }; 81 82 /* transient data */ 83 static struct _PersonEdit_dlg personeditdlg; 84 static AddressBookFile *current_abf = NULL; 85 static ItemPerson *current_person = NULL; 86 static ItemFolder *current_parent_folder = NULL; 87 static EditAddressPostUpdateCallback edit_person_close_post_update_cb = NULL; 88 89 typedef enum { 90 EMAIL_COL_EMAIL, 91 EMAIL_COL_ALIAS, 92 EMAIL_COL_REMARKS, 93 EMAIL_COL_PTR 94 } PersonEditEMailColumnPos; 95 96 #define EDITPERSON_WIDTH 520 97 #define EDITPERSON_HEIGHT 320 98 99 #define EMAIL_N_COLS 4 100 #define EMAIL_COL_WIDTH_EMAIL 180 101 #define EMAIL_COL_WIDTH_ALIAS 80 102 103 #define ATTRIB_COL_WIDTH_NAME 240 104 #define ATTRIB_COL_WIDTH_VALUE 0 105 106 #define PAGE_BASIC 0 107 #define PAGE_EMAIL 1 108 109 static gboolean addressbook_edit_person_close( gboolean cancelled ); 110 static GList *edit_person_build_email_list(); 111 112 static gchar* edit_person_get_common_name_from_widgets(void) 113 { 114 gchar *cn = NULL; /* cn must be freed by caller */ 115 116 { 117 cn = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_name), 0, -1 ); 118 if ( cn == NULL || *cn == '\0' ) { 119 gchar *first = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_first), 0, -1 ); 120 gchar *last = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_last), 0, -1 ); 121 cn = g_strdup_printf("%s%s%s", first?first:"", (first && last && *first && *last)?" ":"", last?last:""); 122 g_free(first); 123 g_free(last); 124 } 125 if ( cn == NULL || *cn == '\0' ) { 126 g_free(cn); 127 cn = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_nick), 0, -1 ); 128 } 129 } 130 if ( cn != NULL ) 131 g_strstrip(cn); 132 return cn; 133 } 134 135 static void edit_person_status_show( gchar *msg ) { 136 if( personeditdlg.statusbar != NULL ) { 137 gtk_statusbar_pop( GTK_STATUSBAR(personeditdlg.statusbar), personeditdlg.status_cid ); 138 if( msg ) { 139 gtk_statusbar_push( GTK_STATUSBAR(personeditdlg.statusbar), personeditdlg.status_cid, msg ); 140 } 141 } 142 } 143 144 static void edit_person_cancel(GtkWidget *widget, gboolean *cancelled) { 145 *cancelled = TRUE; 146 if (prefs_common.addressbook_use_editaddress_dialog) 147 gtk_main_quit(); 148 else 149 addressbook_edit_person_close( *cancelled ); 150 } 151 152 static void edit_person_ok(GtkWidget *widget, gboolean *cancelled) { 153 GList *listEMail = edit_person_build_email_list(); 154 gchar *cn = edit_person_get_common_name_from_widgets(); 155 156 if( (cn == NULL || *cn == '\0') && listEMail == NULL) { 157 gint val; 158 159 val = alertpanel( _("Add New Person"), 160 _("Adding a new person requires at least one of the\n" 161 "following values to be set:\n" 162 " - Display Name\n" 163 " - First Name\n" 164 " - Last Name\n" 165 " - Nickname\n" 166 " - any email address\n" 167 " - any additional attribute\n\n" 168 "Click OK to keep editing this contact.\n" 169 "Click Cancel to close without saving."), 170 NULL, _("_Cancel"), NULL, _("_OK"), NULL, NULL, ALERTFOCUS_SECOND ); 171 if( val == G_ALERTDEFAULT ) { 172 edit_person_cancel(widget, cancelled); 173 } 174 g_free( cn ); 175 return; 176 } 177 g_free( cn ); 178 179 *cancelled = FALSE; 180 if (prefs_common.addressbook_use_editaddress_dialog) 181 gtk_main_quit(); 182 else 183 addressbook_edit_person_close( *cancelled ); 184 } 185 186 /* Updated up/down buttons sensitivity, depending on list 187 * cursor position */ 188 static void edit_person_email_update_buttons() 189 { 190 GtkTreeModel *model; 191 GtkTreeIter iter, otheriter; 192 GtkTreePath *path; 193 gboolean has_prev; 194 ItemEMail *email; 195 196 email = gtkut_tree_view_get_selected_pointer( 197 GTK_TREE_VIEW(personeditdlg.view_email), EMAIL_COL_PTR, 198 &model, NULL, &iter); 199 200 if (email) { 201 if (!personeditdlg.read_only) { 202 otheriter = iter; 203 path = gtk_tree_model_get_path(model, &otheriter); 204 has_prev = gtk_tree_path_prev(path); 205 if (has_prev) { 206 gtk_tree_model_get_iter(model, &otheriter, path); 207 } 208 gtk_widget_set_sensitive(personeditdlg.email_up, has_prev); 209 210 otheriter = iter; 211 gtk_widget_set_sensitive(personeditdlg.email_down, 212 gtk_tree_model_iter_next(model, &otheriter)); 213 } 214 } else { 215 gtk_widget_set_sensitive(personeditdlg.email_del, FALSE); 216 gtk_widget_set_sensitive(personeditdlg.email_up, FALSE); 217 gtk_widget_set_sensitive(personeditdlg.email_down, FALSE); 218 } 219 } 220 221 static void edit_person_email_cursor_changed(GtkTreeView *view, 222 gpointer user_data) 223 { 224 GtkTreeModel *model; 225 GtkTreeIter iter; 226 ItemEMail *email; 227 228 email = gtkut_tree_view_get_selected_pointer( 229 GTK_TREE_VIEW(personeditdlg.view_email), EMAIL_COL_PTR, 230 &model, NULL, &iter); 231 232 if (email != NULL) { 233 if (email->address != NULL) 234 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_email), 235 email->address); 236 if (ADDRITEM_NAME(email) != NULL) 237 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_alias), 238 ADDRITEM_NAME(email)); 239 if (email->remarks != NULL) 240 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_remarks), 241 email->remarks); 242 } 243 244 edit_person_email_update_buttons(); 245 } 246 247 248 static gint edit_person_delete_event(GtkWidget *widget, GdkEventAny *event, gboolean *cancelled) { 249 *cancelled = TRUE; 250 if (prefs_common.addressbook_use_editaddress_dialog) 251 gtk_main_quit(); 252 else 253 addressbook_edit_person_close( *cancelled ); 254 return TRUE; 255 } 256 257 static gchar *_title_new_ = NULL; 258 static gchar *_title_edit_ = NULL; 259 260 static void edit_person_set_widgets_title( gchar *text ) 261 { 262 gchar *label = NULL; 263 264 cm_return_if_fail( text != NULL ); 265 266 gtk_label_set_text(GTK_LABEL(personeditdlg.title), ""); 267 label = g_markup_printf_escaped("<b>%s</b>", text); 268 gtk_label_set_markup(GTK_LABEL(personeditdlg.title), label); 269 g_free(label); 270 } 271 272 static void edit_person_set_window_title( gint pageNum ) { 273 gchar *sTitle; 274 275 if( _title_new_ == NULL ) { 276 _title_new_ = g_strdup( _("Add New Person") ); 277 _title_edit_ = g_strdup( _("Edit Person Details") ); 278 } 279 280 if( pageNum == PAGE_BASIC ) { 281 if( personeditdlg.editNew ) { 282 if (prefs_common.addressbook_use_editaddress_dialog) 283 gtk_window_set_title( GTK_WINDOW(personeditdlg.container), _title_new_ ); 284 else 285 edit_person_set_widgets_title( _title_new_ ); 286 } 287 else { 288 if (prefs_common.addressbook_use_editaddress_dialog) 289 gtk_window_set_title( GTK_WINDOW(personeditdlg.container), _title_edit_ ); 290 else 291 edit_person_set_widgets_title( _title_edit_ ); 292 } 293 } 294 else { 295 if( personeditdlg.entry_name == NULL ) { 296 sTitle = g_strdup( _title_edit_ ); 297 } 298 else { 299 gchar *name; 300 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_name), 0, -1 ); 301 g_strstrip(name); 302 if ( *name != '\0' ) 303 sTitle = g_strdup_printf( "%s - %s", _title_edit_, name ); 304 else 305 sTitle = g_strdup( _title_edit_ ); 306 g_free( name ); 307 } 308 if (prefs_common.addressbook_use_editaddress_dialog) 309 gtk_window_set_title( GTK_WINDOW(personeditdlg.container), sTitle ); 310 else 311 edit_person_set_widgets_title( sTitle ); 312 g_free( sTitle ); 313 } 314 } 315 316 static void edit_person_email_clear( gpointer data ) { 317 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_email), "" ); 318 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_alias), "" ); 319 gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_remarks), "" ); 320 } 321 322 static void edit_person_switch_page( GtkNotebook *notebook, gpointer page, 323 gint pageNum, gpointer user_data) 324 { 325 edit_person_set_window_title( pageNum ); 326 edit_person_status_show( "" ); 327 } 328 329 /* 330 * Load clist with a copy of person's email addresses. 331 */ 332 static void edit_person_load_email( ItemPerson *person ) { 333 GList *node = person->listEMail; 334 GtkTreeModel *model = gtk_tree_view_get_model( 335 GTK_TREE_VIEW(personeditdlg.view_email)); 336 GtkTreeIter iter; 337 338 while( node ) { 339 ItemEMail *emorig = ( ItemEMail * ) node->data; 340 ItemEMail *email = addritem_copyfull_item_email( emorig ); 341 342 gtk_list_store_append(GTK_LIST_STORE(model), &iter); 343 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 344 EMAIL_COL_EMAIL, email->address, 345 EMAIL_COL_ALIAS, email->obj.name, 346 EMAIL_COL_REMARKS, email->remarks, 347 EMAIL_COL_PTR, email, 348 -1); 349 350 node = g_list_next( node ); 351 } 352 } 353 354 static void edit_person_email_move_up( gpointer data ) { 355 GtkTreeModel *model; 356 GtkTreeIter iter, otheriter; 357 GtkTreePath *path; 358 ItemEMail *email; 359 gboolean has_prev; 360 361 edit_person_email_clear( NULL ); 362 edit_person_status_show( NULL ); 363 364 email = gtkut_tree_view_get_selected_pointer( 365 GTK_TREE_VIEW(personeditdlg.view_email), EMAIL_COL_PTR, 366 &model, NULL, &iter); 367 368 if( email ) { 369 otheriter = iter; 370 /* GTK+2 does not have gtk_tree_model_iter_previous(), so 371 * we have to go through GtkTreePath */ 372 path = gtk_tree_model_get_path(model, &otheriter); 373 has_prev = gtk_tree_path_prev(path); 374 if (has_prev) { 375 gtk_tree_model_get_iter(model, &otheriter, path); 376 gtk_list_store_move_before(GTK_LIST_STORE(model), &iter, &otheriter); 377 } 378 gtk_tree_path_free(path); 379 } 380 381 edit_person_email_update_buttons(); 382 } 383 384 static void edit_person_email_move_down( gpointer data ) { 385 GtkTreeModel *model; 386 GtkTreeIter iter, otheriter; 387 ItemEMail *email; 388 389 edit_person_email_clear( NULL ); 390 edit_person_status_show( NULL ); 391 392 email = gtkut_tree_view_get_selected_pointer( 393 GTK_TREE_VIEW(personeditdlg.view_email), EMAIL_COL_PTR, 394 &model, NULL, &iter); 395 396 if( email ) { 397 otheriter = iter; 398 if (gtk_tree_model_iter_next(model, &otheriter)) { 399 gtk_list_store_move_after(GTK_LIST_STORE(model), &iter, &otheriter); 400 } 401 } 402 403 edit_person_email_update_buttons(); 404 } 405 406 static void edit_person_email_delete( gpointer data ) { 407 GtkTreeModel *model; 408 GtkTreeIter iter; 409 GtkTreeSelection *sel; 410 ItemEMail *email; 411 gboolean has_row = FALSE; 412 gint n; 413 414 edit_person_email_clear( NULL ); 415 edit_person_status_show( NULL ); 416 417 email = gtkut_tree_view_get_selected_pointer( 418 GTK_TREE_VIEW(personeditdlg.view_email), EMAIL_COL_PTR, 419 &model, &sel, &iter); 420 421 if( email ) { 422 /* Remove list entry and set iter to next row, if any */ 423 has_row = gtk_list_store_remove(GTK_LIST_STORE(model), &iter); 424 addritem_free_item_email( email ); 425 email = NULL; 426 } 427 428 /* Position hilite bar */ 429 if (!has_row) { 430 /* The removed row was the last in the list, so iter is not 431 * valid. Find out if there is at least one row remaining 432 * in the list, and select the last one if so. */ 433 n = gtk_tree_model_iter_n_children(model, NULL); 434 if (n > 0 && gtk_tree_model_iter_nth_child(model, &iter, NULL, n-1)) { 435 /* It exists */ 436 has_row = TRUE; 437 } 438 } 439 440 if (has_row) 441 gtk_tree_selection_select_iter(sel, &iter); 442 443 edit_person_email_cursor_changed( 444 GTK_TREE_VIEW(personeditdlg.view_email), NULL); 445 } 446 447 static ItemEMail *edit_person_email_edit( gboolean *error, ItemEMail *email ) { 448 ItemEMail *retVal = NULL; 449 gchar *sEmail, *sAlias, *sRemarks; 450 451 *error = TRUE; 452 sAlias = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_alias), 0, -1 ); 453 sRemarks = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_remarks), 0, -1 ); 454 455 sEmail = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_email), 0, -1 ); 456 g_strstrip(sEmail); 457 if (sEmail) { 458 if( email == NULL ) { 459 email = addritem_create_item_email(); 460 } 461 addritem_email_set_address( email, sEmail ); 462 addritem_email_set_alias( email, sAlias ); 463 addritem_email_set_remarks( email, sRemarks ); 464 retVal = email; 465 *error = FALSE; 466 } 467 else { 468 edit_person_status_show( _( "An Email address must be supplied." ) ); 469 } 470 471 g_free( sEmail ); 472 g_free( sAlias ); 473 g_free( sRemarks ); 474 475 return retVal; 476 } 477 478 static void edit_person_email_modify( gpointer data ) { 479 GtkTreeModel *model; 480 GtkTreeIter iter; 481 gboolean errFlg = FALSE; 482 ItemEMail *email; 483 484 email = gtkut_tree_view_get_selected_pointer( 485 GTK_TREE_VIEW(personeditdlg.view_email), EMAIL_COL_PTR, 486 &model, NULL, &iter); 487 488 if( email ) { 489 edit_person_email_edit( &errFlg, email ); 490 if( ! errFlg ) { 491 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 492 EMAIL_COL_EMAIL, email->address, 493 EMAIL_COL_ALIAS, email->obj.name, 494 EMAIL_COL_REMARKS, email->remarks, 495 -1); 496 edit_person_email_clear( NULL ); 497 } 498 } 499 } 500 501 static void edit_person_email_add( gpointer data ) { 502 GtkTreeModel *model; 503 GtkTreeIter iter, otheriter; 504 GtkTreeSelection *sel; 505 gboolean errFlg = FALSE, prev_exists = FALSE; 506 ItemEMail *email = NULL; 507 508 email = gtkut_tree_view_get_selected_pointer( 509 GTK_TREE_VIEW(personeditdlg.view_email), EMAIL_COL_PTR, 510 &model, &sel, &otheriter); 511 if (email != NULL) 512 prev_exists = TRUE; 513 514 email = edit_person_email_edit( &errFlg, NULL ); 515 if( ! errFlg ) { 516 if (prev_exists) 517 gtk_list_store_insert_after(GTK_LIST_STORE(model), &iter, &otheriter); 518 else /* list is empty */ 519 gtk_list_store_append(GTK_LIST_STORE(model), &iter); 520 521 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 522 EMAIL_COL_EMAIL, email->address, 523 EMAIL_COL_ALIAS, email->obj.name, 524 EMAIL_COL_REMARKS, email->remarks, 525 EMAIL_COL_PTR, email, 526 -1); 527 gtk_tree_selection_select_iter(sel, &iter); 528 edit_person_email_update_buttons(); 529 530 edit_person_email_clear( NULL ); 531 } 532 } 533 534 static gboolean list_find_email(const gchar *addr) 535 { 536 GtkWidget *view = personeditdlg.view_email; 537 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); 538 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); 539 GtkTreeIter iter; 540 ItemEMail *email; 541 542 if (!gtk_tree_model_get_iter_first(model, &iter)) 543 return FALSE; 544 545 do { 546 gtk_tree_model_get(model, &iter, EMAIL_COL_PTR, &email, -1); 547 if (!g_ascii_strcasecmp(email->address, addr)) { 548 gtk_tree_selection_select_iter(sel, &iter); 549 return TRUE; 550 } 551 } while (gtk_tree_model_iter_next(model, &iter)); 552 553 return FALSE; 554 } 555 556 /*! 557 *\brief Save Gtk object size to prefs dataset 558 */ 559 static void edit_person_size_allocate_cb(GtkWidget *widget, 560 GtkAllocation *allocation) 561 { 562 cm_return_if_fail(allocation != NULL); 563 564 gtk_window_get_size(GTK_WINDOW(widget), 565 &prefs_common.addressbookeditpersonwin_width, &prefs_common.addressbookeditpersonwin_height); 566 } 567 568 /* build edit person widgets, return a pointer to the main container of the widgetset (a vbox) */ 569 static GtkWidget* addressbook_edit_person_widgets_create( GtkWidget* container, gboolean *cancelled ) 570 { 571 GtkWidget *vbox; 572 GtkWidget *vnbox; 573 GtkWidget *notebook; 574 GtkWidget *hbbox; 575 GtkWidget *ok_btn; 576 GtkWidget *cancel_btn; 577 578 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4); 579 gtk_container_set_border_width(GTK_CONTAINER(vbox), BORDER_WIDTH); 580 gtk_widget_show(vbox); 581 gtk_container_add(GTK_CONTAINER(container), vbox); 582 583 vnbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4); 584 gtk_container_set_border_width(GTK_CONTAINER(vnbox), 4); 585 gtk_widget_show(vnbox); 586 gtk_box_pack_start(GTK_BOX(vbox), vnbox, TRUE, TRUE, 0); 587 588 /* Notebook */ 589 notebook = gtk_notebook_new(); 590 gtk_widget_show(notebook); 591 gtk_box_pack_start(GTK_BOX(vnbox), notebook, TRUE, TRUE, 0); 592 gtk_container_set_border_width(GTK_CONTAINER(notebook), 6); 593 594 /* Button panel */ 595 if (prefs_common.addressbook_use_editaddress_dialog) 596 gtkut_stock_button_set_create(&hbbox, &cancel_btn, NULL, _("_Cancel"), 597 &ok_btn, NULL, _("_OK"), 598 NULL, NULL, NULL); 599 else 600 gtkut_stock_with_text_button_set_create(&hbbox, 601 &cancel_btn, NULL, _("Discard"), 602 &ok_btn, NULL, _("Apply"), 603 NULL, NULL, NULL); 604 gtk_box_pack_end(GTK_BOX(vnbox), hbbox, FALSE, FALSE, 0); 605 gtk_widget_grab_default(ok_btn); 606 607 g_signal_connect(G_OBJECT(ok_btn), "clicked", 608 G_CALLBACK(edit_person_ok), cancelled); 609 g_signal_connect(G_OBJECT(cancel_btn), "clicked", 610 G_CALLBACK(edit_person_cancel), cancelled); 611 g_signal_connect(G_OBJECT(notebook), "switch_page", 612 G_CALLBACK(edit_person_switch_page), NULL ); 613 614 gtk_widget_show_all(vbox); 615 616 personeditdlg.notebook = notebook; 617 personeditdlg.ok_btn = ok_btn; 618 personeditdlg.cancel_btn = cancel_btn; 619 620 return vbox; 621 } 622 623 static void addressbook_edit_person_dialog_create( gboolean *cancelled ) { 624 GtkWidget *window; 625 GtkWidget *hsbox; 626 GtkWidget *vbox; 627 GtkWidget *statusbar; 628 static GdkGeometry geometry; 629 630 window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "editaddress"); 631 /* gtk_container_set_border_width(GTK_CONTAINER(window), 0); */ 632 gtk_window_set_title(GTK_WINDOW(window), _("Edit Person Data")); 633 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); 634 gtk_window_set_modal(GTK_WINDOW(window), TRUE); 635 gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); 636 g_signal_connect(G_OBJECT(window), "delete_event", 637 G_CALLBACK(edit_person_delete_event), 638 cancelled); 639 g_signal_connect(G_OBJECT(window), "size_allocate", 640 G_CALLBACK(edit_person_size_allocate_cb), 641 cancelled); 642 643 vbox = addressbook_edit_person_widgets_create(window, cancelled); 644 645 /* Status line */ 646 hsbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); 647 gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, BORDER_WIDTH); 648 statusbar = gtk_statusbar_new(); 649 gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, BORDER_WIDTH); 650 651 if (!geometry.min_height) { 652 geometry.min_width = EDITPERSON_WIDTH; 653 geometry.min_height = EDITPERSON_HEIGHT; 654 } 655 656 gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry, 657 GDK_HINT_MIN_SIZE); 658 gtk_window_set_default_size(GTK_WINDOW(window), 659 prefs_common.addressbookeditpersonwin_width, 660 prefs_common.addressbookeditpersonwin_height); 661 662 personeditdlg.container = window; 663 personeditdlg.statusbar = statusbar; 664 personeditdlg.status_cid = gtk_statusbar_get_context_id( GTK_STATUSBAR(statusbar), "Edit Person Dialog" ); 665 666 } 667 668 /* parent must be a box */ 669 static void addressbook_edit_person_widgetset_create( GtkWidget *parent, gboolean *cancelled ) 670 { 671 GtkWidget *vbox; 672 GtkWidget *label; 673 674 if ( parent == NULL ) 675 g_warning("addressbook_edit_person_widgetset_create: parent is NULL"); 676 677 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); 678 gtk_box_pack_end(GTK_BOX(parent), vbox, TRUE, TRUE, 0); 679 680 label = gtk_label_new(_("Edit Person Data")); 681 gtk_label_set_justify( GTK_LABEL(label), GTK_JUSTIFY_CENTER); 682 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); 683 684 addressbook_edit_person_widgets_create(vbox, cancelled); 685 686 gtk_widget_set_size_request(vbox, EDITPERSON_WIDTH, EDITPERSON_HEIGHT); 687 688 personeditdlg.container = vbox; 689 personeditdlg.title = label; 690 personeditdlg.statusbar = NULL; 691 personeditdlg.status_cid = 0; 692 } 693 694 void addressbook_edit_person_widgetset_hide( void ) 695 { 696 if ( personeditdlg.container ) 697 gtk_widget_hide( personeditdlg.container ); 698 } 699 700 static void addressbook_edit_person_set_picture(void) 701 { 702 GError *error = NULL; 703 gchar *filename; 704 int width, height, scalewidth, scaleheight; 705 706 if ( (filename = filesel_select_file_open(_("Choose a picture"), NULL)) ) { 707 GdkPixbuf *pixbuf = NULL; 708 gdk_pixbuf_get_file_info(filename, &width, &height); 709 710 if ( width > 128 || height > 128 ) { 711 if (width > height) { 712 scaleheight = (height * 128) / width; 713 scalewidth = 128; 714 } 715 else { 716 scalewidth = (width * 128) / height; 717 scaleheight = 128; 718 } 719 pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, 720 scalewidth, scaleheight, TRUE, &error); 721 } else { 722 pixbuf = gdk_pixbuf_new_from_file(filename, &error); 723 } 724 if (error) { 725 alertpanel_error(_("Failed to import image: \n%s"), 726 error->message); 727 g_error_free(error); 728 error = NULL; 729 /* keep the previous picture if any */ 730 g_free(filename); 731 if (pixbuf) 732 g_object_unref(pixbuf); 733 return; 734 } 735 personeditdlg.picture_set = TRUE; 736 cm_menu_set_sensitive("EditAddressPopup/UnsetPicture", personeditdlg.picture_set); 737 g_free(filename); 738 gtk_image_set_from_pixbuf(GTK_IMAGE(personeditdlg.image), pixbuf); 739 g_object_unref(pixbuf); 740 } 741 } 742 743 static void addressbook_edit_person_clear_picture(void) 744 { 745 GdkPixbuf *pixbuf; 746 747 stock_pixbuf_gdk(STOCK_PIXMAP_ANONYMOUS, &pixbuf); 748 personeditdlg.picture_set = FALSE; 749 cm_menu_set_sensitive("EditAddressPopup/UnsetPicture", personeditdlg.picture_set); 750 gtk_image_set_from_pixbuf(GTK_IMAGE(personeditdlg.image), pixbuf); 751 } 752 753 static void addressbook_edit_person_set_picture_menu_cb (GtkAction *action, gpointer data) 754 { 755 addressbook_edit_person_set_picture(); 756 } 757 758 static void addressbook_edit_person_unset_picture_menu_cb (GtkAction *action, gpointer data) 759 { 760 addressbook_edit_person_clear_picture(); 761 } 762 763 static GtkWidget *editaddr_popup_menu = NULL; 764 static GtkActionEntry editaddr_popup_entries[] = 765 { 766 {"EditAddressPopup", NULL, "EditAddressPopup", NULL, NULL, NULL }, 767 {"EditAddressPopup/SetPicture", NULL, N_("_Set picture"), NULL, NULL, G_CALLBACK(addressbook_edit_person_set_picture_menu_cb) }, 768 {"EditAddressPopup/UnsetPicture", NULL, N_("_Unset picture"), NULL, NULL, G_CALLBACK(addressbook_edit_person_unset_picture_menu_cb) }, 769 }; 770 771 static void addressbook_edit_person_set_picture_cb(GtkWidget *widget, 772 GdkEventButton *event, gpointer data) 773 { 774 if (event->button == 1) { 775 addressbook_edit_person_set_picture(); 776 } else { 777 gtk_menu_popup_at_pointer(GTK_MENU(editaddr_popup_menu), NULL); 778 } 779 } 780 781 static gboolean addressbook_edit_person_picture_popup_menu(GtkWidget *widget, gpointer data) 782 { 783 GdkEventButton event; 784 785 event.button = 3; 786 event.time = gtk_get_current_event_time(); 787 788 addressbook_edit_person_set_picture_cb(NULL, &event, data); 789 790 return TRUE; 791 } 792 793 static void addressbook_edit_person_page_basic( gint pageNum, gchar *pageLbl ) { 794 GtkWidget *vbox; 795 GtkWidget *hbox; 796 GtkWidget *table; 797 GtkWidget *label; 798 GtkWidget *ebox_picture; 799 GtkWidget *frame_picture; 800 GtkWidget *entry_name; 801 GtkWidget *entry_fn; 802 GtkWidget *entry_ln; 803 GtkWidget *entry_nn; 804 const gchar *locale; 805 gint top = 0; 806 807 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 20 ); 808 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8 ); 809 810 gtk_widget_show( vbox ); 811 812 if (!editaddr_popup_menu) { 813 cm_menu_create_action_group("EditAddressPopup", editaddr_popup_entries, 814 G_N_ELEMENTS(editaddr_popup_entries), (gpointer)NULL); 815 MENUITEM_ADDUI("/Menus", "EditAddressPopup", "EditAddressPopup", GTK_UI_MANAGER_MENU) 816 MENUITEM_ADDUI("/Menus/EditAddressPopup", "SetPicture", "EditAddressPopup/SetPicture", GTK_UI_MANAGER_MENUITEM) 817 MENUITEM_ADDUI("/Menus/EditAddressPopup", "UnsetPicture", "EditAddressPopup/UnsetPicture", GTK_UI_MANAGER_MENUITEM) 818 819 editaddr_popup_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM( 820 gtk_ui_manager_get_widget(gtkut_ui_manager(), "/Menus/EditAddressPopup")) ); 821 } 822 /* User's picture */ 823 ebox_picture = gtk_event_box_new(); 824 frame_picture = gtk_frame_new(_("Photo")); 825 826 /* Room for a photo */ 827 personeditdlg.image = gtk_image_new(); 828 addressbook_edit_person_clear_picture(); 829 830 gtk_container_add(GTK_CONTAINER(ebox_picture), personeditdlg.image); 831 gtk_container_add(GTK_CONTAINER(frame_picture), ebox_picture); 832 gtk_container_add(GTK_CONTAINER( personeditdlg.notebook ), hbox ); 833 gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH ); 834 gtk_container_set_border_width( GTK_CONTAINER (hbox), BORDER_WIDTH ); 835 836 label = gtk_label_new_with_mnemonic( pageLbl ); 837 gtk_widget_show( label ); 838 839 gtk_box_pack_start(GTK_BOX(hbox), frame_picture, TRUE, TRUE, 0); 840 841 gtk_notebook_set_tab_label( 842 GTK_NOTEBOOK( personeditdlg.notebook ), 843 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label ); 844 845 g_signal_connect(G_OBJECT(ebox_picture), "popup-menu", 846 G_CALLBACK(addressbook_edit_person_picture_popup_menu), NULL); 847 g_signal_connect(G_OBJECT(ebox_picture), "button_press_event", 848 G_CALLBACK(addressbook_edit_person_set_picture_cb), NULL); 849 850 table = gtk_grid_new(); 851 852 #define ATTACH_ROW(text, entry) \ 853 { \ 854 label = gtk_label_new(text); \ 855 gtk_grid_attach(GTK_GRID(table), label, 0, top, 1, 1); \ 856 gtk_label_set_xalign(GTK_LABEL(label), 0.0); \ 857 \ 858 entry = gtk_entry_new(); \ 859 gtk_grid_attach(GTK_GRID(table), entry, 1, top, 1, 1); \ 860 gtk_widget_set_hexpand(entry, TRUE); \ 861 gtk_widget_set_halign(entry, GTK_ALIGN_FILL); \ 862 top++; \ 863 } 864 865 #define ATTACH_HIDDEN_ROW(text, entry) \ 866 { \ 867 entry = gtk_entry_new(); \ 868 } 869 870 ATTACH_ROW(_("Display Name"), entry_name); 871 locale = conv_get_current_locale(); 872 if (locale && 873 (!g_ascii_strncasecmp(locale, "hu", 2) || 874 !g_ascii_strncasecmp(locale, "ja", 2) || 875 !g_ascii_strncasecmp(locale, "ko", 2) || 876 !g_ascii_strncasecmp(locale, "vi", 2) || 877 !g_ascii_strncasecmp(locale, "zh", 2))) { 878 ATTACH_ROW(_("Last Name"), entry_ln); 879 ATTACH_ROW(_("First Name"), entry_fn); 880 } else { 881 ATTACH_ROW(_("First Name"), entry_fn); 882 ATTACH_ROW(_("Last Name"), entry_ln); 883 } 884 ATTACH_ROW(_("Nickname"), entry_nn); 885 #undef ATTACH_ROW 886 #undef ATTACH_HIDDEN_ROW 887 gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0); 888 gtk_box_pack_end(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); 889 gtk_container_set_border_width( GTK_CONTAINER(table), 8 ); 890 gtk_grid_set_row_spacing(GTK_GRID(table), 15); 891 gtk_grid_set_column_spacing(GTK_GRID(table), 8); 892 893 gtk_widget_show_all(vbox); 894 personeditdlg.entry_name = entry_name; 895 personeditdlg.entry_first = entry_fn; 896 personeditdlg.entry_last = entry_ln; 897 personeditdlg.entry_nick = entry_nn; 898 } 899 900 static gboolean email_adding = FALSE, email_saving = FALSE; 901 902 static void edit_person_entry_email_changed (GtkWidget *entry, gpointer data) 903 { 904 GtkTreeModel *model = gtk_tree_view_get_model( 905 GTK_TREE_VIEW(personeditdlg.view_email)); 906 gboolean non_empty = (gtk_tree_model_iter_n_children(model, NULL) > 0); 907 908 if (personeditdlg.read_only) 909 return; 910 911 if (gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email)) == NULL 912 || strlen(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email))) == 0) { 913 gtk_widget_set_sensitive(personeditdlg.email_add,FALSE); 914 gtk_widget_set_sensitive(personeditdlg.email_mod,FALSE); 915 email_adding = FALSE; 916 email_saving = FALSE; 917 } else if (list_find_email(gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_email)))) { 918 gtk_widget_set_sensitive(personeditdlg.email_add,FALSE); 919 gtk_widget_set_sensitive(personeditdlg.email_mod,non_empty); 920 email_adding = FALSE; 921 email_saving = non_empty; 922 } else { 923 gtk_widget_set_sensitive(personeditdlg.email_add,TRUE); 924 gtk_widget_set_sensitive(personeditdlg.email_mod,non_empty); 925 email_adding = TRUE; 926 email_saving = non_empty; 927 } 928 } 929 930 static gboolean edit_person_entry_email_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data) 931 { 932 if (event && (event->keyval == GDK_KEY_KP_Enter || 933 event->keyval == GDK_KEY_Return)) { 934 if (email_saving) 935 edit_person_email_modify(NULL); 936 else if (email_adding) 937 edit_person_email_add(NULL); 938 } 939 return FALSE; 940 } 941 942 943 static void addressbook_edit_person_page_email( gint pageNum, gchar *pageLbl ) { 944 GtkWidget *vbox; 945 GtkWidget *hbox; 946 GtkWidget *vboxl; 947 GtkWidget *vboxb; 948 GtkWidget *vbuttonbox; 949 GtkWidget *buttonUp; 950 GtkWidget *buttonDown; 951 GtkWidget *buttonDel; 952 GtkWidget *buttonMod; 953 GtkWidget *buttonAdd; 954 955 GtkWidget *table; 956 GtkWidget *label; 957 GtkWidget *scrollwin; 958 GtkWidget *view; 959 GtkWidget *entry_email; 960 GtkWidget *entry_alias; 961 GtkWidget *entry_remarks; 962 GtkListStore *store; 963 GtkTreeViewColumn *col; 964 GtkCellRenderer *rdr; 965 GtkTreeSelection *sel; 966 967 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8 ); 968 gtk_widget_show( vbox ); 969 gtk_container_add( GTK_CONTAINER( personeditdlg.notebook ), vbox ); 970 gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH ); 971 972 label = gtk_label_new_with_mnemonic( pageLbl ); 973 gtk_widget_show( label ); 974 gtk_notebook_set_tab_label( 975 GTK_NOTEBOOK( personeditdlg.notebook ), 976 gtk_notebook_get_nth_page( GTK_NOTEBOOK( personeditdlg.notebook ), pageNum ), label ); 977 978 /* Split into two areas */ 979 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0 ); 980 gtk_container_add( GTK_CONTAINER( vbox ), hbox ); 981 982 /* Address list */ 983 vboxl = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4 ); 984 gtk_container_add( GTK_CONTAINER( hbox ), vboxl ); 985 gtk_container_set_border_width( GTK_CONTAINER(vboxl), 4 ); 986 987 scrollwin = gtk_scrolled_window_new( NULL, NULL ); 988 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), 989 GTK_POLICY_AUTOMATIC, 990 GTK_POLICY_AUTOMATIC); 991 gtk_scrolled_window_set_propagate_natural_height(GTK_SCROLLED_WINDOW(scrollwin), TRUE); 992 993 store = gtk_list_store_new(EMAIL_N_COLS, 994 G_TYPE_STRING, 995 G_TYPE_STRING, 996 G_TYPE_STRING, 997 G_TYPE_POINTER, 998 -1); 999 1000 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); 1001 g_object_unref(store); 1002 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), TRUE); 1003 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); 1004 gtk_tree_selection_set_mode(sel, GTK_SELECTION_BROWSE); 1005 1006 rdr = gtk_cell_renderer_text_new(); 1007 col = gtk_tree_view_column_new_with_attributes(_("Email Address"), rdr, 1008 "markup", EMAIL_COL_EMAIL, NULL); 1009 gtk_tree_view_column_set_min_width(col, EMAIL_COL_WIDTH_EMAIL); 1010 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); 1011 1012 col = gtk_tree_view_column_new_with_attributes(_("Alias"), rdr, 1013 "markup", EMAIL_COL_ALIAS, NULL); 1014 gtk_tree_view_column_set_min_width(col, EMAIL_COL_WIDTH_ALIAS); 1015 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); 1016 1017 col = gtk_tree_view_column_new_with_attributes(_("Remarks"), rdr, 1018 "markup", EMAIL_COL_REMARKS, NULL); 1019 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); 1020 1021 gtk_container_add( GTK_CONTAINER(scrollwin), view ); 1022 1023 /* Data entry area */ 1024 table = gtk_grid_new(); 1025 1026 gtk_container_add( GTK_CONTAINER(vboxl), scrollwin ); 1027 gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0); 1028 gtk_container_set_border_width( GTK_CONTAINER(table), 4 ); 1029 gtk_grid_set_row_spacing(GTK_GRID(table), 4); 1030 gtk_grid_set_column_spacing(GTK_GRID(table), 4); 1031 1032 entry_email = gtk_entry_new(); 1033 entry_alias = gtk_entry_new(); 1034 entry_remarks = gtk_entry_new(); 1035 1036 /* First row */ 1037 label = gtk_label_new(_("Email Address")); 1038 gtk_label_set_xalign(GTK_LABEL(label), 0.0); 1039 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1); 1040 1041 gtk_grid_attach(GTK_GRID(table), entry_email, 1, 0, 1, 1); 1042 gtk_widget_set_hexpand(entry_email, TRUE); 1043 gtk_widget_set_halign(entry_email, GTK_ALIGN_FILL); 1044 1045 /* Next row */ 1046 label = gtk_label_new(_("Alias")); 1047 gtk_label_set_xalign(GTK_LABEL(label), 0.0); 1048 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1); 1049 1050 gtk_grid_attach(GTK_GRID(table), entry_alias, 1, 1, 1, 1); 1051 gtk_widget_set_hexpand(entry_alias, TRUE); 1052 gtk_widget_set_halign(entry_alias, GTK_ALIGN_FILL); 1053 1054 /* Next row */ 1055 label = gtk_label_new(_("Remarks")); 1056 gtk_label_set_xalign(GTK_LABEL(label), 0.0); 1057 gtk_grid_attach(GTK_GRID(table), label, 0, 2, 1, 1); 1058 1059 gtk_grid_attach(GTK_GRID(table), entry_remarks, 1, 2, 1, 1); 1060 gtk_widget_set_hexpand(entry_remarks, TRUE); 1061 gtk_widget_set_halign(entry_remarks, GTK_ALIGN_FILL); 1062 1063 /* Button box */ 1064 vboxb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4 ); 1065 gtk_box_pack_start(GTK_BOX(hbox), vboxb, FALSE, FALSE, 2); 1066 1067 vbuttonbox = gtk_button_box_new(GTK_ORIENTATION_VERTICAL); 1068 gtk_button_box_set_layout( GTK_BUTTON_BOX(vbuttonbox), GTK_BUTTONBOX_START ); 1069 gtk_box_set_spacing( GTK_BOX(vbuttonbox), 8 ); 1070 gtk_container_set_border_width( GTK_CONTAINER(vbuttonbox), 4 ); 1071 gtk_container_add( GTK_CONTAINER(vboxb), vbuttonbox ); 1072 1073 buttonUp = gtkut_stock_button("go-up", _("_Up")); 1074 buttonDown = gtkut_stock_button("go-down", _("_Down")); 1075 buttonDel = gtkut_stock_button("edit-delete", _("D_elete")); 1076 buttonMod = gtkut_stock_button("document-save", _("_Save")); 1077 buttonAdd = gtkut_stock_button("list-add", _("_Add")); 1078 1079 gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonUp ); 1080 gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDown ); 1081 gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonDel ); 1082 gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonMod ); 1083 gtk_container_add( GTK_CONTAINER(vbuttonbox), buttonAdd ); 1084 1085 gtk_widget_show_all(vbox); 1086 1087 /* Event handlers */ 1088 g_signal_connect( G_OBJECT(view), "cursor-changed", 1089 G_CALLBACK( edit_person_email_cursor_changed ), NULL ); 1090 g_signal_connect( G_OBJECT(buttonUp), "clicked", 1091 G_CALLBACK( edit_person_email_move_up ), NULL ); 1092 g_signal_connect( G_OBJECT(buttonDown), "clicked", 1093 G_CALLBACK( edit_person_email_move_down ), NULL ); 1094 g_signal_connect( G_OBJECT(buttonDel), "clicked", 1095 G_CALLBACK( edit_person_email_delete ), NULL ); 1096 g_signal_connect( G_OBJECT(buttonMod), "clicked", 1097 G_CALLBACK( edit_person_email_modify ), NULL ); 1098 g_signal_connect( G_OBJECT(buttonAdd), "clicked", 1099 G_CALLBACK( edit_person_email_add ), NULL ); 1100 g_signal_connect(G_OBJECT(entry_email), "changed", 1101 G_CALLBACK(edit_person_entry_email_changed), NULL); 1102 g_signal_connect(G_OBJECT(entry_email), "key_press_event", 1103 G_CALLBACK(edit_person_entry_email_pressed), NULL); 1104 g_signal_connect(G_OBJECT(entry_alias), "key_press_event", 1105 G_CALLBACK(edit_person_entry_email_pressed), NULL); 1106 g_signal_connect(G_OBJECT(entry_remarks), "key_press_event", 1107 G_CALLBACK(edit_person_entry_email_pressed), NULL); 1108 1109 personeditdlg.view_email = view; 1110 personeditdlg.entry_email = entry_email; 1111 personeditdlg.entry_alias = entry_alias; 1112 personeditdlg.entry_remarks = entry_remarks; 1113 personeditdlg.email_up = buttonUp; 1114 personeditdlg.email_down = buttonDown; 1115 personeditdlg.email_del = buttonDel; 1116 personeditdlg.email_mod = buttonMod; 1117 personeditdlg.email_add = buttonAdd; 1118 } 1119 1120 static void addressbook_edit_person_create( GtkWidget *parent, gboolean *cancelled ) { 1121 if (prefs_common.addressbook_use_editaddress_dialog) 1122 addressbook_edit_person_dialog_create( cancelled ); 1123 else 1124 addressbook_edit_person_widgetset_create( parent, cancelled ); 1125 addressbook_edit_person_page_basic( PAGE_BASIC, _( "_User Data" ) ); 1126 addressbook_edit_person_page_email( PAGE_EMAIL, _( "_Email Addresses" ) ); 1127 gtk_widget_show_all( personeditdlg.container ); 1128 } 1129 1130 /* 1131 * Return list of email items. 1132 */ 1133 static GList *edit_person_build_email_list() { 1134 GtkWidget *view = personeditdlg.view_email; 1135 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); 1136 GtkTreeIter iter; 1137 GList *listEMail = NULL; 1138 ItemEMail *email; 1139 1140 if (!gtk_tree_model_get_iter_first(model, &iter)) 1141 return NULL; 1142 1143 do { 1144 gtk_tree_model_get(model, &iter, EMAIL_COL_PTR, &email, -1); 1145 listEMail = g_list_append( listEMail, email ); 1146 } while (gtk_tree_model_iter_next(model, &iter)); 1147 1148 return listEMail; 1149 } 1150 1151 static void update_sensitivity(void) 1152 { 1153 gtk_widget_set_sensitive(personeditdlg.entry_name, !personeditdlg.read_only); 1154 gtk_widget_set_sensitive(personeditdlg.entry_first, !personeditdlg.read_only); 1155 gtk_widget_set_sensitive(personeditdlg.entry_last, !personeditdlg.read_only); 1156 gtk_widget_set_sensitive(personeditdlg.entry_nick, !personeditdlg.read_only); 1157 gtk_widget_set_sensitive(personeditdlg.entry_email, !personeditdlg.read_only); 1158 gtk_widget_set_sensitive(personeditdlg.entry_alias, !personeditdlg.read_only); 1159 gtk_widget_set_sensitive(personeditdlg.entry_remarks, !personeditdlg.read_only); 1160 gtk_widget_set_sensitive(personeditdlg.email_up, !personeditdlg.read_only); 1161 gtk_widget_set_sensitive(personeditdlg.email_down, !personeditdlg.read_only); 1162 gtk_widget_set_sensitive(personeditdlg.email_del, !personeditdlg.read_only); 1163 gtk_widget_set_sensitive(personeditdlg.email_mod, !personeditdlg.read_only); 1164 gtk_widget_set_sensitive(personeditdlg.email_add, !personeditdlg.read_only); 1165 } 1166 1167 static void addressbook_edit_person_flush_transient( void ) 1168 { 1169 ItemPerson *person = current_person; 1170 EditAddressPostUpdateCallback callback = edit_person_close_post_update_cb; 1171 1172 /* reset transient data */ 1173 current_abf = NULL; 1174 current_person = NULL; 1175 current_parent_folder = NULL; 1176 edit_person_close_post_update_cb = NULL; 1177 1178 /* post action to perform on addressbook side */ 1179 if (callback) 1180 callback( person ); 1181 } 1182 1183 void addressbook_edit_person_invalidate( AddressBookFile *abf, ItemFolder *parent_folder, 1184 ItemPerson *person ) 1185 { 1186 if (current_abf == NULL && 1187 current_person == NULL && 1188 current_parent_folder == NULL) 1189 /* edit address form is already hidden */ 1190 return; 1191 1192 /* unconditional invalidation or invalidating the currently edited item */ 1193 if ( ( abf == NULL && person == NULL && parent_folder == NULL ) 1194 || (current_abf == abf || 1195 current_person == person || 1196 current_parent_folder == parent_folder)) 1197 addressbook_edit_person_close( TRUE ); 1198 } 1199 1200 static gboolean addressbook_edit_person_close( gboolean cancelled ) 1201 { 1202 GList *listEMail = NULL; 1203 GError *error = NULL; 1204 GtkTreeModel *model; 1205 1206 listEMail = edit_person_build_email_list(); 1207 if( cancelled ) { 1208 model = gtk_tree_view_get_model(GTK_TREE_VIEW(personeditdlg.view_email)); 1209 gtk_list_store_clear(GTK_LIST_STORE(model)); 1210 addritem_free_list_email( listEMail ); 1211 1212 if (!prefs_common.addressbook_use_editaddress_dialog) 1213 gtk_widget_hide( personeditdlg.container ); 1214 1215 /* no callback, as we're discarding the form */ 1216 edit_person_close_post_update_cb = NULL; 1217 addressbook_edit_person_flush_transient(); 1218 current_person = NULL; 1219 1220 /* set focus to the address list (this is done by the post_update_cb usually) */ 1221 addressbook_address_list_set_focus(); 1222 return FALSE; 1223 } 1224 1225 if( current_person && current_abf ) { 1226 addrbook_update_address_list( current_abf, current_person, listEMail ); 1227 } else { 1228 /* Create new current_person and email list */ 1229 if( ! cancelled && current_abf ) { 1230 current_person = addrbook_add_address_list( current_abf, current_parent_folder, listEMail ); 1231 } 1232 } 1233 listEMail = NULL; 1234 1235 if(!cancelled && current_person != NULL) { 1236 /* Set current_person stuff */ 1237 1238 gchar *name; 1239 gchar *cn = edit_person_get_common_name_from_widgets(); 1240 1241 addritem_person_set_common_name( current_person, cn ); 1242 g_free( cn ); 1243 1244 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_first), 0, -1 ); 1245 addritem_person_set_first_name( current_person, name ); 1246 g_free( name ); 1247 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_last), 0, -1 ); 1248 addritem_person_set_last_name( current_person, name ); 1249 g_free( name ); 1250 name = gtk_editable_get_chars( GTK_EDITABLE(personeditdlg.entry_nick), 0, -1 ); 1251 addritem_person_set_nick_name( current_person, name ); 1252 g_free( name ); 1253 } 1254 1255 model = gtk_tree_view_get_model(GTK_TREE_VIEW(personeditdlg.view_email)); 1256 gtk_list_store_clear(GTK_LIST_STORE(model)); 1257 1258 if (!prefs_common.addressbook_use_editaddress_dialog) 1259 gtk_widget_hide( personeditdlg.container ); 1260 1261 addressbook_edit_person_flush_transient(); 1262 1263 return TRUE; 1264 } 1265 1266 /* 1267 * Edit person. 1268 * Enter: abf Address book. 1269 * parent Parent folder for person (or NULL if adding to root folder). Argument is 1270 * only required for new objects). 1271 * person Person to edit, or NULL for a new person object. 1272 * pgMail If TRUE, E-Mail page will be activated. 1273 * Return: Edited object, or NULL if cancelled.*/ 1274 ItemPerson *addressbook_edit_person( AddressBookFile *abf, ItemFolder *parent_folder, ItemPerson *person, 1275 gboolean pgMail, GtkWidget *parent_container, 1276 void (*post_update_cb) (ItemPerson *person), 1277 gboolean get_focus) { 1278 static gboolean cancelled; 1279 GError *error = NULL; 1280 GdkPixbuf *pixbuf = NULL; 1281 GtkTreeModel *model; 1282 GtkTreeSelection *sel; 1283 GtkTreeIter iter; 1284 1285 /* set transient data */ 1286 current_abf = abf; 1287 current_person = person; 1288 current_parent_folder = parent_folder; 1289 edit_person_close_post_update_cb = post_update_cb; 1290 1291 if( personeditdlg.container ) { 1292 gtk_widget_destroy(personeditdlg.container); 1293 personeditdlg.container = NULL; 1294 } 1295 addressbook_edit_person_create(parent_container, &cancelled); 1296 1297 /* typically, get focus when dialog mode is enabled, or when editing a new address */ 1298 if( get_focus ) { 1299 gtk_widget_grab_focus(personeditdlg.ok_btn); 1300 gtk_widget_grab_focus(personeditdlg.entry_name); 1301 } 1302 1303 personeditdlg.read_only = (current_abf == NULL); 1304 update_sensitivity(); 1305 1306 gtk_widget_show(personeditdlg.container); 1307 if (prefs_common.addressbook_use_editaddress_dialog) 1308 manage_window_set_transient(GTK_WINDOW(personeditdlg.container)); 1309 else 1310 if (get_focus) 1311 addressbook_address_list_disable_some_actions(); 1312 1313 /* Clear all fields */ 1314 edit_person_status_show( "" ); 1315 1316 model = gtk_tree_view_get_model(GTK_TREE_VIEW(personeditdlg.view_email)); 1317 gtk_list_store_clear(GTK_LIST_STORE(model)); 1318 1319 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_name), "" ); 1320 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_first), "" ); 1321 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_last), "" ); 1322 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), "" ); 1323 1324 personeditdlg.editNew = FALSE; 1325 if( current_person ) { 1326 gchar *filename = NULL; 1327 1328 if( ADDRITEM_NAME(current_person) ) 1329 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_name), ADDRITEM_NAME(person) ); 1330 if( current_person->firstName ) 1331 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_first), current_person->firstName ); 1332 if( current_person->lastName ) 1333 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_last), current_person->lastName ); 1334 if( current_person->nickName ) 1335 gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), current_person->nickName ); 1336 edit_person_load_email( current_person ); 1337 } 1338 else { 1339 personeditdlg.editNew = TRUE; 1340 } 1341 1342 /* Select appropriate start page */ 1343 if( pgMail ) { 1344 gtk_notebook_set_current_page( GTK_NOTEBOOK(personeditdlg.notebook), PAGE_EMAIL ); 1345 } 1346 else { 1347 gtk_notebook_set_current_page( GTK_NOTEBOOK(personeditdlg.notebook), PAGE_BASIC ); 1348 } 1349 1350 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(personeditdlg.view_email)); 1351 model = gtk_tree_view_get_model(GTK_TREE_VIEW(personeditdlg.view_email)); 1352 if (gtk_tree_model_get_iter_first(model, &iter)) { 1353 gtk_tree_selection_select_iter(sel, &iter); 1354 edit_person_email_cursor_changed( 1355 GTK_TREE_VIEW(personeditdlg.view_email), NULL); 1356 } 1357 1358 edit_person_email_clear( NULL ); 1359 1360 if (prefs_common.addressbook_use_editaddress_dialog) { 1361 gtk_main(); 1362 gtk_widget_hide( personeditdlg.container ); 1363 1364 if (!addressbook_edit_person_close( cancelled )) { 1365 return NULL; 1366 } 1367 } 1368 1369 return person; 1370 }