]> err.no Git - mapper/blob - src/poi-gui.c
Merge branch 'master' of git+ssh://tal.org/home/git/mapper
[mapper] / src / poi-gui.c
1 #include <config.h>
2
3 #define _GNU_SOURCE
4
5 #include <unistd.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <strings.h>
9 #include <stddef.h>
10 #include <locale.h>
11 #include <math.h>
12 #include <errno.h>
13 #include <sys/wait.h>
14 #include <glib/gstdio.h>
15 #include <gtk/gtk.h>
16 #include <fcntl.h>
17
18 #include <libintl.h>
19 #include <locale.h>
20
21 #include <sqlite3.h>
22
23 #include "utils.h"
24 #include "poi.h"
25 #include "gps.h"
26 #include "map.h"
27 #include "mapper-types.h"
28 #include "ui-common.h"
29 #include "settings.h"
30
31 guint _poi_zoom = 6;
32 gboolean select_poi(guint unitx, guint unity, PoiInfo * poi);
33
34
35 gboolean category_delete(GtkWidget * widget, DeletePOI * dpoi)
36 {
37         GtkWidget *dialog;
38         guint i;
39         gchar *buffer;
40         printf("%s()\n", __PRETTY_FUNCTION__);
41
42         buffer = g_strdup_printf("%s\n\t%s\n%s",
43                                  _("Delete category?"),
44                                  dpoi->txt_label,
45                                  _("WARNING: All POIs in that category will also be deleted!"));
46         dialog = hildon_note_new_confirmation(GTK_WINDOW(_window), buffer);
47         g_free(buffer);
48         i = gtk_dialog_run(GTK_DIALOG(dialog));
49         gtk_widget_destroy(GTK_WIDGET(dialog));
50
51         if (i == GTK_RESPONSE_OK) {
52                 if (poi_category_delete(dpoi)==FALSE)
53                         MACRO_BANNER_SHOW_INFO(_window, _("Problem deleting category or POI"));
54                 gtk_widget_hide_all(dpoi->dialog);
55                 map_force_redraw();
56         }
57
58         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
59         return TRUE;
60 }
61
62 gboolean category_dialog(guint cat_id)
63 {
64         gchar *cat_label = NULL, *cat_desc = NULL;
65         guint cat_enabled;
66         GtkWidget *dialog;
67         GtkWidget *table;
68         GtkWidget *label;
69         GtkWidget *txt_label;
70         GtkWidget *txt_desc;
71         GtkWidget *btn_delete = NULL;
72         GtkWidget *txt_scroll;
73         GtkWidget *chk_enabled;
74         GtkTextBuffer *desc_txt;
75         GtkTextIter begin, end;
76         gboolean results = TRUE;
77         DeletePOI dpoi = { NULL, NULL, 0 };
78         printf("%s()\n", __PRETTY_FUNCTION__);
79
80         if (cat_id > 0) {
81                 if (SQLITE_OK != sqlite3_bind_double(_stmt_select_cat, 1, cat_id)
82                     || SQLITE_ROW != sqlite3_step(_stmt_select_cat)) {
83                         vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
84                         sqlite3_reset(_stmt_select_cat);
85                         return FALSE;
86                 }
87
88                 cat_label = g_strdup(sqlite3_column_text(_stmt_select_cat, 0));
89                 cat_desc = g_strdup(sqlite3_column_text(_stmt_select_cat, 1));
90                 cat_enabled = sqlite3_column_int(_stmt_select_cat, 2);
91
92                 sqlite3_reset(_stmt_select_cat);
93
94                 dialog = gtk_dialog_new_with_buttons(_("Edit Category"),
95                                                      GTK_WINDOW(_window),
96                                                      GTK_DIALOG_MODAL,
97                                                      GTK_STOCK_OK,
98                                                      GTK_RESPONSE_ACCEPT, NULL);
99
100                 gtk_container_add(GTK_CONTAINER
101                                   (GTK_DIALOG(dialog)->action_area),
102                                   btn_delete =
103                                   gtk_button_new_with_label(_("Delete")));
104
105                 dpoi.dialog = dialog;
106                 dpoi.txt_label = g_strdup(cat_label);
107                 dpoi.id = cat_id;
108
109                 g_signal_connect(G_OBJECT(btn_delete), "clicked",
110                                  G_CALLBACK(category_delete), &dpoi);
111
112                 gtk_dialog_add_button(GTK_DIALOG(dialog),
113                                       GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
114         } else {
115                 cat_enabled = 1;
116                 cat_label = g_strdup("");
117                 cat_id = 0;
118                 cat_desc = g_strdup("");
119
120                 dialog = gtk_dialog_new_with_buttons(_("Add Category"),
121                                                      GTK_WINDOW(_window),
122                                                      GTK_DIALOG_MODAL,
123                                                      GTK_STOCK_OK,
124                                                      GTK_RESPONSE_ACCEPT,
125                                                      GTK_STOCK_CANCEL,
126                                                      GTK_RESPONSE_REJECT, NULL);
127         }
128
129         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
130                            table = gtk_table_new(6, 4, FALSE), TRUE, TRUE, 0);
131
132         gtk_table_attach(GTK_TABLE(table),
133                          label = gtk_label_new(_("Label")),
134                          0, 1, 0, 1, GTK_FILL, 0, 2, 4);
135         gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
136         gtk_table_attach(GTK_TABLE(table),
137                          txt_label = gtk_entry_new(),
138                          1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
139
140         gtk_table_attach(GTK_TABLE(table),
141                          label = gtk_label_new(_("Description")),
142                          0, 1, 1, 2, GTK_FILL, 0, 2, 4);
143         gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
144
145         txt_scroll = gtk_scrolled_window_new(NULL, NULL);
146         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll),
147                                             GTK_SHADOW_IN);
148         gtk_table_attach(GTK_TABLE(table),
149                          txt_scroll,
150                          1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
151
152         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll),
153                                        GTK_POLICY_AUTOMATIC,
154                                        GTK_POLICY_AUTOMATIC);
155
156         txt_desc = gtk_text_view_new();
157         gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD);
158
159         gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc);
160         gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 400, 60);
161
162         desc_txt = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_desc));
163
164         gtk_table_attach(GTK_TABLE(table),
165                          chk_enabled =
166                          gtk_check_button_new_with_label(_("Enabled")), 0, 2, 2,
167                          3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
168
169         /* label */
170         gtk_entry_set_text(GTK_ENTRY(txt_label), cat_label);
171
172         /* desc */
173         gtk_text_buffer_set_text(desc_txt, cat_desc, -1);
174
175         /* enabled */
176         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_enabled),
177                                      (cat_enabled == 1 ? TRUE : FALSE));
178
179         g_free(cat_label);
180         cat_label = NULL;
181         g_free(cat_desc);
182         cat_desc = NULL;
183
184         gtk_widget_show_all(dialog);
185
186         while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
187                 if (strlen(gtk_entry_get_text(GTK_ENTRY(txt_label))))
188                         cat_label = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_label)));
189                 else {
190                         popup_error(dialog,
191                                     _("Please specify a name for the category."));
192                         continue;
193                 }
194
195                 gtk_text_buffer_get_iter_at_offset(desc_txt, &begin, 0);
196                 gtk_text_buffer_get_end_iter(desc_txt, &end);
197                 cat_desc = gtk_text_buffer_get_text(desc_txt, &begin, &end, TRUE);
198
199                 cat_enabled = (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(chk_enabled)) ? 1 : 0);
200
201                 if (cat_id > 0) {
202                         /* edit category */
203                         if (SQLITE_OK !=
204                             sqlite3_bind_text(_stmt_update_cat, 1, cat_label,
205                                               -1, g_free)
206                             || SQLITE_OK != sqlite3_bind_text(_stmt_update_cat,
207                                                               2, cat_desc, -1,
208                                                               g_free)
209                             || SQLITE_OK != sqlite3_bind_int(_stmt_update_cat,
210                                                              3, cat_enabled)
211                             || SQLITE_OK != sqlite3_bind_int(_stmt_update_cat,
212                                                              4, cat_id)
213                             || SQLITE_DONE != sqlite3_step(_stmt_update_cat)) {
214                                 MACRO_BANNER_SHOW_INFO(_window,
215                                                        _("Problem updating category"));
216                                 results = FALSE;
217                         }
218                         sqlite3_reset(_stmt_update_cat);
219                 } else {
220                         /* add category */
221                         if (SQLITE_OK !=
222                             sqlite3_bind_text(_stmt_insert_cat, 1, cat_label,
223                                               -1, g_free)
224                             || SQLITE_OK != sqlite3_bind_text(_stmt_insert_cat,
225                                                               2, cat_desc, -1,
226                                                               g_free)
227                             || SQLITE_OK != sqlite3_bind_int(_stmt_insert_cat,
228                                                              3, cat_enabled)
229                             || SQLITE_DONE != sqlite3_step(_stmt_insert_cat)) {
230                                 MACRO_BANNER_SHOW_INFO(_window,
231                                                        _("Problem adding category"));
232                                 results = FALSE;
233                         }
234                         sqlite3_reset(_stmt_insert_cat);
235                 }
236                 break;
237         }
238
239         g_free(dpoi.txt_label);
240
241         g_object_unref(desc_txt);
242
243         gtk_widget_hide_all(dialog);
244
245         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
246         return results;
247 }
248
249 void category_toggled(GtkCellRendererToggle * cell, gchar * path, gpointer data)
250 {
251         GtkTreeIter iter;
252         gboolean cat_enabled;
253         guint cat_id;
254         printf("%s()\n", __PRETTY_FUNCTION__);
255
256         GtkTreeModel *model = GTK_TREE_MODEL(data);
257         if (!gtk_tree_model_get_iter_from_string(model, &iter, path))
258                 return;
259
260         gtk_tree_model_get(model, &iter, CAT_ENABLED, &cat_enabled, -1);
261         gtk_tree_model_get(model, &iter, CAT_ID, &cat_id, -1);
262
263         cat_enabled ^= 1;
264
265         if (SQLITE_OK != sqlite3_bind_int(_stmt_toggle_cat, 1, cat_enabled) ||
266             SQLITE_OK != sqlite3_bind_int(_stmt_toggle_cat, 2, cat_id) ||
267             SQLITE_DONE != sqlite3_step(_stmt_toggle_cat)) {
268                 MACRO_BANNER_SHOW_INFO(_window, _("Problem updating Category"));
269         } else
270                 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
271                                    CAT_ENABLED, cat_enabled, -1);
272
273         sqlite3_reset(_stmt_toggle_cat);
274
275         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
276 }
277
278 static GtkListStore *
279 category_generate_store()
280 {
281         GtkTreeIter iter;
282         GtkListStore *store;
283         printf("%s()\n", __PRETTY_FUNCTION__);
284
285         store = gtk_list_store_new(CAT_NUM_COLUMNS,
286                                    G_TYPE_UINT,
287                                    G_TYPE_BOOLEAN,
288                                    G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT);
289
290         while (SQLITE_ROW == sqlite3_step(_stmt_selall_cat)) {
291                 gtk_list_store_append(store, &iter);
292                 gtk_list_store_set(store, &iter,
293                                 CAT_ID, sqlite3_column_int(_stmt_selall_cat, 0), 
294                                 CAT_ENABLED, sqlite3_column_int(_stmt_selall_cat, 3),
295                                 CAT_LABEL, sqlite3_column_text(_stmt_selall_cat, 1),
296                                 CAT_DESC, sqlite3_column_text(_stmt_selall_cat, 2),
297                                 CAT_POI_CNT, sqlite3_column_int(_stmt_selall_cat, 6), -1);
298         }
299         sqlite3_reset(_stmt_selall_cat);
300
301         vprintf("%s(): return %p\n", __PRETTY_FUNCTION__, store);
302         return store;
303 }
304
305 gboolean 
306 category_add(GtkWidget * widget, GtkWidget * tree_view)
307 {
308         GtkListStore *store;
309         printf("%s()\n", __PRETTY_FUNCTION__);
310
311         if (category_dialog(0)) {
312                 store = category_generate_store();
313                 gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view),
314                                         GTK_TREE_MODEL(store));
315                 g_object_unref(G_OBJECT(store));
316         }
317         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
318         return TRUE;
319 }
320
321 gboolean category_edit(GtkWidget * widget, GtkWidget * tree_view)
322 {
323         GtkTreeIter iter;
324         GtkTreeModel *store;
325         GtkTreeSelection *selection;
326         printf("%s()\n", __PRETTY_FUNCTION__);
327
328         store = gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view));
329         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
330         if (gtk_tree_selection_get_selected(selection, &store, &iter)) {
331                 GValue val;
332                 memset(&val, 0, sizeof(val));
333                 gtk_tree_model_get_value(store, &iter, 0, &val);
334                 if (category_dialog(g_value_get_uint(&val))) {
335                         GtkListStore *new_store = category_generate_store();
336                         gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view),
337                                                 GTK_TREE_MODEL(new_store));
338                         g_object_unref(G_OBJECT(new_store));
339                 }
340         }
341         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
342         return TRUE;
343 }
344
345 gboolean category_list()
346 {
347         GtkWidget *dialog;
348         GtkWidget *tree_view;
349         GtkWidget *sw;
350         GtkWidget *btn_edit;
351         GtkWidget *btn_add;
352         GtkTreeViewColumn *column;
353         GtkCellRenderer *renderer;
354         GtkListStore *store;
355         printf("%s()\n", __PRETTY_FUNCTION__);
356
357         dialog = gtk_dialog_new_with_buttons(_("POI Categories"),
358                                              GTK_WINDOW(_window),
359                                              GTK_DIALOG_MODAL, GTK_STOCK_OK,
360                                              GTK_RESPONSE_ACCEPT, NULL);
361
362 #ifdef WITH_HILDON
363         /* Enable the help button. */
364         ossohelp_dialog_help_enable(GTK_DIALOG(dialog), HELP_ID_POICAT, _osso);
365 #endif
366
367         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
368                           btn_edit = gtk_button_new_with_label(_("Edit")));
369
370         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
371                           btn_add = gtk_button_new_with_label(_("Add")));
372
373         store = category_generate_store();
374
375         if (!store)
376                 return TRUE;
377
378         sw = gtk_scrolled_window_new(NULL, NULL);
379         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
380                                        GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
381         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
382                            sw, TRUE, TRUE, 0);
383
384         tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
385         /* Maemo-related? */
386         g_object_set(tree_view, "allow-checkbox-mode", FALSE, NULL);
387         gtk_container_add(GTK_CONTAINER(sw), tree_view);
388
389         gtk_tree_selection_set_mode(gtk_tree_view_get_selection
390                                     (GTK_TREE_VIEW(tree_view)),
391                                     GTK_SELECTION_SINGLE);
392         gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), TRUE);
393
394         renderer = gtk_cell_renderer_text_new();
395         column = gtk_tree_view_column_new_with_attributes(_("ID"), renderer, "text", CAT_ID, NULL);
396         gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
397         gtk_tree_view_column_set_max_width(column, 1);
398
399         renderer = gtk_cell_renderer_toggle_new();
400         g_signal_connect(renderer, "toggled",
401                          G_CALLBACK(category_toggled), store);
402         column = gtk_tree_view_column_new_with_attributes(_("Enabled"), renderer,
403                                                      "active", CAT_ENABLED,
404                                                      NULL);
405         gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
406         gtk_tree_view_column_set_sort_column_id (column, CAT_ENABLED);
407
408         g_object_unref(G_OBJECT(store));
409
410         renderer = gtk_cell_renderer_text_new();
411         column = gtk_tree_view_column_new_with_attributes(_("Label"), renderer,
412                                                      "text", CAT_LABEL, NULL);
413         gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
414         gtk_tree_view_column_set_sort_column_id (column, CAT_LABEL);
415
416         renderer = gtk_cell_renderer_text_new();
417         column = gtk_tree_view_column_new_with_attributes(_("Description"), renderer,
418                                                      "text", CAT_DESC, NULL);
419         gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
420
421         renderer = gtk_cell_renderer_text_new();
422         column = gtk_tree_view_column_new_with_attributes(_("# POIs"), renderer,
423                                                      "text", CAT_POI_CNT, NULL);
424         gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
425         gtk_tree_view_column_set_sort_column_id (column, CAT_POI_CNT);
426
427         gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 300);
428         gtk_widget_show_all(dialog);
429
430         g_signal_connect(G_OBJECT(btn_edit), "clicked",
431                          G_CALLBACK(category_edit), tree_view);
432
433         g_signal_connect(G_OBJECT(btn_add), "clicked",
434                          G_CALLBACK(category_add), tree_view);
435
436         while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
437                 break;
438         }
439         gtk_widget_destroy(dialog);
440
441         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
442         return TRUE;
443 }
444
445 gboolean menu_cb_category(GtkAction * action)
446 {
447         printf("%s()\n", __PRETTY_FUNCTION__);
448
449         if (category_list())
450                 map_force_redraw();
451
452         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
453         return TRUE;
454 }
455
456 gboolean poi_delete_confirm(GtkWidget * widget, DeletePOI * dpoi)
457 {
458         GtkWidget *dialog;
459         guint i;
460         gchar *buffer;
461         printf("%s()\n", __PRETTY_FUNCTION__);
462
463         buffer = g_strdup_printf("%s\n%s", _("Delete POI?"), dpoi->txt_label);
464         dialog = hildon_note_new_confirmation(GTK_WINDOW(_window), buffer);
465         g_free(buffer);
466         i = gtk_dialog_run(GTK_DIALOG(dialog));
467         gtk_widget_destroy(GTK_WIDGET(dialog));
468
469         if (i == GTK_RESPONSE_OK) {
470                 if (poi_delete(dpoi)==FALSE) {
471                         MACRO_BANNER_SHOW_INFO(_window, _("Problem deleting POI"));
472                 } else {
473                         gtk_widget_hide_all(dpoi->dialog);
474                         map_force_redraw();
475                 }
476         }
477
478         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
479         return TRUE;
480 }
481
482 gboolean select_poi(guint unitx, guint unity, PoiInfo * poi)
483 {
484         GtkWidget *dialog;
485         GtkWidget *list;
486         GtkWidget *sw;
487         GtkTreeViewColumn *column;
488         GtkCellRenderer *renderer;
489         GtkListStore *store;
490         GtkTreeIter iter;
491         gboolean selected = FALSE;
492         guint num_cats;
493         printf("%s()\n", __PRETTY_FUNCTION__);
494
495         if (poi_get_list(unitx, unity, &store, &num_cats)==FALSE)
496                 return FALSE;
497
498         g_printf("N: %d\n", num_cats);
499
500         switch (num_cats) {
501         case 0:
502                 MACRO_BANNER_SHOW_INFO(_window, _("No POIs found."));
503                 g_object_unref(G_OBJECT(store));
504                 return FALSE;
505         break;
506         case 1:
507                 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
508                 gtk_tree_model_get(GTK_TREE_MODEL(store),
509                                    &iter,
510                                    POI_POIID, &(poi->poi_id),
511                                    POI_CATID, &(poi->cat_id),
512                                    POI_LAT, &(poi->lat),
513                                    POI_LON, &(poi->lon),
514                                    POI_LABEL, &(poi->label),
515                                    POI_DESC, &(poi->desc), -1);
516                 g_object_unref(G_OBJECT(store));
517                 return TRUE;
518         break;
519         }
520
521         /* There are at least 2 matching POI's - let the user select one. */
522         dialog = gtk_dialog_new_with_buttons(_("Select POI"),
523                                              GTK_WINDOW(_window),
524                                              GTK_DIALOG_MODAL, GTK_STOCK_OK,
525                                              GTK_RESPONSE_ACCEPT,
526                                              GTK_STOCK_CANCEL,
527                                              GTK_RESPONSE_REJECT, NULL);
528
529         gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 300);
530
531         sw = gtk_scrolled_window_new(NULL, NULL);
532         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
533                                             GTK_SHADOW_ETCHED_IN);
534         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
535                                        GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
536         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
537                            sw, TRUE, TRUE, 0);
538
539         list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
540         gtk_container_add(GTK_CONTAINER(sw), list);
541         g_object_unref(G_OBJECT(store));
542
543         gtk_tree_selection_set_mode(gtk_tree_view_get_selection
544                                     (GTK_TREE_VIEW(list)),
545                                     GTK_SELECTION_SINGLE);
546         gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
547         gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (list), TRUE);
548         gtk_tree_view_set_search_column (GTK_TREE_VIEW (list), POI_LABEL);
549
550         renderer = gtk_cell_renderer_text_new();
551         column = gtk_tree_view_column_new_with_attributes(_("Location"), renderer,
552                                                      "text", POI_LATLON, NULL);
553         gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
554
555         renderer = gtk_cell_renderer_text_new();
556         column = gtk_tree_view_column_new_with_attributes(_("Label"), renderer,
557                                                      "text", POI_LABEL, NULL);
558         gtk_tree_view_column_set_sort_column_id (column, POI_LABEL);
559         gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
560
561         renderer = gtk_cell_renderer_text_new();
562         column = gtk_tree_view_column_new_with_attributes(_("Category"), renderer,
563                                                      "text", POI_CATLAB, NULL);
564         gtk_tree_view_column_set_sort_column_id (column, POI_CATLAB);
565         gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
566
567         gtk_widget_show_all(dialog);
568
569         while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
570                 if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), NULL, &iter)) {
571                         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, POI_POIID, &(poi->poi_id), -1);
572                         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, POI_CATID, &(poi->cat_id), -1);
573                         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, POI_LAT, &(poi->lat), -1);
574                         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, POI_LON, &(poi->lon), -1);
575                         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, POI_LABEL, &(poi->label), -1);
576                         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, POI_DESC, &(poi->desc), -1);
577                         selected = TRUE;
578                         break;
579                 } else {
580                         popup_error(dialog, _("Select one POI from the list."));
581                 }
582         }
583
584         gtk_widget_destroy(dialog);
585
586         vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, selected);
587         return selected;
588 }
589
590 void poi_populate_cat_combo(GtkWidget * cmb_category, guint cat_id)
591 {
592         GtkTreeIter active;
593         GtkListStore *store;
594         gboolean has_active = FALSE;
595         printf("%s()\n", __PRETTY_FUNCTION__);
596
597         store = GTK_LIST_STORE(gtk_combo_box_get_model
598                            (GTK_COMBO_BOX(cmb_category)));
599         gtk_list_store_clear(store);
600
601         while (SQLITE_ROW == sqlite3_step(_stmt_selall_cat)) {
602                 GtkTreeIter iter;
603                 guint cid = sqlite3_column_int(_stmt_selall_cat, 0);
604                 gtk_list_store_append(store, &iter);
605                 gtk_list_store_set(store, &iter,
606                                    0, cid,
607                                    1, sqlite3_column_text(_stmt_selall_cat, 1),
608                                    -1);
609                 if (cid == cat_id) {
610                         active = iter;
611                         has_active = TRUE;
612                 }
613         }
614         sqlite3_reset(_stmt_selall_cat);
615
616         if (!has_active)
617                 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &active);
618
619         gtk_combo_box_set_active_iter(GTK_COMBO_BOX(cmb_category), &active);
620
621         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
622 }
623
624 typedef struct _PoiCategoryEditInfo PoiCategoryEditInfo;
625 struct _PoiCategoryEditInfo {
626         GtkWidget *cmb_category;
627         guint cat_id;
628 };
629
630 gboolean poi_edit_cat(GtkWidget * widget, PoiCategoryEditInfo * data)
631 {
632         printf("%s()\n", __PRETTY_FUNCTION__);
633         if (category_list())
634                 poi_populate_cat_combo(data->cmb_category, data->cat_id);
635         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
636         return TRUE;
637 }
638
639 gboolean poi_dialog(POIAction action, guint unitx, guint unity)
640 {
641         PoiInfo poi;
642         gchar slat1[10], slon1[10];
643         gchar *p_latlon;
644         GtkWidget *dialog;
645         GtkWidget *table;
646         GtkWidget *label;
647         GtkWidget *txt_label;
648         GtkWidget *cmb_category;
649         GtkWidget *txt_desc;
650         GtkWidget *btn_delete = NULL;
651         GtkWidget *btn_catedit;
652         GtkWidget *hbox;
653         GtkWidget *txt_scroll;
654         GtkTextBuffer *desc_txt;
655         GtkTextIter begin, end;
656         DeletePOI dpoi = { NULL, NULL, 0 };
657         PoiCategoryEditInfo pcedit;
658         printf("%s()\n", __PRETTY_FUNCTION__);
659
660         if (action == ACTION_EDIT_POI) {
661                 if (!select_poi(unitx, unity, &poi)) {
662                         return FALSE;
663                 }
664
665                 dialog = gtk_dialog_new_with_buttons(_("Edit POI"),
666                                                      GTK_WINDOW(_window),
667                                                      GTK_DIALOG_MODAL,
668                                                      GTK_STOCK_OK,
669                                                      GTK_RESPONSE_ACCEPT, NULL);
670
671                 gtk_container_add(GTK_CONTAINER
672                                   (GTK_DIALOG(dialog)->action_area),
673                                   btn_delete =
674                                   gtk_button_new_with_label(_("Delete")));
675
676                 dpoi.dialog = dialog;
677                 dpoi.txt_label = g_strdup(poi.label);
678                 dpoi.id = poi.poi_id;
679
680                 g_signal_connect(G_OBJECT(btn_delete), "clicked",
681                                  G_CALLBACK(poi_delete_confirm), &dpoi);
682
683                 gtk_dialog_add_button(GTK_DIALOG(dialog),
684                                       GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
685         } else {
686                 if (SQLITE_ROW == sqlite3_step(_stmt_nextlabel_poi))
687                         poi.label = g_strdup_printf("Point%06d",
688                                                     sqlite3_column_int
689                                                     (_stmt_nextlabel_poi, 0));
690                 sqlite3_reset(_stmt_nextlabel_poi);
691
692                 unit2latlon(unitx, unity, poi.lat, poi.lon);
693
694                 poi.poi_id = 0;
695                 poi.cat_id = 0;
696                 poi.desc = g_strdup("");
697
698                 dialog = gtk_dialog_new_with_buttons(_("Add POI"),
699                                                      GTK_WINDOW(_window),
700                                                      GTK_DIALOG_MODAL,
701                                                      GTK_STOCK_OK,
702                                                      GTK_RESPONSE_ACCEPT,
703                                                      GTK_STOCK_CANCEL,
704                                                      GTK_RESPONSE_REJECT, NULL);
705         }
706
707         /* Set the p_latlon string. */
708         {
709                 gchar tmp1[16], tmp2[16];
710                 lat_format(poi.lat, tmp1);
711                 lon_format(poi.lon, tmp2);
712                 p_latlon = g_strdup_printf("%s, %s", tmp1, tmp2);
713         }
714
715         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
716                            table = gtk_table_new(6, 4, FALSE), TRUE, TRUE, 0);
717
718         gtk_table_attach(GTK_TABLE(table),
719                          label = gtk_label_new(_("Lat, Lon")),
720                          0, 1, 0, 1, GTK_FILL, 0, 2, 4);
721         gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
722
723         gtk_table_attach(GTK_TABLE(table),
724                          label = gtk_label_new(p_latlon),
725                          1, 3, 0, 1, GTK_FILL, 0, 2, 4);
726         gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
727
728         gtk_table_attach(GTK_TABLE(table),
729                          label = gtk_label_new(_("Label")),
730                          0, 1, 1, 2, GTK_FILL, 0, 2, 4);
731         gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
732         gtk_table_attach(GTK_TABLE(table),
733                          txt_label = gtk_entry_new(),
734                          1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
735
736         gtk_table_attach(GTK_TABLE(table),
737                          label = gtk_label_new(_("Category")),
738                          0, 1, 3, 4, GTK_FILL, 0, 2, 4);
739         gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
740         gtk_table_attach(GTK_TABLE(table),
741                          hbox = gtk_hbox_new(FALSE, 4),
742                          1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
743         gtk_box_pack_start(GTK_BOX(hbox), cmb_category = gtk_combo_box_new_with_model(GTK_TREE_MODEL(gtk_list_store_new(2, G_TYPE_INT,  /* Category ID */
744                                                                                                                         G_TYPE_STRING))),       /* Category Label */
745                            FALSE, FALSE, 4);
746         /* Set up the view for the combo box. */
747         {
748                 GtkCellRenderer *renderer;
749                 renderer = gtk_cell_renderer_text_new();
750                 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(cmb_category),
751                                            renderer, TRUE);
752                 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(cmb_category),
753                                                renderer, "text", 1, NULL);
754         }
755
756         gtk_box_pack_start(GTK_BOX(hbox),
757                            btn_catedit =
758                            gtk_button_new_with_label(_("Edit Categories...")),
759                            FALSE, FALSE, 4);
760
761         gtk_table_attach(GTK_TABLE(table),
762                          label = gtk_label_new(_("Description")),
763                          0, 1, 5, 6, GTK_FILL, 0, 2, 4);
764         gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
765
766         txt_scroll = gtk_scrolled_window_new(NULL, NULL);
767         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll),
768                                             GTK_SHADOW_IN);
769         gtk_table_attach(GTK_TABLE(table),
770                          txt_scroll,
771                          1, 2, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 4);
772
773         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll),
774                                        GTK_POLICY_AUTOMATIC,
775                                        GTK_POLICY_AUTOMATIC);
776
777         txt_desc = gtk_text_view_new();
778         gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD);
779
780         gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc);
781         gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 400, 60);
782
783         desc_txt = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_desc));
784
785         /* label */
786         gtk_entry_set_text(GTK_ENTRY(txt_label), poi.label);
787
788         /* category */
789         poi_populate_cat_combo(cmb_category, poi.cat_id);
790
791         /* poi_desc */
792         gtk_text_buffer_set_text(desc_txt, poi.desc, -1);
793
794         /* Connect Signals */
795         pcedit.cmb_category = cmb_category;
796         pcedit.cat_id = poi.cat_id;
797         g_signal_connect(G_OBJECT(btn_catedit), "clicked",
798                          G_CALLBACK(poi_edit_cat), &pcedit);
799         gtk_widget_show_all(dialog);
800
801         while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
802                 const gchar *poi_label = NULL;
803                 gchar *poi_desc = NULL;
804                 GtkTreeIter iter;
805
806                 if (strlen(gtk_entry_get_text(GTK_ENTRY(txt_label))))
807                         poi_label = gtk_entry_get_text(GTK_ENTRY(txt_label));
808                 else {
809                         popup_error(dialog, _("Please specify a name for the POI."));
810                         continue;
811                 }
812
813                 if (!gtk_combo_box_get_active_iter
814                     (GTK_COMBO_BOX(cmb_category), &iter)) {
815                         popup_error(dialog, _("Please specify a category for the POI."));
816                         continue;
817                 }
818
819                 gtk_text_buffer_get_iter_at_offset(desc_txt, &begin, 0);
820                 gtk_text_buffer_get_end_iter(desc_txt, &end);
821                 poi_desc = gtk_text_buffer_get_text(desc_txt, &begin, &end, TRUE);
822
823                 gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(cmb_category)), &iter, 0, &poi.cat_id, -1);
824
825                 if (action == ACTION_EDIT_POI) {
826                         /* edit poi */
827                         if (poi_update(poi.poi_id, poi.cat_id, poi_label, poi_desc)==FALSE) {
828                                 MACRO_BANNER_SHOW_INFO(_window, _("Problem updating POI"));
829                         } else {
830                                 MACRO_MAP_RENDER_DATA();
831                         }
832                 } else {
833                         /* add poi */
834                         g_ascii_dtostr(slat1, sizeof(slat1), poi.lat);
835                         g_ascii_dtostr(slon1, sizeof(slon1), poi.lon);
836                         if (poi_add(poi.lat, poi.lon, poi.cat_id, poi_label, poi_desc)==FALSE) {
837                                 MACRO_BANNER_SHOW_INFO(_window, _("Problem adding POI"));
838                         } else {
839                                 MACRO_MAP_RENDER_DATA();
840                         }
841                 }
842                 break;
843         }
844
845         g_free(dpoi.txt_label);
846
847         g_free(poi.label);
848         g_free(poi.desc);
849         g_free(p_latlon);
850
851         gtk_widget_hide_all(dialog);
852
853         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
854         return TRUE;
855 }