3
* Osmo - a handy personal organizer
5
* Copyright (C) 2007 Tomasz Maka <pasp@users.sourceforge.net>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36
#include "contacts_items.h"
38
#include "gui_utils.h"
39
#include "options_prefs.h"
40
#include "stock_icons.h"
41
#include "contacts_birthdays.h"
42
#include "contacts_import.h"
43
#include "contacts_export.h"
44
#include "time_utils.h"
45
#include "date_utils.h"
47
/*------------------------------------------------------------------------------*/
50
set_export_active (GUI *appGUI) {
57
while (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(appGUI->cnt->contacts_filter), &iter, NULL, n++));
58
state = (n == 1) ? FALSE : TRUE;
59
gtk_widget_set_sensitive(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/export"), state);
62
/*------------------------------------------------------------------------------*/
65
show_contacts_desc_panel (gboolean enable, GUI *appGUI) {
68
GdkRectangle rect, visible_rect;
69
GtkTreePath *visible_path;
75
if (gtk_tree_selection_get_selected (appGUI->cnt->contacts_list_selection, &model, &iter)) {
77
gtk_paned_set_position(GTK_PANED(appGUI->cnt->contacts_paned), config.contacts_pane_pos);
79
while (g_main_context_iteration(NULL, FALSE));
81
visible_path = gtk_tree_model_get_path (model, &iter);
85
gtk_tree_view_get_cell_area (GTK_TREE_VIEW (appGUI->cnt->contacts_list), visible_path, NULL, &rect);
86
gtk_tree_view_get_visible_rect (GTK_TREE_VIEW (appGUI->cnt->contacts_list), &visible_rect);
88
if (rect.y < visible_rect.y || rect.y > visible_rect.y + visible_rect.height) {
89
gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (appGUI->cnt->contacts_list), visible_path, NULL, TRUE, 0.5, 0.0);
92
gtk_tree_path_free(visible_path);
101
config.contacts_pane_pos = gtk_paned_get_position(GTK_PANED(appGUI->cnt->contacts_paned));
102
gtk_paned_set_position(GTK_PANED(appGUI->cnt->contacts_paned), 99999);
104
adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW(appGUI->cnt->contacts_panel_scrolledwindow));
105
gtk_adjustment_set_value (adj, 0.0);
106
gtk_adjustment_value_changed (adj);
110
appGUI->cnt->contacts_panel_status = enable;
113
/*------------------------------------------------------------------------------*/
116
find_combo_box_focus_cb (GtkWidget *widget, GtkDirectionType *arg1, gpointer user_data) {
120
/*------------------------------------------------------------------------------*/
123
contacts_panel_close_desc_cb (GtkWidget *widget, gpointer data) {
125
GUI *appGUI = (GUI *)data;
127
show_contacts_desc_panel(FALSE, appGUI);
130
/*------------------------------------------------------------------------------*/
133
contacts_list_filter_cb (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) {
137
gint i, j, len, text_len;
140
GUI *appGUI = (GUI *)data;
142
if (appGUI->cnt->contacts_filter_disabled == TRUE) {
146
text = gtk_entry_get_text(GTK_ENTRY(appGUI->cnt->contacts_find_entry));
152
text_len = strlen(text);
156
if(config.find_mode == CONTACTS_FF_FIRST_NAME) {
158
gtk_tree_model_get(model, iter, COLUMN_FIRST_NAME, &value, -1);
161
if(g_ascii_strncasecmp(g_utf8_casefold(text, -1), g_utf8_casefold(value, -1), text_len))
168
} else if (config.find_mode == CONTACTS_FF_LAST_NAME) {
170
gtk_tree_model_get(model, iter, COLUMN_LAST_NAME, &value, -1);
173
if(g_ascii_strncasecmp(g_utf8_casefold(text, -1), g_utf8_casefold(value, -1), text_len))
180
} else if (config.find_mode == CONTACTS_FF_ALL_FIELDS) {
182
for(i=0; i < CONTACTS_NUM_COLUMNS; i++) {
184
if (i != COLUMN_PHOTO && i != COLUMN_ID) {
185
if (i == COLUMN_BIRTH_DAY_DATE || i == COLUMN_NAME_DAY_DATE) {
186
gtk_tree_model_get (model, iter, i, &date, -1);
190
if (i == COLUMN_BIRTH_DAY_DATE) {
191
value = g_strdup((const gchar *)julian_to_str(date, DATE_FULL));
193
value = g_strdup((const gchar *)julian_to_str(date, DATE_NAME_DAY));
197
gtk_tree_model_get(model, iter, i, &value, -1);
202
len = strlen(value) - text_len;
205
for(j=0; j <= len; j++) {
206
if(!g_ascii_strncasecmp(g_utf8_casefold(text, -1), g_utf8_casefold(value+j, -1), text_len))
223
/*------------------------------------------------------------------------------*/
226
contacts_select_first_position_in_list(GUI *appGUI) {
231
/* set cursor at first position */
232
if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), &iter) == TRUE) {
233
path = gtk_tree_model_get_path (GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), &iter);
235
gtk_tree_view_set_cursor (GTK_TREE_VIEW (appGUI->cnt->contacts_list), path, NULL, FALSE);
236
gtk_tree_path_free(path);
241
/*------------------------------------------------------------------------------*/
244
contacts_item_selected_cb (GtkTreeSelection *selection, gpointer data) {
250
GtkTextBuffer *text_buffer;
252
gchar photo_full_path[PATH_MAX], space_line[PATH_MAX];
253
char tmpbuf[BUFFER_SIZE];
254
gboolean activate_home_phone, activate_work_phone, activate_cell_phone;
255
gboolean activate_email, activate_www;
258
GUI *appGUI = (GUI *)data;
260
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
262
gtk_widget_set_sensitive(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/edit"), TRUE);
263
gtk_widget_set_sensitive(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/delete"), TRUE);
264
set_export_active (appGUI);
266
text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(appGUI->cnt->contacts_desc_textview));
267
gui_clear_text_buffer (text_buffer, &titer);
269
if (appGUI->cnt->photo_image != NULL) { /* remove old photo */
270
gtk_widget_destroy(appGUI->cnt->photo_image);
271
appGUI->cnt->photo_image = NULL;
274
gui_url_remove_links (&appGUI->cnt->contacts_links_list, &appGUI->cnt->contacts_link_index);
276
for(i=0; i < CONTACTS_NUM_COLUMNS; i++) {
278
if (i != COLUMN_ID) {
280
if (i == COLUMN_BIRTH_DAY_DATE || i == COLUMN_NAME_DAY_DATE) {
281
gtk_tree_model_get (model, &iter, i, &date, -1);
285
if (i == COLUMN_BIRTH_DAY_DATE) {
286
text = g_strdup((const gchar *)julian_to_str(date, DATE_FULL));
288
text = g_strdup((const gchar *)julian_to_str(date, DATE_NAME_DAY));
292
gtk_tree_model_get (model, &iter, i, &text, -1);
295
if (i != COLUMN_PHOTO && i != COLUMN_ID) {
297
if (i == COLUMN_FIRST_NAME || i == COLUMN_SECOND_NAME || i == COLUMN_LAST_NAME) {
300
gtk_text_buffer_insert_with_tags_by_name (text_buffer, &titer, text, -1,
302
gtk_text_buffer_insert_with_tags_by_name (text_buffer, &titer, " ", -1,
306
if (i == COLUMN_LAST_NAME) {
307
gtk_text_buffer_insert(text_buffer, &titer, "\n", -1);
310
} else if (text != NULL && i!= COLUMN_GROUP) {
312
gtk_text_buffer_insert_with_tags_by_name (text_buffer, &titer, "\n", -1, "normal", NULL);
314
activate_home_phone = (i == COLUMN_HOME_PHONE_2 || i == COLUMN_HOME_PHONE_3 || i == COLUMN_HOME_PHONE_4) && strlen(text);
315
activate_work_phone = (i == COLUMN_WORK_PHONE_2 || i == COLUMN_WORK_PHONE_3 || i == COLUMN_WORK_PHONE_4) && strlen(text);
316
activate_cell_phone = (i == COLUMN_WORK_PHONE_2 || i == COLUMN_WORK_PHONE_3 || i == COLUMN_WORK_PHONE_4) && strlen(text);
317
activate_email = (i == COLUMN_EMAIL_2 || i == COLUMN_EMAIL_3 || i == COLUMN_EMAIL_4) && strlen(text);
318
activate_www = (i == COLUMN_WWW_2 || i == COLUMN_WWW_3 || i == COLUMN_WWW_4) && strlen(text);
320
for(j=0;j<PATH_MAX;j++) space_line[j] = ' ';
322
if ((i >= COLUMN_HOME_PHONE_1 && i <= COLUMN_HOME_PHONE_4) ||
323
(i >= COLUMN_WORK_PHONE_1 && i <= COLUMN_WORK_PHONE_4) ||
324
(i >= COLUMN_CELL_PHONE_1 && i <= COLUMN_CELL_PHONE_4) ||
325
(i >= COLUMN_EMAIL_1 && i <= COLUMN_EMAIL_4) ||
326
(i >= COLUMN_WWW_1 && i <= COLUMN_WWW_4)) {
328
if ((activate_home_phone == FALSE && i == COLUMN_HOME_PHONE_1) ||
329
(activate_work_phone == FALSE && i == COLUMN_WORK_PHONE_1) ||
330
(activate_cell_phone == FALSE && i == COLUMN_CELL_PHONE_1) ||
331
(activate_email == FALSE && i == COLUMN_EMAIL_1) ||
332
(activate_www == FALSE && i == COLUMN_WWW_1)) {
334
sprintf(tmpbuf, "%s: ", gettext(appGUI->cnt->contact_fields_tags_name[2*i]));
336
sprintf(tmpbuf, " ");
340
sprintf(tmpbuf, "%s: ", gettext(appGUI->cnt->contact_fields_tags_name[2*i]));
343
if (i != COLUMN_INFO) {
344
space_line[appGUI->cnt->longest_tag_name - strlen(tmpbuf) + 2] = '\0';
345
strcat(tmpbuf, space_line);
347
gtk_text_buffer_insert_with_tags_by_name (text_buffer, &titer, tmpbuf, -1, "tag_name", NULL);
349
if (i == COLUMN_INFO) {
350
gtk_text_buffer_insert_with_tags_by_name (text_buffer, &titer, "\n", -1, "normal", NULL);
353
if (i == COLUMN_BLOG || (i >= COLUMN_EMAIL_1 && i <= COLUMN_EMAIL_4) || (i >= COLUMN_WWW_1 && i <= COLUMN_WWW_4)) { /* insert link */
354
gui_url_insert_link(&appGUI->cnt->contacts_links_list, &appGUI->cnt->contacts_link_index, appGUI->cnt->contacts_desc_textview , &titer, config.contact_link_color, config.tags_font_size, text, FALSE, appGUI);
356
gtk_text_buffer_insert_with_tags_by_name (text_buffer, &titer, text, -1, "normal", NULL);
366
gtk_tree_model_get (model, &iter, COLUMN_PHOTO, &text, -1);
369
strncpy(photo_full_path, text, PATH_MAX-1);
370
insert_photo(photo_full_path, &titer, appGUI);
375
gtk_widget_set_sensitive(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/edit"), FALSE);
376
gtk_widget_set_sensitive(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/delete"), FALSE);
377
set_export_active (appGUI);
381
/*------------------------------------------------------------------------------*/
384
contacts_desc_scrolled (GtkAdjustment *adj, gpointer data) {
388
GUI *appGUI = (GUI *)data;
390
if (appGUI->cnt->photo_image != NULL) {
391
gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(appGUI->cnt->contacts_desc_textview), GTK_TEXT_WINDOW_TEXT,
392
appGUI->cnt->contacts_desc_textview->allocation.width-config.photo_width-5, 5, &x, &y);
393
gtk_text_view_move_child(GTK_TEXT_VIEW(appGUI->cnt->contacts_desc_textview), appGUI->cnt->photo_image,
394
appGUI->cnt->contacts_desc_textview->allocation.width-config.photo_width-5, y);
399
contacts_desc_size_allocate (GtkWidget *widget, GtkAllocation *allocation, gpointer data) {
401
GUI *appGUI = (GUI *)data;
402
contacts_desc_scrolled(NULL, appGUI);
405
/*------------------------------------------------------------------------------*/
408
add_contacts_toolbar_widget (GtkUIManager *contacts_uim_widget, GtkWidget *widget, gpointer user_data) {
410
GtkWidget *handle_box;
412
GUI *appGUI = (GUI *)user_data;
414
if (GTK_IS_TOOLBAR (widget)) {
416
appGUI->cnt->contacts_toolbar = GTK_TOOLBAR (widget);
418
handle_box = gtk_handle_box_new ();
419
gtk_widget_show (handle_box);
420
gtk_container_add (GTK_CONTAINER (handle_box), widget);
421
gtk_box_pack_start (appGUI->cnt->vbox, handle_box, FALSE, FALSE, 0);
422
g_signal_connect_swapped (widget, "destroy", G_CALLBACK (gtk_widget_destroy), handle_box);
425
gtk_box_pack_start (appGUI->cnt->vbox, widget, FALSE, FALSE, 0);
428
gtk_widget_show (widget);
431
/*------------------------------------------------------------------------------*/
434
contacts_search_entry_changed_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data) {
441
GUI *appGUI = (GUI *)user_data;
443
gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(appGUI->cnt->contacts_filter));
444
set_export_active (appGUI);
446
if(strlen(gtk_entry_get_text (GTK_ENTRY(appGUI->cnt->contacts_find_entry)))) {
448
if (config.show_after_search == TRUE) {
451
while (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(appGUI->cnt->contacts_filter), &iter, NULL, i++));
454
show_contacts_desc_panel(TRUE, appGUI);
456
path = gtk_tree_path_new_first();
458
gtk_tree_view_set_cursor (GTK_TREE_VIEW (appGUI->cnt->contacts_list), path, NULL, FALSE);
462
gui_clear_text_buffer (gtk_text_view_get_buffer(GTK_TEXT_VIEW(appGUI->cnt->contacts_desc_textview)), &titer);
469
/*------------------------------------------------------------------------------*/
472
contacts_find_type_selected_cb (GtkComboBox *widget, gpointer user_data) {
476
GUI *appGUI = (GUI *)user_data;
478
config.find_mode = gtk_combo_box_get_active (widget);
480
if(strlen(gtk_entry_get_text (GTK_ENTRY(appGUI->cnt->contacts_find_entry)))) {
481
gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(appGUI->cnt->contacts_filter));
483
path = gtk_tree_path_new_first();
485
gtk_tree_view_set_cursor (GTK_TREE_VIEW (appGUI->cnt->contacts_list), path, NULL, FALSE);
487
show_contacts_desc_panel(TRUE, appGUI);
492
/*------------------------------------------------------------------------------*/
495
custom_contacts_sort_function (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer user_data) {
497
gchar *last_name_a, *last_name_b;
498
gchar *group_a, *group_b;
499
gchar *first_name_a, *first_name_b;
500
gint group_s, first_name_s, last_name_s;
502
GUI *appGUI = (GUI *)user_data;
504
if (appGUI->cnt->contacts_filter_disabled == TRUE)
507
if(iter_a == NULL || iter_b == NULL) {
511
gtk_tree_model_get(model, iter_a,
512
COLUMN_GROUP, &group_a, COLUMN_FIRST_NAME, &first_name_a, COLUMN_LAST_NAME, &last_name_a, -1);
513
gtk_tree_model_get(model, iter_b,
514
COLUMN_GROUP, &group_b, COLUMN_FIRST_NAME, &first_name_b, COLUMN_LAST_NAME, &last_name_b, -1);
516
if (group_a == NULL) {
518
} else if (group_b == NULL) {
520
} else if (group_a != NULL && group_b != NULL) {
521
group_s = g_utf8_collate(group_a, group_b);
526
if (group_a != NULL) {
529
if (group_b != NULL) {
533
if (first_name_a == NULL) {
535
} else if (first_name_b == NULL) {
537
} else if (first_name_a != NULL && first_name_b != NULL) {
538
first_name_s = g_utf8_collate(first_name_a, first_name_b);
543
if (first_name_a != NULL) {
544
g_free(first_name_a);
546
if (first_name_b != NULL) {
547
g_free(first_name_b);
550
if (last_name_a == NULL) {
552
} else if (last_name_b == NULL) {
554
} else if (last_name_a != NULL && last_name_b != NULL) {
555
last_name_s = g_utf8_collate(last_name_a, last_name_b);
560
if (last_name_a != NULL) {
563
if (last_name_b != NULL) {
567
switch(config.contacts_sorting_mode) {
569
/* Group, First Name, Last Name */
573
if (first_name_s != 0)
575
if (last_name_s != 0)
579
/* Group, Last Name, First Name */
583
if (last_name_s != 0)
585
if (first_name_s != 0)
589
/* Last Name, First Name, Group */
591
if (last_name_s != 0)
593
if (first_name_s != 0)
599
/* Last Name, Group, First Name */
601
if (last_name_s != 0)
605
if (first_name_s != 0)
609
/* First Name, Last Name, Group */
611
if (first_name_s != 0)
613
if (last_name_s != 0)
619
/* First Name, Group, Last Name */
621
if (first_name_s != 0)
625
if (last_name_s != 0)
636
/*------------------------------------------------------------------------------*/
639
contacts_add_item_cb (GtkWidget *widget, gpointer data) {
641
GUI *appGUI = (GUI *)data;
642
contacts_add_edit_dialog_show (FALSE, appGUI);
645
/*------------------------------------------------------------------------------*/
648
contacts_edit_item_cb (GtkWidget *widget, gpointer data) {
650
GUI *appGUI = (GUI *)data;
652
if (gtk_tree_selection_get_selected (appGUI->cnt->contacts_list_selection, NULL, NULL)) {
653
GUI *appGUI = (GUI *)data;
654
contacts_add_edit_dialog_show (TRUE, appGUI);
658
/*------------------------------------------------------------------------------*/
661
contacts_remove_item_cb (GtkWidget *widget, gpointer data) {
663
GUI *appGUI = (GUI *)data;
664
contacts_remove_dialog_show(appGUI->cnt->contacts_list, appGUI->cnt->contacts_list_store, appGUI);
667
/*------------------------------------------------------------------------------*/
670
contacts_birthdays_item_cb (GtkWidget *widget, gpointer data) {
672
GUI *appGUI = (GUI *)data;
673
contacts_create_birthdays_window (appGUI);
676
/*------------------------------------------------------------------------------*/
679
contacts_export_items_cb (GtkWidget *widget, gpointer data) {
681
GUI *appGUI = (GUI *)data;
682
contacts_create_export_window(appGUI);
685
/*------------------------------------------------------------------------------*/
688
contacts_import_items_cb (GtkWidget *widget, gpointer data) {
690
GUI *appGUI = (GUI *)data;
691
import_contacts_from_csv_file(appGUI);
694
/*------------------------------------------------------------------------------*/
697
contacts_list_dbclick_cb(GtkWidget * widget, GdkEventButton * event, gpointer func_data) {
699
GUI *appGUI = (GUI *)func_data;
701
if ((event->type==GDK_2BUTTON_PRESS) && (event->button == 1)) {
703
if (appGUI->cnt->contacts_panel_status == TRUE) {
704
contacts_edit_item_cb (NULL, appGUI);
706
show_contacts_desc_panel(TRUE, appGUI);
714
/*------------------------------------------------------------------------------*/
717
gui_create_contacts(GUI *appGUI) {
722
GtkWidget *hseparator;
724
GtkWidget *top_scrolledwindow;
725
GtkWidget *top_viewport;
726
GtkWidget *bottom_viewport;
727
GtkWidget *close_button;
728
GtkCellRenderer *renderer[CONTACTS_NUM_COLUMNS];
729
GType contact_columns_types[CONTACTS_NUM_COLUMNS];
730
GtkTextBuffer *text_buffer;
732
GError *error = NULL;
733
GtkActionGroup *action_group = NULL;
734
GtkAdjustment *adjustment;
735
char tmpbuf[BUFFER_SIZE];
737
static gchar *contact_fields_tags_name[] = {
738
N_("Group"), "group", N_("First name"), "first_name", N_("Second name"), "second_name",
739
N_("Last name"), "last_name",
740
N_("Nickname"), "nickname", N_("Birthday date"), "birthday_date", N_("Name day date"), "name_day_date",
742
/*--------------------------------------------------*/
743
N_("Home address"), "home_address", N_("Home postcode"), "home_postcode", N_("Home city"),
744
"home_city", N_("Home state"), "home_state", N_("Home country"), "home_country",
745
/*--------------------------------------------------*/
747
N_("Organization"), "organization", N_("Department"), "department",
749
/*--------------------------------------------------*/
750
N_("Work address"), "work_address", N_("Work postcode"), "work_postcode", N_("Work city"),
751
"work_city", N_("Work state"), "work_state", N_("Work country"), "work_country",
752
/*--------------------------------------------------*/
754
N_("Fax"), "work_fax",
756
/*--------------------------------------------------*/
757
N_("Home phone"), "home_phone_1", N_("Home phone 2"), "home_phone_2",
758
N_("Home phone 3"), "home_phone_3", N_("Home phone 4"), "home_phone_4",
759
N_("Work phone"), "work_phone_1", N_("Work phone 2"), "work_phone_2",
760
N_("Work phone 3"), "work_phone_3", N_("Work phone 4"), "work_phone_4",
761
N_("Cell phone"), "cell_phone_1", N_("Cell phone 2"), "cell_phone_2",
762
N_("Cell phone 3"), "cell_phone_3", N_("Cell phone 4"), "cell_phone_4",
763
N_("E-Mail"), "email_1", N_("E-Mail 2"), "email_2", N_("E-Mail 3"), "email_3",
764
N_("E-Mail 4"), "email_4", N_("WWW"), "www_1", N_("WWW 2"), "www_2", N_("WWW 3"), "www_3",
765
N_("WWW 4"), "www_4",
766
/*--------------------------------------------------*/
768
N_("IM Gadu-Gadu"), "im_gg", N_("IM Yahoo"), "im_yahoo", N_("IM MSN"), "im_msn",
769
N_("IM ICQ"), "im_icq", N_("IM AOL"), "im_aol",
770
N_("IM Jabber"), "im_jabber", N_("IM Skype"), "im_skype", N_("IM Tlen"), "im_tlen",
771
N_("Blog"), "blog", N_("Photo"), "photo_path", N_("Additional info"), "additional_info", "ID", "id"
774
const gchar *ui_info =
775
" <toolbar name=\"toolbar\">\n"
776
" <toolitem name=\"add\" action=\"add\" />\n"
777
" <toolitem name=\"delete\" action=\"delete\" />\n"
778
" <toolitem name=\"edit\" action=\"edit\" />\n"
779
" <separator name=\"sep1\" />\n"
780
" <toolitem name=\"birthdays\" action=\"birthdays\" />\n"
781
" <separator name=\"sep2\" />\n"
782
" <toolitem name=\"import\" action=\"import\" />\n"
783
" <toolitem name=\"export\" action=\"export\" />\n"
786
GtkActionEntry entries[] = {
787
{ "add", OSMO_STOCK_CONTACTS_ADD, _("New contact"), NULL, _("New contact"), NULL },
788
{ "delete", OSMO_STOCK_CONTACTS_REMOVE, _("Remove contact"), NULL, _("Remove contact"), NULL },
789
{ "edit", OSMO_STOCK_CONTACTS_EDIT, _("Edit contact"), NULL, _("Edit contact"), NULL },
790
{ "birthdays", OSMO_STOCK_CONTACTS_BIRTHDAYS, _("Show birthdays"), NULL, _("Show birthdays"), NULL },
791
{ "import", OSMO_STOCK_CONTACTS_IMPORT, _("Import contacts"), NULL, _("Import contacts"), NULL },
792
{ "export", OSMO_STOCK_CONTACTS_EXPORT, _("Export contacts"), NULL, _("Export contacts"), NULL },
795
guint n_entries = G_N_ELEMENTS (entries);
797
appGUI->cnt->contact_fields_tags_name = contact_fields_tags_name;
798
appGUI->cnt->longest_tag_name = 0;
800
for(i=0; i < CONTACTS_NUM_COLUMNS; i++) {
801
if (i != COLUMN_ID) {
802
if (appGUI->cnt->longest_tag_name < strlen(gettext(contact_fields_tags_name[i*2]))) {
803
appGUI->cnt->longest_tag_name = strlen(gettext(contact_fields_tags_name[i*2]));
808
vbox1 = gtk_vbox_new (FALSE, 0);
809
gtk_widget_show (vbox1);
810
gtk_container_set_border_width (GTK_CONTAINER (vbox1), 8);
811
sprintf(tmpbuf, "<b>%s</b>", _("Contacts"));
812
gui_add_to_notebook (vbox1, tmpbuf, appGUI);
814
appGUI->cnt->vbox = GTK_BOX(vbox1);
816
if (config.hide_contacts == TRUE) {
817
gtk_widget_hide(GTK_WIDGET(appGUI->cnt->vbox));
820
/*-------------------------------------------------------------------------------------*/
822
action_group = gtk_action_group_new ("_actions");
823
gtk_action_group_add_actions (action_group, entries, n_entries, NULL);
824
gtk_action_group_set_sensitive(action_group, TRUE);
826
appGUI->cnt->contacts_uim_widget = gtk_ui_manager_new ();
828
gtk_ui_manager_insert_action_group (appGUI->cnt->contacts_uim_widget, action_group, 0);
829
g_signal_connect (appGUI->cnt->contacts_uim_widget, "add_widget", G_CALLBACK (add_contacts_toolbar_widget), appGUI);
831
if (!gtk_ui_manager_add_ui_from_string (appGUI->cnt->contacts_uim_widget, ui_info, -1, &error)) {
832
g_message ("building toolbar failed: %s", error->message);
833
g_error_free (error);
835
gtk_ui_manager_ensure_update (appGUI->cnt->contacts_uim_widget);
837
gtk_toolbar_set_style (appGUI->cnt->contacts_toolbar, GTK_TOOLBAR_ICONS);
838
gtk_toolbar_set_tooltips (appGUI->cnt->contacts_toolbar, config.enable_tooltips);
840
/*-------------------------------------------------------------------------------------*/
841
/* assign callbacks */
843
g_signal_connect (G_OBJECT(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/add")), "clicked",
844
G_CALLBACK(contacts_add_item_cb), appGUI);
845
g_signal_connect (G_OBJECT(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/edit")), "clicked",
846
G_CALLBACK(contacts_edit_item_cb), appGUI);
847
g_signal_connect (G_OBJECT(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/delete")), "clicked",
848
G_CALLBACK(contacts_remove_item_cb), appGUI);
849
g_signal_connect (G_OBJECT(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/birthdays")), "clicked",
850
G_CALLBACK(contacts_birthdays_item_cb), appGUI);
851
g_signal_connect (G_OBJECT(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/export")), "clicked",
852
G_CALLBACK(contacts_export_items_cb), appGUI);
853
g_signal_connect (G_OBJECT(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/import")), "clicked",
854
G_CALLBACK(contacts_import_items_cb), appGUI);
856
/*-------------------------------------------------------------------------------------*/
858
gtk_widget_set_sensitive(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/edit"), FALSE);
859
gtk_widget_set_sensitive(gtk_ui_manager_get_widget (appGUI->cnt->contacts_uim_widget, "/toolbar/delete"), FALSE);
861
hseparator = gtk_hseparator_new ();
862
gtk_widget_show (hseparator);
863
gtk_box_pack_start (GTK_BOX (vbox1), hseparator, FALSE, FALSE, 6);
865
sprintf(tmpbuf, "<b>%s:</b>", _("Search"));
866
label = gtk_label_new (tmpbuf);
867
gtk_widget_show (label);
868
gtk_label_set_use_markup (GTK_LABEL(label), TRUE);
869
gtk_box_pack_start (GTK_BOX (vbox1), label, FALSE, FALSE, 0);
870
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
872
hbox2 = gtk_hbox_new (FALSE, 0);
873
gtk_widget_show (hbox2);
874
gtk_box_pack_start (GTK_BOX (vbox1), hbox2, FALSE, TRUE, 0);
876
appGUI->cnt->contacts_find_entry = gtk_entry_new();
877
gtk_entry_set_max_length(GTK_ENTRY(appGUI->cnt->contacts_find_entry), 128);
878
gtk_widget_show (appGUI->cnt->contacts_find_entry);
879
g_signal_connect (G_OBJECT(appGUI->cnt->contacts_find_entry), "key_release_event",
880
G_CALLBACK(contacts_search_entry_changed_cb), appGUI);
881
gtk_box_pack_start (GTK_BOX (hbox2), appGUI->cnt->contacts_find_entry, TRUE, TRUE, 0);
883
appGUI->cnt->contacts_find_combobox = gtk_combo_box_new_text ();
884
gtk_widget_show (appGUI->cnt->contacts_find_combobox);
885
gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (appGUI->cnt->contacts_find_combobox), FALSE);
886
gtk_box_pack_start (GTK_BOX (hbox2), appGUI->cnt->contacts_find_combobox, FALSE, FALSE, 0);
887
g_signal_connect (G_OBJECT (appGUI->cnt->contacts_find_combobox), "changed",
888
G_CALLBACK (contacts_find_type_selected_cb), appGUI);
889
g_signal_connect(G_OBJECT(appGUI->cnt->contacts_find_combobox), "focus",
890
G_CALLBACK(find_combo_box_focus_cb), appGUI);
891
gtk_combo_box_append_text (GTK_COMBO_BOX (appGUI->cnt->contacts_find_combobox), _("First Name"));
892
gtk_combo_box_append_text (GTK_COMBO_BOX (appGUI->cnt->contacts_find_combobox), _("Last Name"));
893
gtk_combo_box_append_text (GTK_COMBO_BOX (appGUI->cnt->contacts_find_combobox), _("All fields"));
895
hseparator = gtk_hseparator_new ();
896
gtk_widget_show (hseparator);
897
gtk_box_pack_start (GTK_BOX (vbox1), hseparator, FALSE, FALSE, 6);
899
/******************************************************************************************/
901
appGUI->cnt->contacts_paned = gtk_vpaned_new();
902
gtk_widget_show (appGUI->cnt->contacts_paned);
903
gtk_paned_set_position(GTK_PANED(appGUI->cnt->contacts_paned), 99999);
904
gtk_box_pack_start(GTK_BOX(vbox1), appGUI->cnt->contacts_paned, TRUE, TRUE, 0);
906
top_viewport = gtk_viewport_new (NULL, NULL);
907
gtk_widget_show (top_viewport);
908
gtk_viewport_set_shadow_type (GTK_VIEWPORT (top_viewport), GTK_SHADOW_NONE);
909
gtk_paned_pack1 (GTK_PANED (appGUI->cnt->contacts_paned), top_viewport, FALSE, TRUE);
911
top_scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
912
gtk_widget_show (top_scrolledwindow);
913
gtk_container_add (GTK_CONTAINER (top_viewport), top_scrolledwindow);
915
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (top_scrolledwindow), GTK_SHADOW_IN);
916
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (top_scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
918
for(i=0; i< CONTACTS_NUM_COLUMNS; i++) {
919
if (i == COLUMN_BIRTH_DAY_DATE || i == COLUMN_NAME_DAY_DATE || i == COLUMN_ID) {
920
contact_columns_types[i] = G_TYPE_UINT;
922
contact_columns_types[i] = G_TYPE_STRING;
926
appGUI->cnt->contacts_list_store = gtk_list_store_newv(CONTACTS_NUM_COLUMNS, &contact_columns_types[0]);
928
appGUI->cnt->contacts_filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), NULL);
929
gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER(appGUI->cnt->contacts_filter),
930
(GtkTreeModelFilterVisibleFunc)contacts_list_filter_cb,
933
appGUI->cnt->contacts_sort = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(appGUI->cnt->contacts_filter));
935
appGUI->cnt->contacts_list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(appGUI->cnt->contacts_sort));
936
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(appGUI->cnt->contacts_list), config.contacts_rules_hint);
937
gtk_widget_show (appGUI->cnt->contacts_list);
938
GTK_WIDGET_SET_FLAGS (appGUI->cnt->contacts_list, GTK_CAN_DEFAULT);
939
gtk_widget_modify_fg(GTK_WIDGET(appGUI->cnt->contacts_list), GTK_STATE_SELECTED,
940
(& GTK_WIDGET(appGUI->cnt->contacts_list)->style->base[GTK_STATE_SELECTED]));
942
g_signal_connect(G_OBJECT(appGUI->cnt->contacts_list), "button_press_event",
943
G_CALLBACK(contacts_list_dbclick_cb), appGUI);
945
appGUI->cnt->contacts_list_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (appGUI->cnt->contacts_list));
946
g_signal_connect(G_OBJECT(appGUI->cnt->contacts_list_selection), "changed",
947
G_CALLBACK(contacts_item_selected_cb), appGUI);
951
for (i = COLUMN_GROUP; i < CONTACTS_NUM_COLUMNS; i++) {
952
renderer[i] = gtk_cell_renderer_text_new();
953
appGUI->cnt->contacts_columns[i] = gtk_tree_view_column_new_with_attributes(gettext(contact_fields_tags_name[i*2]),
954
renderer[i], "text", i, NULL);
955
gtk_tree_view_append_column (GTK_TREE_VIEW(appGUI->cnt->contacts_list), appGUI->cnt->contacts_columns[i]);
957
if(i != COLUMN_FIRST_NAME && i != COLUMN_LAST_NAME && i != COLUMN_GROUP) {
958
gtk_tree_view_column_set_visible (appGUI->cnt->contacts_columns[i], FALSE);
960
if (config.hide_group_column == TRUE && i == COLUMN_GROUP) {
961
gtk_tree_view_column_set_visible (appGUI->cnt->contacts_columns[i], FALSE);
963
gtk_tree_view_column_set_expand (appGUI->cnt->contacts_columns[i], TRUE);
967
gtk_container_add (GTK_CONTAINER (top_scrolledwindow), appGUI->cnt->contacts_list);
968
gtk_tree_view_set_enable_search (GTK_TREE_VIEW(appGUI->cnt->contacts_list), FALSE);
970
/* configure sorting */
972
gtk_tree_sortable_set_sort_func((GtkTreeSortable *)appGUI->cnt->contacts_sort, 0,
973
(GtkTreeIterCompareFunc)custom_contacts_sort_function, appGUI, NULL);
975
gtk_tree_sortable_set_sort_column_id((GtkTreeSortable *)appGUI->cnt->contacts_sort, COLUMN_FIRST_NAME, config.contacts_sorting_order);
976
gtk_tree_sortable_set_sort_column_id((GtkTreeSortable *)appGUI->cnt->contacts_sort, COLUMN_LAST_NAME, config.contacts_sorting_order);
977
gtk_tree_sortable_set_sort_column_id((GtkTreeSortable *)appGUI->cnt->contacts_sort, COLUMN_GROUP, config.contacts_sorting_order);
979
bottom_viewport = gtk_viewport_new (NULL, NULL);
980
gtk_widget_show (bottom_viewport);
981
gtk_viewport_set_shadow_type (GTK_VIEWPORT (bottom_viewport), GTK_SHADOW_NONE);
982
gtk_paned_pack2 (GTK_PANED (appGUI->cnt->contacts_paned), bottom_viewport, TRUE, TRUE);
984
vbox2 = gtk_vbox_new (FALSE, 0);
985
gtk_widget_show (vbox2);
986
gtk_container_set_border_width (GTK_CONTAINER (vbox2), 0);
987
gtk_container_add (GTK_CONTAINER (bottom_viewport), vbox2);
989
appGUI->cnt->panel_hbox = gtk_hbox_new (FALSE, 0);
990
gtk_box_pack_start (GTK_BOX (vbox2), appGUI->cnt->panel_hbox, FALSE, FALSE, 0);
991
gtk_widget_show(appGUI->cnt->panel_hbox);
993
sprintf(tmpbuf, "%s:", _("Contact details"));
994
label = gtk_label_new (tmpbuf);
995
gtk_widget_show (label);
996
gtk_box_pack_start (GTK_BOX (appGUI->cnt->panel_hbox), label, FALSE, FALSE, 0);
998
if (config.default_stock_icons) {
999
close_button = gui_stock_button(GTK_STOCK_CLOSE, FALSE);
1001
close_button = gui_stock_button(OSMO_STOCK_BUTTON_CLOSE, FALSE);
1003
GTK_WIDGET_UNSET_FLAGS(close_button, GTK_CAN_FOCUS);
1004
gtk_button_set_relief (GTK_BUTTON(close_button), GTK_RELIEF_NONE);
1005
gtk_tooltips_set_tip (appGUI->osmo_tooltips, close_button, _("Close contact panel"), NULL);
1006
gtk_box_pack_end (GTK_BOX (appGUI->cnt->panel_hbox), close_button, FALSE, FALSE, 0);
1007
g_signal_connect (G_OBJECT (close_button), "clicked",
1008
G_CALLBACK (contacts_panel_close_desc_cb), appGUI);
1010
appGUI->cnt->contacts_panel_scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
1011
gtk_widget_show (appGUI->cnt->contacts_panel_scrolledwindow);
1012
gtk_box_pack_start (GTK_BOX (vbox2), appGUI->cnt->contacts_panel_scrolledwindow, TRUE, TRUE, 0);
1013
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (appGUI->cnt->contacts_panel_scrolledwindow), GTK_SHADOW_IN);
1014
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (appGUI->cnt->contacts_panel_scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1016
appGUI->cnt->contacts_desc_textview = gtk_text_view_new ();
1017
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (appGUI->cnt->contacts_desc_textview), GTK_WRAP_WORD);
1018
gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(appGUI->cnt->contacts_desc_textview), 4);
1019
gtk_text_view_set_left_margin(GTK_TEXT_VIEW(appGUI->cnt->contacts_desc_textview), 4);
1020
gtk_text_view_set_right_margin(GTK_TEXT_VIEW(appGUI->cnt->contacts_desc_textview), 4);
1021
gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(appGUI->cnt->contacts_desc_textview), FALSE);
1022
gtk_text_view_set_editable(GTK_TEXT_VIEW(appGUI->cnt->contacts_desc_textview), FALSE);
1023
gtk_widget_show (appGUI->cnt->contacts_desc_textview);
1024
gtk_container_add (GTK_CONTAINER (appGUI->cnt->contacts_panel_scrolledwindow), appGUI->cnt->contacts_desc_textview);
1026
gui_url_setup(&appGUI->cnt->contacts_links_list, &appGUI->cnt->contacts_link_index, appGUI->cnt->contacts_desc_textview, appGUI);
1028
adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(appGUI->cnt->contacts_panel_scrolledwindow));
1029
g_signal_connect(G_OBJECT(adjustment), "value-changed", G_CALLBACK(contacts_desc_scrolled), appGUI);
1030
g_signal_connect(G_OBJECT(appGUI->cnt->contacts_desc_textview), "size_allocate",
1031
G_CALLBACK(contacts_desc_size_allocate), appGUI);
1033
text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(appGUI->cnt->contacts_desc_textview));
1035
appGUI->cnt->contact_name_tag_object = gtk_text_buffer_create_tag (text_buffer, "big",
1036
"size", config.name_font_size * PANGO_SCALE, NULL);
1037
appGUI->cnt->contact_tags_value_tag_object = gtk_text_buffer_create_tag (text_buffer, "normal",
1038
"size", config.tags_font_size * PANGO_SCALE, NULL);
1039
appGUI->cnt->contact_color_tag_object = gtk_text_buffer_create_tag (text_buffer, "tag_name",
1040
"foreground", config.contact_tag_color, "font", "Monospace",
1041
"size", config.tags_font_size * PANGO_SCALE, "weight", PANGO_WEIGHT_SEMIBOLD, NULL);
1043
gtk_combo_box_set_active (GTK_COMBO_BOX (appGUI->cnt->contacts_find_combobox), config.find_mode);
1045
appGUI->cnt->contacts_filter_disabled = FALSE;
1046
gtk_tree_sortable_sort_column_changed((GtkTreeSortable *)appGUI->cnt->contacts_sort);
1047
gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(appGUI->cnt->contacts_filter));
1050
/*------------------------------------------------------------------------------*/
1053
insert_photo(gchar *photo_filename, GtkTextIter *iter, GUI *appGUI) {
1055
GtkTextBuffer * buffer;
1058
gint i, d_photo_width, d_photo_height;
1059
gint rowstride, channels, bc1, bc2, bc3, bc4;
1062
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(appGUI->cnt->contacts_desc_textview));
1066
d_photo_width = config.photo_width;
1068
pixbuf = gdk_pixbuf_new_from_file_at_size (photo_filename, d_photo_width, -1, NULL);
1070
if (pixbuf != NULL) {
1072
d_photo_width = gdk_pixbuf_get_width(pixbuf);
1073
d_photo_height = gdk_pixbuf_get_height(pixbuf);
1074
channels = gdk_pixbuf_get_n_channels (pixbuf);
1075
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1076
pixels = gdk_pixbuf_get_pixels (pixbuf);
1081
/* horizontal lines */
1083
for(i=0; i < d_photo_width; i++) {
1084
p = pixels + i * channels;
1085
p[0] = p[1] = p[2] = bc1;
1086
p = pixels + (d_photo_height-1) * rowstride + i * channels;
1087
p[0] = p[1] = p[2] = bc2;
1090
/* vertical lines */
1092
for(i=0; i < d_photo_height; i++) {
1093
p = pixels + i * rowstride;
1094
p[0] = p[1] = p[2] = bc3;
1095
p = pixels + i * rowstride + (d_photo_width-1) * channels;
1096
p[0] = p[1] = p[2] = bc4;
1101
appGUI->cnt->photo_image = gtk_image_new_from_pixbuf(pixbuf);
1103
if (appGUI->cnt->photo_image != NULL) {
1104
gtk_text_view_add_child_in_window(GTK_TEXT_VIEW(appGUI->cnt->contacts_desc_textview), appGUI->cnt->photo_image, GTK_TEXT_WINDOW_TEXT,
1105
appGUI->cnt->contacts_desc_textview->allocation.width-d_photo_width-5, 5);
1106
gtk_widget_show_all(appGUI->cnt->contacts_desc_textview);
1109
g_object_unref (pixbuf);
1114
/*------------------------------------------------------------------------------*/