1 
2 /*
3  * Osmo - a handy personal organizer
4  *
5  * Copyright (C) 2007 Tomasz Maka <pasp@users.sourceforge.net>
6  *
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.
11  *
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.
16  *
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.
20  */
21 
22 #include "about.h"
23 #include "backup.h"
24 #include "contacts.h"
25 #include "i18n.h"
26 #include "contacts_items.h"
27 #include "utils.h"
28 #include "utils_date.h"
29 #include "utils_gui.h"
30 #include "options_prefs.h"
31 #include "preferences_gui.h"
32 #include "stock_icons.h"
33 #include "contacts_birthdays.h"
34 #include "contacts_import.h"
35 #include "contacts_export.h"
36 #include "calendar_utils.h"
37 
38 #ifdef CONTACTS_ENABLED
39 
40 /*============================================================================*/
41 
42 static void
show_preferences_window_cb(GtkToolButton * toolbutton,gpointer data)43 show_preferences_window_cb (GtkToolButton *toolbutton, gpointer data)
44 {
45     GUI *appGUI = (GUI *) data;
46     appGUI->opt->window = opt_create_preferences_window (appGUI);
47     gtk_widget_show (appGUI->opt->window);
48 
49     gint page = gtk_notebook_page_num (GTK_NOTEBOOK (appGUI->opt->notebook), appGUI->opt->contacts);
50     gtk_notebook_set_current_page (GTK_NOTEBOOK (appGUI->opt->notebook), page);
51 }
52 
53 /*------------------------------------------------------------------------------*/
54 
55 
56 void
set_export_active(GUI * appGUI)57 set_export_active (GUI *appGUI) {
58 
59 GtkTreeIter iter;
60 gboolean state;
61 
62     state = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(appGUI->cnt->contacts_filter), &iter);
63     gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->export_toolbar_button), state);
64 }
65 
66 /*------------------------------------------------------------------------------*/
67 
68 gboolean
find_combo_box_focus_cb(GtkWidget * widget,GtkDirectionType * arg1,gpointer user_data)69 find_combo_box_focus_cb (GtkWidget *widget, GtkDirectionType *arg1, gpointer user_data) {
70     return TRUE;
71 }
72 
73 /*------------------------------------------------------------------------------*/
74 
75 void
contacts_panel_close_desc_cb(GtkWidget * widget,gpointer data)76 contacts_panel_close_desc_cb (GtkWidget *widget, gpointer data) {
77     GtkPaned *paned;
78     gint max_position;
79     GUI *appGUI = (GUI *)data;
80 
81     paned = GTK_PANED (appGUI->cnt->contacts_paned);
82     g_object_get(paned, "max-position", &max_position, NULL);
83     gtk_paned_set_position(paned, max_position);
84 }
85 
86 /*------------------------------------------------------------------------------*/
87 
88 gboolean
contacts_list_filter_cb(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)89 contacts_list_filter_cb (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) {
90 
91 const gchar *text;
92 gchar *value = NULL;
93 gint i;
94 guint32 date;
95 gboolean result;
96 
97     GUI *appGUI = (GUI *)data;
98 
99     text = gtk_entry_get_text(GTK_ENTRY(appGUI->cnt->contacts_find_entry));
100 
101     if (text == NULL) {
102         return TRUE;
103     }
104     if (!g_utf8_strlen(text, -1)) {
105         return TRUE;
106     }
107 
108     if (config.find_mode == CONTACTS_FF_ALL_FIELDS) {
109         result = FALSE;
110         for (i = 0; i < CONTACTS_NUM_COLUMNS && !result; i++) {
111 
112             if (i != COLUMN_PHOTO && i != COLUMN_ID) {
113                 if (i == COLUMN_BIRTH_DAY_DATE || i == COLUMN_NAME_DAY_DATE) {
114                     gtk_tree_model_get(model, iter, i, &date, -1);
115                     if (date == 0) {
116                         value = NULL;
117                     } else {
118                         if (i == COLUMN_BIRTH_DAY_DATE) {
119                             value = g_strdup((const gchar *) julian_to_str(date, DATE_FULL, config.override_locale_settings));
120                         } else {
121                             value = g_strdup((const gchar *) julian_to_str(date, DATE_NAME_DAY, config.override_locale_settings));
122                         }
123                     }
124                 } else {
125                     gtk_tree_model_get(model, iter, i, &value, -1);
126                 }
127 
128                 if (value != NULL) {
129                     result = utl_text_strcasestr(value, text);
130                     g_free(value);
131                 }
132             }
133         }
134     } else {
135         if (config.find_mode == CONTACTS_FF_FIRST_NAME) {
136             gtk_tree_model_get(model, iter, COLUMN_FIRST_NAME, &value, -1);
137         } else if (config.find_mode == CONTACTS_FF_LAST_NAME) {
138             gtk_tree_model_get(model, iter, COLUMN_LAST_NAME, &value, -1);
139         } else if (config.find_mode == CONTACTS_FF_TAGS) {
140             gtk_tree_model_get(model, iter, COLUMN_TAGS, &value, -1);
141         }
142 
143         if (value == NULL) {
144             result = FALSE;
145         } else {
146             result = utl_text_strcasestr(value, text);
147         }
148         g_free(value);
149     }
150 
151     return result;
152 }
153 
154 /*------------------------------------------------------------------------------*/
155 
156 void
contacts_select_first_position_in_list(GUI * appGUI)157 contacts_select_first_position_in_list (GUI *appGUI) {
158 
159 GtkTreeIter     iter;
160 GtkTreePath     *path;
161 
162     /* set cursor at first position */
163     if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), &iter) == TRUE) {
164         path = gtk_tree_model_get_path (GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), &iter);
165         if (path != NULL) {
166             gtk_tree_view_set_cursor (GTK_TREE_VIEW (appGUI->cnt->contacts_list), path, NULL, FALSE);
167             gtk_tree_path_free (path);
168         }
169     }
170 }
171 
172 /*------------------------------------------------------------------------------*/
173 
174 void
contacts_item_selected_cb(GtkTreeSelection * selection,GUI * appGUI)175 contacts_item_selected_cb (GtkTreeSelection *selection, GUI *appGUI)
176 {
177     GtkTreeModel *model;
178     GtkTreeIter iter;
179     gint selection_size;
180     gboolean address_available = FALSE, additional_info = FALSE;
181     guint32 date;
182     gchar *fname, *sname, *lname, *html, *photo;
183     gchar tmpbuf[BUFFER_SIZE], htmpbuf[BUFFER_SIZE];
184     gint i;
185 
186     selection_size = gtk_tree_selection_count_selected_rows(selection);
187     if (selection_size > 1) {
188         gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->edit_toolbar_button), FALSE);
189         gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->delete_toolbar_button), TRUE);
190         gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->map_location_toolbar_button), FALSE);
191 
192 #ifdef HAVE_LIBWEBKIT
193         webkit_web_view_load_html(appGUI->cnt->html_webkitview, "", "file://");
194 #endif  /* LIBWEBKIT */
195     } else if (selection_size == 1) {
196         gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->edit_toolbar_button), TRUE);
197         gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->delete_toolbar_button), TRUE);
198 
199         address_available = check_address(HOME_ADDRESS, appGUI);
200         if (address_available == FALSE) {
201             address_available = check_address(WORK_ADDRESS, appGUI);
202         }
203 
204         gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->map_location_toolbar_button), address_available);
205 
206         /****************************************************************/
207 
208         html = g_strdup_printf(
209                 "<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n"
210                 "<style type=\"text/css\">\n"
211                 "body { font-size: %dpx; }\n"
212                 "h1 { font-size: %dpx; font-weight: bold; font-style: italic; }\n"
213                 "pre { white-space: pre; margin-top: 0; margin-left: 2px; margin-bottom: 2px; }\n"
214                 "a { color: %s; }\n"
215                 "table { width: 100%%; }\n"
216                 "td.tag { width: 30%%; }\n"
217                 "td.value { width: 70%%; }\n"
218                 ".tag { font-weight: bold; color: %s; }\n"
219 #ifdef HAVE_LIBWEBKIT
220                 ".photo { position: absolute; top: 4; right: 4; width: %dpx; border: 1px solid #000; float: right; }\n"
221 #endif  /* HAVE_LIBWEBKIT */
222                 "</style>\n</head>\n\n<body>\n",
223                 config.contact_item_font_size, config.contact_name_font_size,
224                 config.contact_link_color, config.contact_tag_color, config.photo_width);
225 
226         /****************************************************************/
227 
228         iter = utl_gui_get_first_selection_iter(selection, &model);
229         gtk_tree_model_get(model, &iter,
230                 COLUMN_FIRST_NAME, &fname,
231                 COLUMN_SECOND_NAME, &sname,
232                 COLUMN_LAST_NAME, &lname,
233                 COLUMN_PHOTO, &photo,
234                 -1);
235 
236         if (!fname) fname = g_strdup("");
237         if (!sname) sname = g_strdup("");
238         if (!lname) lname = g_strdup("");
239 
240         g_snprintf(htmpbuf, BUFFER_SIZE, "<h1>%s %s %s</h1>\n", fname, sname, lname);
241         html = utl_strconcat(html, htmpbuf, NULL);
242         g_free(fname);
243         g_free(sname);
244         g_free(lname);
245 
246         /* insert photo */
247         if (photo != NULL) {
248 #ifdef HAVE_LIBWEBKIT
249             g_snprintf(htmpbuf, BUFFER_SIZE, "<img src=\"file://%s\" alt=\"\" class=\"photo\">", photo);
250 #endif  /* HAVE_LIBWEBKIT */
251             html = utl_strconcat(html, htmpbuf, NULL);
252             g_free(photo);
253         }
254 
255         g_snprintf(htmpbuf, BUFFER_SIZE, "<table>\n");
256         html = utl_strconcat(html, htmpbuf, NULL);
257 
258         for (i = 0; i < CONTACTS_NUM_COLUMNS; i++) {
259             gchar *text;
260             if ((i == COLUMN_ID) ||
261                     (i == COLUMN_PHOTO) ||
262                     (i == COLUMN_FIRST_NAME) ||
263                     (i == COLUMN_SECOND_NAME) ||
264                     (i == COLUMN_LAST_NAME) ||
265                     (i == COLUMN_GROUP))
266                 continue;
267 
268             if (i == COLUMN_BIRTH_DAY_DATE || i == COLUMN_NAME_DAY_DATE) {
269                 gtk_tree_model_get(model, &iter, i, &date, -1);
270                 if (date == 0) {
271                     text = NULL;
272                 } else {
273                     if (i == COLUMN_BIRTH_DAY_DATE) {
274                         text = g_strdup((const gchar *) julian_to_str(date, DATE_FULL, config.override_locale_settings));
275                     } else {
276                         text = g_strdup((const gchar *) julian_to_str(date, DATE_NAME_DAY, config.override_locale_settings));
277                     }
278                 }
279             } else {
280                 gtk_tree_model_get(model, &iter, i, &text, -1);
281             }
282 
283             if (text == NULL || !strlen(text)) {
284                 g_free(text);
285                 continue;
286             }
287 
288             g_snprintf(htmpbuf, BUFFER_SIZE, "<tr>");
289             html = utl_strconcat(html, htmpbuf, NULL);
290 
291             if ((i >= COLUMN_HOME_PHONE_2 && i <= COLUMN_HOME_PHONE_4) ||
292                     (i >= COLUMN_WORK_PHONE_2 && i <= COLUMN_WORK_PHONE_4) ||
293                     (i >= COLUMN_CELL_PHONE_2 && i <= COLUMN_CELL_PHONE_4) ||
294                     (i >= COLUMN_EMAIL_2 && i <= COLUMN_EMAIL_4) ||
295                     (i >= COLUMN_WWW_2 && i <= COLUMN_WWW_4)) {
296                 tmpbuf[0] = '\0';
297             } else {
298                 g_snprintf(tmpbuf, BUFFER_SIZE, "%s:", gettext(appGUI->cnt->contact_fields_tags_name[2 * i]));
299             }
300 
301             if (i == COLUMN_INFO) {
302 
303                 gchar *tmp = utl_text_to_html(text, FALSE, TRUE);
304 
305                 if (tmp != NULL) {
306                     additional_info = TRUE;
307 
308                     gchar *tmp2 = utl_text_replace(tmp, REGEX_URL, "<a href=\"\\0\">\\0</a>");
309                     g_free(tmp);
310                     gchar *tmp3 = utl_text_replace(tmp2, REGEX_EMAIL, "<a href=\"mailto:\\0\">\\0</a>");
311                     g_free(tmp2);
312 
313                     g_snprintf(htmpbuf, BUFFER_SIZE,
314                             "<td colspan=\"2\" class=\"tag\">%s</td></tr></table>\n<pre>%s</pre>\n", tmpbuf, tmp3);
315 
316                     html = utl_strconcat(html, htmpbuf, NULL);
317                     g_free(tmp3);
318                 }
319 
320             } else {
321 
322                 g_snprintf(htmpbuf, BUFFER_SIZE, "<td class=\"tag\">%s</td>", tmpbuf);
323                 html = utl_strconcat(html, htmpbuf, NULL);
324 
325             }
326 
327             if (i == COLUMN_BLOG || (i >= COLUMN_EMAIL_1 && i <= COLUMN_EMAIL_4) || (i >= COLUMN_WWW_1 && i <= COLUMN_WWW_4)) {
328 
329                 gchar *protocol;
330                 if (i >= COLUMN_EMAIL_1 && i <= COLUMN_EMAIL_4) {
331                     protocol = "mailto:";
332                 } else if (!utl_text_match(text, REGEX_URI_PROTO)) {
333                     protocol = "http://";
334                 } else {
335                     protocol = "";
336                 }
337                 g_snprintf(htmpbuf, BUFFER_SIZE, "<td class=\"value\"><a href=\"%s%s\">%s</a></td></tr>\n", protocol, text, text);
338                 html = utl_strconcat(html, htmpbuf, NULL);
339 
340             } else if (i != COLUMN_INFO) {
341 
342                 g_snprintf(htmpbuf, BUFFER_SIZE, "<td class=\"value\">%s</td></tr>\n", text);
343                 html = utl_strconcat(html, htmpbuf, NULL);
344 
345             }
346             g_free(text);
347         }
348 
349         if (additional_info == TRUE) {
350             g_snprintf(htmpbuf, BUFFER_SIZE, "</body>\n</html>\n");
351         } else {
352             g_snprintf(htmpbuf, BUFFER_SIZE, "</table>\n</body>\n</html>\n");
353         }
354         html = utl_strconcat(html, htmpbuf, NULL);
355 
356 #ifdef HAVE_LIBWEBKIT
357         webkit_web_view_load_html(appGUI->cnt->html_webkitview, html, "file://");
358 #endif  /* LIBWEBKIT */
359 
360         g_free(html);
361     } else {
362 
363         gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->edit_toolbar_button), FALSE);
364         gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->delete_toolbar_button), FALSE);
365         gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->map_location_toolbar_button), FALSE);
366 
367 #ifdef HAVE_LIBWEBKIT
368         webkit_web_view_load_html(appGUI->cnt->html_webkitview, "", "file://");
369 #endif  /* LIBWEBKIT */
370     }
371     set_export_active(appGUI);
372 }
373 
374 /*------------------------------------------------------------------------------*/
375 
376 gboolean
contacts_search_entry_changed_cb(GtkEditable * editable,gpointer user_data)377 contacts_search_entry_changed_cb (GtkEditable *editable, gpointer user_data) {
378     GUI *appGUI = (GUI *)user_data;
379 
380     gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(appGUI->cnt->contacts_filter));
381     set_export_active (appGUI);
382 
383     return FALSE;
384 }
385 
386 /*------------------------------------------------------------------------------*/
387 
388 void
contacts_find_type_selected_cb(GtkComboBox * widget,gpointer user_data)389 contacts_find_type_selected_cb (GtkComboBox *widget, gpointer user_data) {
390 
391 GtkTreeIter iter;
392 gboolean has_next;
393 
394     GUI *appGUI = (GUI *)user_data;
395 
396     config.find_mode = gtk_combo_box_get_active (widget);
397 
398     if(strlen(gtk_entry_get_text (GTK_ENTRY(appGUI->cnt->contacts_find_entry)))) {
399         gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(appGUI->cnt->contacts_filter));
400 
401         has_next = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (appGUI->cnt->contacts_filter), &iter);
402         gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->export_toolbar_button), has_next);
403         if (has_next) {
404             GtkTreePath *path = gtk_tree_path_new_first();
405             if (path != NULL) {
406                 gtk_tree_view_set_cursor(GTK_TREE_VIEW(appGUI->cnt->contacts_list), path, NULL, FALSE);
407             }
408             gtk_tree_path_free(path);
409         }
410     }
411 }
412 
413 /*------------------------------------------------------------------------------*/
414 
415 gint
contacts_column_sort_function(GtkTreeModel * model,GtkTreeIter * iter_a,GtkTreeIter * iter_b,gint sort_column,GUI * appGUI)416 contacts_column_sort_function (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gint sort_column, GUI *appGUI)
417 {
418     gchar *last_name_a, *last_name_b;
419     gchar *group_a, *group_b;
420     gchar *first_name_a, *first_name_b;
421     gint diff;
422 
423     if (iter_a == NULL || iter_b == NULL) {
424         return 0;
425     }
426 
427 
428     switch(sort_column) {
429         case COLUMN_GROUP:
430             gtk_tree_model_get(model, iter_a, COLUMN_GROUP, &group_a, -1);
431             gtk_tree_model_get(model, iter_b, COLUMN_GROUP, &group_b, -1);
432             diff = utl_text_strcmp(group_a, group_b);
433             g_free(group_a);
434             g_free(group_b);
435             break;
436         case COLUMN_FIRST_NAME:
437             gtk_tree_model_get(model, iter_a, COLUMN_FIRST_NAME, &first_name_a, -1);
438             gtk_tree_model_get(model, iter_b, COLUMN_FIRST_NAME, &first_name_b, -1);
439             diff = utl_text_strcmp(first_name_a, first_name_b);
440             g_free(first_name_a);
441             g_free(first_name_b);
442             break;
443         case COLUMN_LAST_NAME:
444             gtk_tree_model_get(model, iter_a, COLUMN_LAST_NAME, &last_name_a, -1);
445             gtk_tree_model_get(model, iter_b, COLUMN_LAST_NAME, &last_name_b, -1);
446             diff = utl_text_strcmp(last_name_a, last_name_b);
447             g_free(last_name_a);
448             g_free(last_name_b);
449             break;
450         default:
451             diff = 0;
452     }
453     return diff;
454 }
455 
456 /*------------------------------------------------------------------------------*/
457 
458 gint
contacts_column_sort_by_group_function(GtkTreeModel * model,GtkTreeIter * iter_a,GtkTreeIter * iter_b,gpointer user_data)459 contacts_column_sort_by_group_function (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer user_data)
460 {
461     return contacts_column_sort_function(model, iter_a, iter_b, COLUMN_GROUP, (GUI *)user_data);
462 }
463 
464 /*------------------------------------------------------------------------------*/
465 
466 gint
contacts_column_sort_by_first_name_function(GtkTreeModel * model,GtkTreeIter * iter_a,GtkTreeIter * iter_b,gpointer user_data)467 contacts_column_sort_by_first_name_function (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer user_data)
468 {
469     return contacts_column_sort_function(model, iter_a, iter_b, COLUMN_FIRST_NAME, (GUI *)user_data);
470 }
471 
472 /*------------------------------------------------------------------------------*/
473 
474 gint
contacts_column_sort_by_last_name_function(GtkTreeModel * model,GtkTreeIter * iter_a,GtkTreeIter * iter_b,gpointer user_data)475 contacts_column_sort_by_last_name_function (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer user_data)
476 {
477     return contacts_column_sort_function(model, iter_a, iter_b, COLUMN_LAST_NAME, (GUI *)user_data);
478 }
479 
480 
481 /*------------------------------------------------------------------------------*/
482 
contacts_sort_column_changed_cb(GtkTreeSortable * sortable,gpointer user_data)483 void contacts_sort_column_changed_cb (GtkTreeSortable *sortable, gpointer user_data)
484 {
485     GtkSortType sort_order;
486 
487     gtk_tree_sortable_get_sort_column_id(sortable, &config.contacts_sorting_column, &sort_order);
488     config.contacts_sorting_order = sort_order;
489 }
490 /*------------------------------------------------------------------------------*/
491 
492 static void
contacts_add_item_cb(GtkToolButton * toolbutton,gpointer data)493 contacts_add_item_cb (GtkToolButton *toolbutton, gpointer data) {
494 
495     GUI *appGUI = (GUI *)data;
496     contacts_add_edit_dialog_show (FALSE, appGUI);
497 }
498 
499 /*------------------------------------------------------------------------------*/
500 
501 static void
contacts_edit_item_cb(GtkToolButton * toolbutton,gpointer data)502 contacts_edit_item_cb (GtkToolButton *toolbutton, gpointer data) {
503 
504     GUI *appGUI = (GUI *)data;
505 
506     if (gtk_tree_selection_count_selected_rows (appGUI->cnt->contacts_list_selection) == 1) {
507         contacts_add_edit_dialog_show (TRUE, appGUI);
508     }
509 }
510 
511 /*------------------------------------------------------------------------------*/
512 
513 static void
contacts_remove_item_cb(GtkToolButton * toolbutton,gpointer data)514 contacts_remove_item_cb (GtkToolButton *toolbutton, gpointer data) {
515 
516     GUI *appGUI = (GUI *)data;
517     contacts_remove_dialog_show(appGUI);
518 }
519 
520 /*------------------------------------------------------------------------------*/
521 
522 static void
contacts_birthdays_item_cb(GtkToolButton * toolbutton,gpointer data)523 contacts_birthdays_item_cb (GtkToolButton *toolbutton, gpointer data) {
524 
525     GUI *appGUI = (GUI *)data;
526     contacts_create_birthdays_window (appGUI);
527 }
528 
529 /*------------------------------------------------------------------------------*/
530 
531 static void
contacts_map_location_cb(GtkToolButton * toolbutton,gpointer data)532 contacts_map_location_cb (GtkToolButton *toolbutton, gpointer data) {
533 
534 gint response = -1;
535 GtkWidget *info_dialog = NULL;
536 GtkWidget *hbox;
537 GtkWidget *home_addr_radiobutton;
538 GtkWidget *work_addr_radiobutton;
539 GSList *hw_radiobutton_group = NULL;
540 
541 
542     GUI *appGUI = (GUI *)data;
543 
544     if (gtk_tree_selection_count_selected_rows (appGUI->cnt->contacts_list_selection) == 1) {
545 
546         if (check_address (HOME_ADDRESS, appGUI) && check_address (WORK_ADDRESS, appGUI)) {
547             GtkWidget *message_area;
548 
549             info_dialog = gtk_message_dialog_new (GTK_WINDOW(appGUI->main_window),
550                                                   GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
551                                                   GTK_MESSAGE_INFO, GTK_BUTTONS_OK_CANCEL,
552                                                   "\n%s:", _("Please select address"));
553 
554             gtk_window_set_title(GTK_WINDOW(info_dialog), _("Information"));
555             gtk_widget_show (info_dialog);
556 
557             hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
558             message_area = gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(info_dialog));
559             gtk_box_pack_start (GTK_BOX(message_area), hbox, FALSE, TRUE, 2);
560             gtk_widget_show (hbox);
561 
562             work_addr_radiobutton = gtk_radio_button_new_with_mnemonic (NULL, _("Work"));
563             gtk_widget_show (work_addr_radiobutton);
564             gtk_box_pack_end (GTK_BOX(hbox), work_addr_radiobutton, FALSE, TRUE, 2);
565             gtk_radio_button_set_group (GTK_RADIO_BUTTON (work_addr_radiobutton), hw_radiobutton_group);
566             hw_radiobutton_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (work_addr_radiobutton));
567 
568             home_addr_radiobutton = gtk_radio_button_new_with_mnemonic (NULL, _("Home"));
569             gtk_widget_show (home_addr_radiobutton);
570             gtk_box_pack_end (GTK_BOX(hbox), home_addr_radiobutton, FALSE, TRUE, 2);
571             gtk_radio_button_set_group (GTK_RADIO_BUTTON (home_addr_radiobutton), hw_radiobutton_group);
572             hw_radiobutton_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (home_addr_radiobutton));
573 
574             gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (home_addr_radiobutton), TRUE);
575 
576             response = gtk_dialog_run(GTK_DIALOG(info_dialog));
577 
578             if (response == GTK_RESPONSE_OK) {
579                 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (home_addr_radiobutton)) == TRUE) {
580                     show_contact_location_on_map (HOME_ADDRESS, appGUI);
581                 } else {
582                     show_contact_location_on_map (WORK_ADDRESS, appGUI);
583                 }
584             }
585 
586             gtk_widget_destroy(info_dialog);
587 
588         } else {
589             if (check_address (HOME_ADDRESS, appGUI)) {
590                 show_contact_location_on_map (HOME_ADDRESS, appGUI);
591             } else {
592                 show_contact_location_on_map (WORK_ADDRESS, appGUI);
593             }
594         }
595     }
596 }
597 
598 /*------------------------------------------------------------------------------*/
599 
600 static void
contacts_export_items_cb(GtkToolButton * toolbutton,gpointer data)601 contacts_export_items_cb (GtkToolButton *toolbutton, gpointer data) {
602 
603     GUI *appGUI = (GUI *)data;
604     contacts_create_export_window(appGUI);
605 }
606 
607 /*------------------------------------------------------------------------------*/
608 
609 static void
contacts_import_items_cb(GtkToolButton * toolbutton,gpointer data)610 contacts_import_items_cb (GtkToolButton *toolbutton, gpointer data) {
611 
612     GUI *appGUI = (GUI *)data;
613     import_contacts_from_csv_file (appGUI);
614 }
615 
616 /*------------------------------------------------------------------------------*/
617 
618 gint
contacts_list_dbclick_cb(GtkWidget * widget,GdkEventButton * event,gpointer func_data)619 contacts_list_dbclick_cb(GtkWidget * widget, GdkEventButton * event, gpointer func_data) {
620 
621     GUI *appGUI = (GUI *)func_data;
622 
623     if ((event->type==GDK_2BUTTON_PRESS) && (event->button == 1)) {
624         contacts_edit_item_cb (NULL, appGUI);
625         return TRUE;
626     }
627 
628     return FALSE;
629 }
630 
631 /*------------------------------------------------------------------------------*/
632 
633 void
contacts_selection_activate(gboolean active,GUI * appGUI)634 contacts_selection_activate (gboolean active, GUI *appGUI) {
635     if (active == TRUE) {
636         g_signal_connect(G_OBJECT(appGUI->cnt->contacts_list_selection), "changed",
637                          G_CALLBACK(contacts_item_selected_cb), appGUI);
638     } else {
639         g_signal_handlers_disconnect_by_func (G_OBJECT (appGUI->cnt->contacts_list_selection),
640                                               G_CALLBACK (contacts_item_selected_cb), appGUI);
641     }
642 }
643 
644 /*------------------------------------------------------------------------------*/
645 
646 void
store_contact_columns_info(GUI * appGUI)647 store_contact_columns_info (GUI *appGUI) {
648 
649     gint n;
650 
651     config.contacts_column_idx_0 = utl_gui_get_column_position (appGUI->cnt->contacts_columns[COLUMN_GROUP],
652                                                                 GTK_TREE_VIEW(appGUI->cnt->contacts_list), MAX_VISIBLE_CONTACT_COLUMNS, appGUI);
653     config.contacts_column_idx_1 = utl_gui_get_column_position (appGUI->cnt->contacts_columns[COLUMN_FIRST_NAME],
654                                                                 GTK_TREE_VIEW(appGUI->cnt->contacts_list), MAX_VISIBLE_CONTACT_COLUMNS, appGUI);
655     config.contacts_column_idx_2 = utl_gui_get_column_position (appGUI->cnt->contacts_columns[COLUMN_LAST_NAME],
656                                                                 GTK_TREE_VIEW(appGUI->cnt->contacts_list), MAX_VISIBLE_CONTACT_COLUMNS, appGUI);
657 
658     n = gtk_tree_view_column_get_width(gtk_tree_view_get_column (GTK_TREE_VIEW(appGUI->cnt->contacts_list), 0));
659     if (n > 1) {
660         config.contacts_column_idx_0_width = n;
661     }
662     n = gtk_tree_view_column_get_width(gtk_tree_view_get_column (GTK_TREE_VIEW(appGUI->cnt->contacts_list), 1));
663     if (n > 1) {
664         config.contacts_column_idx_1_width = n;
665     }
666     n = gtk_tree_view_column_get_width(gtk_tree_view_get_column (GTK_TREE_VIEW(appGUI->cnt->contacts_list), 2));
667     if (n > 1) {
668         config.contacts_column_idx_2_width = n;
669     }
670 }
671 
672 /*------------------------------------------------------------------------------*/
673 
674 void
set_contacts_columns_width(GUI * appGUI)675 set_contacts_columns_width (GUI *appGUI) {
676 
677     GtkTreeViewColumn   *col;
678     gint w;
679 
680     w = 2 * utl_gui_get_sw_vscrollbar_width (appGUI->cnt->scrolled_win);
681 
682     col = gtk_tree_view_get_column (GTK_TREE_VIEW(appGUI->cnt->contacts_list), COLUMN_GROUP);
683     if (gtk_tree_view_column_get_visible(col) == TRUE && config.contacts_column_idx_0_width > 0) {
684         gtk_tree_view_column_set_fixed_width (col, config.contacts_column_idx_0_width);
685     }
686     col = gtk_tree_view_get_column (GTK_TREE_VIEW(appGUI->cnt->contacts_list), COLUMN_FIRST_NAME);
687     if (gtk_tree_view_column_get_visible(col) == TRUE && config.contacts_column_idx_1_width > 0) {
688         gtk_tree_view_column_set_fixed_width (col, config.contacts_column_idx_1_width);
689     }
690     col = gtk_tree_view_get_column (GTK_TREE_VIEW(appGUI->cnt->contacts_list), COLUMN_LAST_NAME);
691     if (gtk_tree_view_column_get_visible(col) == TRUE && config.contacts_column_idx_2_width > w) {
692         gtk_tree_view_column_set_fixed_width (col, config.contacts_column_idx_2_width - w);
693     }
694 }
695 
696 /*------------------------------------------------------------------------------*/
697 
698 void
cnt_clear_find_cb(GtkWidget * widget,gpointer user_data)699 cnt_clear_find_cb (GtkWidget *widget, gpointer user_data)
700 {
701     GUI *appGUI = (GUI *) user_data;
702     if (strlen(gtk_entry_get_text(GTK_ENTRY(appGUI->cnt->contacts_find_entry)))) {
703         gtk_entry_set_text(GTK_ENTRY(appGUI->cnt->contacts_find_entry), "");
704     }
705     gtk_widget_grab_focus (appGUI->cnt->contacts_find_entry);
706 }
707 
708 /*------------------------------------------------------------------------------*/
709 
710 static void
create_contact_fields(GUI * appGUI)711 create_contact_fields(GUI *appGUI)
712 {
713 static gchar *contact_fields_tags_name[] = {
714     N_("Group"), "group",
715     N_("First name"), "first_name", N_("Last name"), "last_name",
716     N_("Second name"), "second_name",
717     N_("Nickname"), "nickname", N_("Tags"), "tags",
718     N_("Birthday date"), "birthday_date", N_("Name day date"), "name_day_date",
719 
720     /*--------------------------------------------------*/
721     N_("Home address"), "home_address", N_("Home postcode"), "home_postcode", N_("Home city"),
722     "home_city", N_("Home state"), "home_state", N_("Home country"), "home_country",
723     /*--------------------------------------------------*/
724 
725     N_("Organization"), "organization", N_("Department"), "department",
726 
727     /*--------------------------------------------------*/
728     N_("Work address"), "work_address", N_("Work postcode"), "work_postcode", N_("Work city"),
729     "work_city", N_("Work state"), "work_state", N_("Work country"), "work_country",
730     /*--------------------------------------------------*/
731 
732     N_("Fax"), "work_fax",
733 
734     /*--------------------------------------------------*/
735     N_("Home phone"), "home_phone_1", N_("Home phone 2"), "home_phone_2",
736     N_("Home phone 3"), "home_phone_3", N_("Home phone 4"), "home_phone_4",
737     N_("Work phone"), "work_phone_1", N_("Work phone 2"), "work_phone_2",
738     N_("Work phone 3"), "work_phone_3", N_("Work phone 4"), "work_phone_4",
739     N_("Cell phone"), "cell_phone_1", N_("Cell phone 2"), "cell_phone_2",
740     N_("Cell phone 3"), "cell_phone_3", N_("Cell phone 4"), "cell_phone_4",
741     N_("E-Mail"), "email_1", N_("E-Mail 2"), "email_2", N_("E-Mail 3"), "email_3",
742     N_("E-Mail 4"), "email_4", N_("WWW"), "www_1", N_("WWW 2"), "www_2", N_("WWW 3"), "www_3",
743     N_("WWW 4"), "www_4",
744     /*--------------------------------------------------*/
745 
746     N_("IM Gadu-Gadu"), "im_gg", N_("IM Yahoo"), "im_yahoo", N_("IM MSN"), "im_msn",
747     N_("IM ICQ"), "im_icq", N_("IM AOL"), "im_aol",
748     N_("IM Jabber"), "im_jabber", N_("IM Skype"), "im_skype", N_("IM Tlen"), "im_tlen",
749     N_("Blog"), "blog", N_("Photo"), "photo_path", N_("Additional info"), "additional_info", "ID", "id"
750 };
751 
752     appGUI->cnt->contact_fields_tags_name = contact_fields_tags_name;
753 }
754 
755 /*------------------------------------------------------------------------------*/
756 
757 void
create_contacts_list_store(GUI * appGUI)758 create_contacts_list_store(GUI* appGUI)
759 {
760     GType contact_columns_types[CONTACTS_NUM_COLUMNS];
761     gint i;
762 
763     for(i=0; i< CONTACTS_NUM_COLUMNS; i++) {
764         if (i == COLUMN_BIRTH_DAY_DATE || i == COLUMN_NAME_DAY_DATE || i == COLUMN_ID) {
765             contact_columns_types[i] = G_TYPE_UINT;
766         } else {
767             contact_columns_types[i] = G_TYPE_STRING;
768         }
769     }
770     appGUI->cnt->contacts_list_store = gtk_list_store_newv(CONTACTS_NUM_COLUMNS, &contact_columns_types[0]);
771 }
772 /*------------------------------------------------------------------------------*/
773 
774 #if defined(BACKUP_SUPPORT) && defined(HAVE_LIBGRINGOTTS)
775 
776 static void
button_create_backup_cb(GtkToolButton * toolbutton,gpointer data)777 button_create_backup_cb(GtkToolButton *toolbutton, gpointer data) {
778     GUI *appGUI = (GUI *) data;
779     backup_create(appGUI);
780 }
781 
782 static void
button_restore_backup_cb(GtkToolButton * toolbutton,gpointer data)783 button_restore_backup_cb(GtkToolButton *toolbutton, gpointer data) {
784     GUI *appGUI = (GUI *) data;
785     backup_restore(appGUI);
786 }
787 
788 #endif  /* BACKUP_SUPPORT && HAVE_LIBGRINGOTTS */
789 
790 /*------------------------------------------------------------------------------*/
791 
792 void
contacts_paned_position_change_cb(GObject * gobject,GParamSpec * pspec,GUI * appGUI)793 contacts_paned_position_change_cb (GObject *gobject, GParamSpec *pspec, GUI *appGUI)
794 {
795     config.contacts_pane_pos = gtk_paned_get_position (GTK_PANED (appGUI->cnt->contacts_paned));
796 }
797 
798 /*------------------------------------------------------------------------------*/
799 
800 void
gui_create_contacts(GUI * appGUI)801 gui_create_contacts(GUI *appGUI) {
802 
803 GtkWidget           *vbox1;
804 GtkWidget           *vbox2;
805 GtkWidget           *vbox3;
806 GtkWidget           *hbox2;
807 GtkWidget           *frame;
808 GtkWidget           *hseparator;
809 GtkWidget           *label;
810 GtkWidget           *top_viewport;
811 GtkWidget           *bottom_viewport;
812 GtkWidget           *close_button;
813 GtkCellRenderer     *renderer[CONTACTS_NUM_COLUMNS];
814 gint                i, n;
815 gchar tmpbuf[BUFFER_SIZE];
816 
817 gint columns_order[MAX_VISIBLE_CONTACT_COLUMNS];
818 
819 gint co_columns[MAX_VISIBLE_CONTACT_COLUMNS] = {
820         COLUMN_GROUP, COLUMN_FIRST_NAME, COLUMN_LAST_NAME
821 };
822 
823     create_contact_fields(appGUI);
824 
825     vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
826     gtk_widget_show (vbox1);
827     gtk_container_set_border_width (GTK_CONTAINER (vbox1), 0);
828     g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s</b>", _("Contacts"));
829     gui_add_to_notebook (vbox1, tmpbuf, appGUI);
830 
831     appGUI->cnt->vbox = GTK_BOX(vbox1);
832 
833     if (config.hide_contacts == TRUE) {
834         gtk_widget_hide(GTK_WIDGET(appGUI->cnt->vbox));
835     }
836 
837     /*-------------------------------------------------------------------------------------*/
838     appGUI->cnt->contacts_toolbar = GTK_TOOLBAR(gtk_toolbar_new());
839     gtk_box_pack_start(GTK_BOX(vbox1), GTK_WIDGET(appGUI->cnt->contacts_toolbar), FALSE, FALSE, 0);
840 
841     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, gui_create_toolbar_button(appGUI, OSMO_STOCK_CONTACTS_ADD, _("New contact"), contacts_add_item_cb), -1);
842     appGUI->cnt->edit_toolbar_button = gui_create_toolbar_button(appGUI, OSMO_STOCK_CONTACTS_EDIT, _("Edit contact"), contacts_edit_item_cb);
843     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, appGUI->cnt->edit_toolbar_button, -1);
844     appGUI->cnt->delete_toolbar_button = gui_create_toolbar_button(appGUI, OSMO_STOCK_CONTACTS_REMOVE, _("Remove contact"), contacts_remove_item_cb);
845     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, appGUI->cnt->delete_toolbar_button, -1);
846     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, gtk_separator_tool_item_new(), -1);
847     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, gui_create_toolbar_button(appGUI, OSMO_STOCK_CONTACTS_BIRTHDAYS, _("Show birthdays"), contacts_birthdays_item_cb), -1);
848     appGUI->cnt->map_location_toolbar_button = gui_create_toolbar_button(appGUI, OSMO_STOCK_OPEN_URL, _("Show contact location on the map"), contacts_map_location_cb);
849     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, appGUI->cnt->map_location_toolbar_button, -1);
850     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, gtk_separator_tool_item_new(), -1);
851     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, gui_create_toolbar_button(appGUI, OSMO_STOCK_CONTACTS_IMPORT, _("Import contacts"), contacts_import_items_cb), -1);
852     appGUI->cnt->export_toolbar_button = gui_create_toolbar_button(appGUI, OSMO_STOCK_CONTACTS_EXPORT, _("Export contacts"), contacts_export_items_cb);
853     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, appGUI->cnt->export_toolbar_button, -1);
854     gui_append_toolbar_spring(appGUI->cnt->contacts_toolbar);
855 #if defined(BACKUP_SUPPORT) && defined(HAVE_LIBGRINGOTTS)
856     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, gtk_separator_tool_item_new(), -1);
857     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, gui_create_toolbar_button(appGUI, OSMO_STOCK_BACKUP, _("Backup data"), button_create_backup_cb), -1);
858     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, gui_create_toolbar_button(appGUI, OSMO_STOCK_RESTORE, _("Restore data"), button_restore_backup_cb), -1);
859     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, gtk_separator_tool_item_new(), -1);
860 #endif  /* BACKUP_SUPPORT && HAVE_LIBGRINGOTTS */
861     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, gui_create_toolbar_button(appGUI, OSMO_STOCK_PREFERENCES, _("Preferences"), show_preferences_window_cb), -1);
862     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, gui_create_toolbar_button(appGUI, OSMO_STOCK_ABOUT, _("About"), gui_show_about_window_cb), -1);
863     appGUI->cnt->quit_toolbar_button = gui_create_toolbar_button(appGUI, "application-exit", _("Quit"), gui_quit_osmo_cb);
864     gtk_toolbar_insert(appGUI->cnt->contacts_toolbar, appGUI->cnt->quit_toolbar_button, -1);
865 
866     gtk_toolbar_set_style (appGUI->cnt->contacts_toolbar, GTK_TOOLBAR_ICONS);
867     gtk_toolbar_set_icon_size(appGUI->cnt->contacts_toolbar, GTK_ICON_SIZE_LARGE_TOOLBAR);
868     gtk_widget_show_all(GTK_WIDGET(appGUI->cnt->contacts_toolbar));
869 
870     /*-------------------------------------------------------------------------------------*/
871 
872     gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->edit_toolbar_button), FALSE);
873     gtk_widget_set_sensitive(GTK_WIDGET(appGUI->cnt->delete_toolbar_button), FALSE);
874 
875 /******************************************************************************************/
876 
877     if (!config.gui_layout) {
878         appGUI->cnt->contacts_paned = gtk_paned_new(GTK_ORIENTATION_VERTICAL );
879     } else {
880         appGUI->cnt->contacts_paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
881     }
882 
883     gtk_widget_show (appGUI->cnt->contacts_paned);
884     gtk_box_pack_start(GTK_BOX(vbox1), appGUI->cnt->contacts_paned, TRUE, TRUE, 0);
885 
886     top_viewport = gtk_viewport_new (NULL, NULL);
887     gtk_widget_show (top_viewport);
888     gtk_viewport_set_shadow_type (GTK_VIEWPORT (top_viewport), GTK_SHADOW_NONE);
889     gtk_paned_pack1 (GTK_PANED (appGUI->cnt->contacts_paned), top_viewport, FALSE, TRUE);
890 
891     vbox3 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
892     gtk_widget_show (vbox3);
893     gtk_container_add (GTK_CONTAINER (top_viewport), vbox3);
894 	gtk_widget_set_margin_left (vbox3, 8);
895 	gtk_widget_set_margin_right (vbox3, 8);
896 	gtk_widget_set_margin_bottom (vbox3, 8);
897 
898     hseparator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
899     gtk_widget_show (hseparator);
900     gtk_box_pack_start (GTK_BOX (vbox3), hseparator, FALSE, FALSE, 6);
901 
902     g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s:</b>", _("Search"));
903     label = gtk_label_new (tmpbuf);
904     gtk_widget_show (label);
905     gtk_label_set_use_markup (GTK_LABEL(label), TRUE);
906     gtk_box_pack_start (GTK_BOX (vbox3), label, FALSE, FALSE, 0);
907     gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
908     gtk_widget_set_halign(label, GTK_ALIGN_START);
909 
910     hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
911     gtk_widget_show (hbox2);
912     gtk_box_pack_start (GTK_BOX (vbox3), hbox2, FALSE, TRUE, 0);
913 
914     appGUI->cnt->contacts_find_entry = gtk_entry_new();
915     gtk_entry_set_max_length(GTK_ENTRY(appGUI->cnt->contacts_find_entry), 128);
916     gtk_widget_show (appGUI->cnt->contacts_find_entry);
917     g_signal_connect (G_OBJECT(appGUI->cnt->contacts_find_entry), "changed",
918                         G_CALLBACK(contacts_search_entry_changed_cb), appGUI);
919     gtk_box_pack_start (GTK_BOX (hbox2), appGUI->cnt->contacts_find_entry, TRUE, TRUE, 0);
920 
921     appGUI->cnt->contacts_find_clear_button = gtk_button_new_from_icon_name ("edit-clear", GTK_ICON_SIZE_BUTTON);
922     gtk_widget_show (appGUI->cnt->contacts_find_clear_button);
923     gtk_widget_set_can_focus (appGUI->cnt->contacts_find_clear_button, FALSE);
924     gtk_button_set_relief (GTK_BUTTON(appGUI->cnt->contacts_find_clear_button), GTK_RELIEF_NONE);
925     if (config.enable_tooltips) {
926         gtk_widget_set_tooltip_text (appGUI->cnt->contacts_find_clear_button, _("Clear"));
927     }
928     g_signal_connect (G_OBJECT (appGUI->cnt->contacts_find_clear_button), "clicked",
929                         G_CALLBACK (cnt_clear_find_cb), appGUI);
930     gtk_box_pack_start (GTK_BOX (hbox2), appGUI->cnt->contacts_find_clear_button, FALSE, FALSE, 0);
931 
932     appGUI->cnt->contacts_find_combobox = gtk_combo_box_text_new ();
933     gtk_widget_show (appGUI->cnt->contacts_find_combobox);
934     gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (appGUI->cnt->contacts_find_combobox), FALSE);
935     gtk_box_pack_start (GTK_BOX (hbox2), appGUI->cnt->contacts_find_combobox, FALSE, FALSE, 0);
936     g_signal_connect (G_OBJECT (appGUI->cnt->contacts_find_combobox), "changed",
937                       G_CALLBACK (contacts_find_type_selected_cb), appGUI);
938     g_signal_connect(G_OBJECT(appGUI->cnt->contacts_find_combobox), "focus",
939                      G_CALLBACK(find_combo_box_focus_cb), appGUI);
940     gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (appGUI->cnt->contacts_find_combobox), NULL, _("First Name"));
941     gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (appGUI->cnt->contacts_find_combobox), NULL, _("Last Name"));
942     gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (appGUI->cnt->contacts_find_combobox), NULL, _("Tags"));
943     gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (appGUI->cnt->contacts_find_combobox), NULL, _("All fields"));
944 
945     hseparator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
946     gtk_widget_show (hseparator);
947     gtk_box_pack_start (GTK_BOX (vbox3), hseparator, FALSE, FALSE, 6);
948 
949     appGUI->cnt->scrolled_win = gtk_scrolled_window_new (NULL, NULL);
950     gtk_widget_show (appGUI->cnt->scrolled_win);
951     gtk_box_pack_start (GTK_BOX (vbox3), appGUI->cnt->scrolled_win, TRUE, TRUE, 0);
952 
953     gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (appGUI->cnt->scrolled_win), GTK_SHADOW_IN);
954     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (appGUI->cnt->scrolled_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
955 
956     create_contacts_list_store(appGUI);
957 
958     appGUI->cnt->contacts_filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(appGUI->cnt->contacts_list_store), NULL);
959     gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER(appGUI->cnt->contacts_filter),
960                                             (GtkTreeModelFilterVisibleFunc)contacts_list_filter_cb,
961                                             appGUI, NULL);
962 
963     appGUI->cnt->contacts_sort = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(appGUI->cnt->contacts_filter));
964 
965     appGUI->cnt->contacts_list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(appGUI->cnt->contacts_sort));
966     gtk_widget_show (appGUI->cnt->contacts_list);
967     gtk_widget_set_can_default (appGUI->cnt->contacts_list, TRUE);
968     gtk_tree_view_set_enable_search (GTK_TREE_VIEW(appGUI->cnt->contacts_list), FALSE);
969 
970     g_signal_connect(G_OBJECT(appGUI->cnt->contacts_list), "button_press_event",
971                      G_CALLBACK(contacts_list_dbclick_cb), appGUI);
972 
973     appGUI->cnt->contacts_list_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (appGUI->cnt->contacts_list));
974     gtk_tree_selection_set_mode (appGUI->cnt->contacts_list_selection, GTK_SELECTION_MULTIPLE);
975     contacts_selection_activate (TRUE, appGUI);
976 
977     /* columns setup */
978 
979     for (i = COLUMN_GROUP; i < CONTACTS_NUM_COLUMNS; i++) {
980         renderer[i] = gtk_cell_renderer_text_new();
981         appGUI->cnt->contacts_columns[i] = gtk_tree_view_column_new_with_attributes(gettext(appGUI->cnt->contact_fields_tags_name[i*2]),
982                                                               renderer[i], "text", i, NULL);
983         gtk_tree_view_append_column (GTK_TREE_VIEW(appGUI->cnt->contacts_list), appGUI->cnt->contacts_columns[i]);
984 
985         if(i != COLUMN_FIRST_NAME && i != COLUMN_LAST_NAME && i != COLUMN_GROUP) {
986             gtk_tree_view_column_set_visible (appGUI->cnt->contacts_columns[i], FALSE);
987         } else {
988 
989             if (config.hide_group_column == TRUE && i == COLUMN_GROUP) {
990                 gtk_tree_view_column_set_visible (appGUI->cnt->contacts_columns[i], FALSE);
991             }
992 
993             gtk_tree_view_column_set_reorderable (appGUI->cnt->contacts_columns[i], TRUE);
994             gtk_tree_view_column_set_resizable (appGUI->cnt->contacts_columns[i], TRUE);
995             gtk_tree_view_column_set_sizing (appGUI->cnt->contacts_columns[i], GTK_TREE_VIEW_COLUMN_FIXED);
996 
997         }
998     }
999 
1000 
1001     /* restore columns order */
1002 
1003     columns_order[0] = config.contacts_column_idx_0;
1004     columns_order[1] = config.contacts_column_idx_1;
1005     columns_order[2] = config.contacts_column_idx_2;
1006 
1007     n = MAX_VISIBLE_CONTACT_COLUMNS-1;
1008 
1009     while (n >= 0) {
1010         for (i = 0; i < MAX_VISIBLE_CONTACT_COLUMNS; i++) {
1011             if (n == columns_order[i]) {
1012                 gtk_tree_view_move_column_after(GTK_TREE_VIEW(appGUI->cnt->contacts_list),
1013                                                 appGUI->cnt->contacts_columns[co_columns[i]], NULL);
1014                 n--;
1015             }
1016         }
1017     }
1018 
1019     set_contacts_columns_width (appGUI);
1020 
1021     gtk_container_add (GTK_CONTAINER (appGUI->cnt->scrolled_win), appGUI->cnt->contacts_list);
1022 
1023     /* configure sorting */
1024     for (i = 0; i < MAX_VISIBLE_CONTACT_COLUMNS; i++) {
1025         gtk_tree_view_column_set_sort_column_id (appGUI->cnt->contacts_columns[co_columns[i]], co_columns[i]);
1026     }
1027     gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (appGUI->cnt->contacts_sort), COLUMN_GROUP,
1028             contacts_column_sort_by_group_function, appGUI, NULL);
1029     gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (appGUI->cnt->contacts_sort), COLUMN_FIRST_NAME,
1030             contacts_column_sort_by_first_name_function, appGUI, NULL);
1031     gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (appGUI->cnt->contacts_sort), COLUMN_LAST_NAME,
1032             contacts_column_sort_by_last_name_function, appGUI, NULL);
1033 
1034 
1035     /* restore sorting */
1036     gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE (appGUI->cnt->contacts_sort),
1037             config.contacts_sorting_column, config.contacts_sorting_order);
1038 
1039     g_signal_connect (appGUI->cnt->contacts_sort, "sort-column-changed", G_CALLBACK (contacts_sort_column_changed_cb), appGUI);
1040 
1041     bottom_viewport = gtk_viewport_new (NULL, NULL);
1042     gtk_widget_show (bottom_viewport);
1043     gtk_viewport_set_shadow_type (GTK_VIEWPORT (bottom_viewport), GTK_SHADOW_NONE);
1044     gtk_paned_pack2 (GTK_PANED (appGUI->cnt->contacts_paned), bottom_viewport, TRUE, TRUE);
1045 
1046     vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1047     gtk_widget_show (vbox2);
1048     gtk_container_set_border_width (GTK_CONTAINER (vbox2), 0);
1049     gtk_container_add (GTK_CONTAINER (bottom_viewport), vbox2);
1050 
1051     appGUI->cnt->panel_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1052     gtk_box_pack_start (GTK_BOX (vbox2), appGUI->cnt->panel_hbox, FALSE, FALSE, 0);
1053     gtk_widget_show(appGUI->cnt->panel_hbox);
1054 
1055 	frame = gtk_frame_new (NULL);
1056 	gtk_widget_show (frame);
1057 	gtk_box_pack_start (GTK_BOX (vbox2), frame, TRUE, TRUE, 0);
1058 	gtk_widget_set_margin_left(GTK_WIDGET(frame), 8);
1059 	gtk_widget_set_margin_right(GTK_WIDGET(frame), 8);
1060 	gtk_widget_set_margin_bottom(GTK_WIDGET(frame), 8);
1061 	gtk_frame_set_label_align (GTK_FRAME (frame), 0.98, 0.5);
1062 	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1063 
1064     g_snprintf(tmpbuf, BUFFER_SIZE, "<b>%s</b>", _("Contact details"));
1065     label = gtk_label_new (tmpbuf);
1066     gtk_widget_show (label);
1067     gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
1068     gtk_frame_set_label_widget (GTK_FRAME (frame), label);
1069 
1070     if (!config.gui_layout) {
1071         close_button = gtk_button_new_from_icon_name ("window-close", GTK_ICON_SIZE_BUTTON);
1072         gtk_widget_set_can_focus(close_button, FALSE);
1073         gtk_button_set_relief (GTK_BUTTON(close_button), GTK_RELIEF_NONE);
1074         if (config.enable_tooltips) {
1075             gtk_widget_set_tooltip_text (close_button, _("Close contact panel"));
1076         }
1077         gtk_widget_show (close_button);
1078         gtk_box_pack_end (GTK_BOX (appGUI->cnt->panel_hbox), close_button, FALSE, FALSE, 0);
1079         g_signal_connect (G_OBJECT (close_button), "clicked", G_CALLBACK (contacts_panel_close_desc_cb), appGUI);
1080     }
1081 
1082     appGUI->cnt->contacts_panel_scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
1083     gtk_widget_show (appGUI->cnt->contacts_panel_scrolledwindow);
1084     gtk_container_add (GTK_CONTAINER (frame), appGUI->cnt->contacts_panel_scrolledwindow);
1085     gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (appGUI->cnt->contacts_panel_scrolledwindow), GTK_SHADOW_NONE);
1086     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (appGUI->cnt->contacts_panel_scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1087 
1088 #ifdef HAVE_LIBWEBKIT
1089     appGUI->cnt->html_webkitview = utl_create_webkit_web_view(appGUI);
1090     webkit_settings_set_default_font_size (webkit_web_view_get_settings(appGUI->cnt->html_webkitview), config.contact_item_font_size);
1091 
1092     g_signal_connect (appGUI->cnt->html_webkitview, "context-menu",
1093                       G_CALLBACK (utl_webkit_on_menu), appGUI);
1094     g_signal_connect (appGUI->cnt->html_webkitview, "decide-policy",
1095                       G_CALLBACK (utl_webkit_link_clicked), appGUI);
1096 
1097     gtk_widget_show (GTK_WIDGET(appGUI->cnt->html_webkitview));
1098     gtk_container_add (GTK_CONTAINER (appGUI->cnt->contacts_panel_scrolledwindow),
1099                        GTK_WIDGET(appGUI->cnt->html_webkitview));
1100 #endif  /* LIBWEBKIT */
1101 
1102     gtk_combo_box_set_active (GTK_COMBO_BOX (appGUI->cnt->contacts_find_combobox), config.find_mode);
1103 
1104     gtk_tree_sortable_sort_column_changed((GtkTreeSortable *)appGUI->cnt->contacts_sort);
1105     gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(appGUI->cnt->contacts_filter));
1106 
1107     g_signal_connect(G_OBJECT(appGUI->cnt->contacts_paned), "notify::position", G_CALLBACK(contacts_paned_position_change_cb), appGUI);
1108     gtk_paned_set_position(GTK_PANED(appGUI->cnt->contacts_paned), config.contacts_pane_pos);
1109 
1110     gtk_widget_grab_focus (appGUI->cnt->contacts_find_entry);
1111 }
1112 
1113 /*------------------------------------------------------------------------------*/
1114 
1115 gboolean
check_address(gint address_type,GUI * appGUI)1116 check_address (gint address_type, GUI *appGUI) {
1117 
1118 GtkTreeIter iter;
1119 GtkTreeModel *model;
1120 gchar *text = NULL;
1121 gint n = 0;
1122 gint c1, c2, c3;
1123 
1124     if (gtk_tree_selection_count_selected_rows(appGUI->cnt->contacts_list_selection) == 1) {
1125 
1126         if (address_type == HOME_ADDRESS) {
1127             c1 = COLUMN_HOME_ADDRESS;
1128             c2 = COLUMN_HOME_CITY;
1129             c3 = COLUMN_HOME_COUNTRY;
1130         } else {
1131             c1 = COLUMN_WORK_ADDRESS;
1132             c2 = COLUMN_WORK_CITY;
1133             c3 = COLUMN_WORK_COUNTRY;
1134         }
1135 
1136         iter = utl_gui_get_first_selection_iter(appGUI->cnt->contacts_list_selection, &model);
1137 
1138         gtk_tree_model_get (model, &iter, c1, &text, -1);
1139         if (text == NULL) return FALSE;
1140         if (strlen(text)) n++;
1141         g_free (text);
1142         gtk_tree_model_get (model, &iter, c2, &text, -1);
1143         if (text == NULL) return FALSE;
1144         if (strlen(text)) n++;
1145         g_free (text);
1146         gtk_tree_model_get (model, &iter, c3, &text, -1);
1147         if (text == NULL) return FALSE;
1148         if (strlen(text)) n++;
1149         g_free (text);
1150     }
1151 
1152     return (n == 3);
1153 }
1154 
1155 /*------------------------------------------------------------------------------*/
1156 
1157 void
show_contact_location_on_map(gint address_type,GUI * appGUI)1158 show_contact_location_on_map (gint address_type, GUI *appGUI) {
1159 
1160 GtkTreeIter     iter;
1161 GtkTreeModel    *model;
1162 gboolean pn_flag = FALSE;
1163 gint i;
1164 gchar *text = NULL, *mapsURL = NULL;
1165 gchar maps_url[BUFFER_SIZE];
1166 gint cbegin, cend, cskip1, cskip2;
1167 
1168     if (gtk_tree_selection_count_selected_rows(appGUI->cnt->contacts_list_selection) == 1) {
1169 
1170         if (address_type == HOME_ADDRESS) {
1171             cbegin = COLUMN_HOME_ADDRESS;
1172             cend = COLUMN_HOME_COUNTRY;
1173             cskip1 = COLUMN_HOME_POST_CODE;
1174             cskip2 = COLUMN_HOME_STATE;
1175         } else {
1176             cbegin = COLUMN_WORK_ADDRESS;
1177             cend = COLUMN_WORK_COUNTRY;
1178             cskip1 = COLUMN_WORK_POST_CODE;
1179             cskip2 = COLUMN_WORK_STATE;
1180         }
1181 
1182         iter = utl_gui_get_first_selection_iter(appGUI->cnt->contacts_list_selection, &model);
1183 
1184         i = config.maps_provider % 3;
1185         if (i == 0) {
1186             g_snprintf(maps_url, BUFFER_SIZE, "%s", GOOGLE_MAPS_QUERY);
1187         } else if (i == 1) {
1188             g_snprintf(maps_url, BUFFER_SIZE, "%s", BING_MAPS_QUERY);
1189         } else {
1190             g_snprintf(maps_url, BUFFER_SIZE, "%s", OSM_MAPS_QUERY);
1191         }
1192 
1193         for (i = cbegin; i <= cend; i++) {
1194 
1195             if (i == cskip1 || i == cskip2) continue;
1196 
1197                 gtk_tree_model_get (model, &iter, i, &text, -1);
1198                 if (text != NULL) {
1199                     if (pn_flag) {
1200                         g_strlcat (maps_url, ",", BUFFER_SIZE);
1201                     }
1202                     g_strlcat (maps_url, text, BUFFER_SIZE);
1203                     pn_flag = TRUE;
1204                     g_free (text);
1205                 }
1206         }
1207 
1208         mapsURL = utl_text_to_html(maps_url, TRUE, FALSE);
1209         utl_run_helper(mapsURL, WWW);
1210         free(mapsURL);
1211     }
1212 }
1213 
1214 /*------------------------------------------------------------------------------*/
1215 
1216 gboolean
queryFilter(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)1217 queryFilter(GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
1218 {
1219     gboolean matches;
1220     gchar*   value;
1221     gchar*   matchWith = data;
1222 
1223 
1224     /* we don't want to match the empty string to match everything */
1225     if (!g_utf8_strlen(matchWith, -1)) return FALSE;
1226 
1227     /* try first name */
1228     value = NULL;
1229     gtk_tree_model_get(model, iter, COLUMN_FIRST_NAME, &value, -1);
1230     if(value != NULL)
1231     {
1232         matches = utl_text_strcasestr(value, matchWith);
1233         g_free (value);
1234         if (matches) return TRUE;
1235     }
1236     /* and last name */
1237     value = NULL;
1238     gtk_tree_model_get(model, iter, COLUMN_LAST_NAME, &value, -1);
1239     if(value != NULL)
1240     {
1241         matches = utl_text_strcasestr(value, matchWith);
1242         g_free (value);
1243         if (matches) return TRUE;
1244     }
1245 
1246     return FALSE;
1247 }
1248 
1249 gint
query(GUI * appGUI,gchar * matchWith)1250 query(GUI* appGUI, gchar *matchWith)
1251 {
1252     GtkTreeIter sort_iter;
1253     gboolean valid;
1254     gchar *text;
1255     gint n = 0, col;
1256 
1257     create_contact_fields(appGUI);
1258     create_contacts_list_store(appGUI);
1259     read_contacts_entries(appGUI);
1260 
1261     appGUI->cnt->contacts_filter = gtk_tree_model_filter_new (GTK_TREE_MODEL(appGUI->cnt->contacts_list_store),
1262                                                               NULL);
1263 
1264     gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER(appGUI->cnt->contacts_filter),
1265                                             queryFilter, /* < this is where the actual filtering takes place */
1266                                             matchWith, NULL);
1267 
1268     /* FIXME: for some reason mutt ignores the first line */
1269     printf("\n");
1270 
1271     /* here we loop over all matching contacts and print the e-mail adresses */
1272 
1273     appGUI->cnt->contacts_sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(appGUI->cnt->contacts_filter));
1274     valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(appGUI->cnt->contacts_sort), &sort_iter);
1275 
1276     while (valid) {
1277         GtkTreeIter filter_iter, iter;
1278         gtk_tree_model_sort_convert_iter_to_child_iter(GTK_TREE_MODEL_SORT(appGUI->cnt->contacts_sort), &filter_iter, &sort_iter);
1279         gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(appGUI->cnt->contacts_filter), &iter, &filter_iter);
1280 
1281         for (col = COLUMN_EMAIL_1; col <= COLUMN_EMAIL_4; col++) {
1282 
1283             gtk_tree_model_get(GTK_TREE_MODEL(appGUI->cnt->contacts_list_store),
1284                     &iter, col, &text, -1);
1285             if (text) {
1286                 printf("%s\n", text);
1287                 n++;
1288             }
1289         }
1290         valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(appGUI->cnt->contacts_sort), &sort_iter);
1291     }
1292 
1293     return n;   /* returns number of found emails */
1294 }
1295 
1296 /*------------------------------------------------------------------------------*/
1297 #endif  /* CONTACTS_ENABLED */
1298 
1299