Index: src/poi.c.dialog-size.diff =================================================================== --- src/poi.c.dialog-size.diff (revision 0) +++ src/poi.c.dialog-size.diff (revision 14) @@ -0,0 +1,265 @@ +Index: poi.c +=================================================================== +--- poi.c (revision 13) ++++ poi.c (working copy) +@@ -1228,6 +1228,7 @@ + GtkTextIter begin, end; + DeletePOI dpoi; + PoiCategoryEditInfo pcedit; ++ gboolean compact = TRUE; + + gchar tmp1[LL_FMT_LEN], tmp2[LL_FMT_LEN]; + +@@ -1243,100 +1244,170 @@ + else if(_degformat != last_deg_format) + last_deg_format = _degformat; + +- if (is_add_dialog) ++ dialog = gtk_dialog_new_with_buttons(_("Add POI"), ++ GTK_WINDOW(parent), GTK_DIALOG_MODAL, ++ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, ++ NULL); ++ ++ if (!is_add_dialog) + { +- dialog = gtk_dialog_new_with_buttons(_("Add POI"), +- GTK_WINDOW(parent), GTK_DIALOG_MODAL, +- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, +- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, +- NULL); +- } +- else +- { +- dialog = gtk_dialog_new_with_buttons(_("Edit POI"), +- GTK_WINDOW(parent), GTK_DIALOG_MODAL, +- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, +- NULL); +- + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), + btn_delete = gtk_button_new_with_label(_("Delete..."))); +- +- gtk_dialog_add_button(GTK_DIALOG(dialog), +- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT); ++ g_signal_connect(G_OBJECT(btn_delete), "clicked", ++ G_CALLBACK(poi_delete), &dpoi); + } + +- /* Set the lat/lon strings. */ +- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), +- table = gtk_table_new(6, 4, FALSE), TRUE, TRUE, 0); ++ if (compact) ++ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), ++ btn_catedit = gtk_button_new_with_label(_("Edit Cats..."))); + +- gtk_table_attach(GTK_TABLE(table), +- label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat] +- .short_field_1), +- 0, 1, 0, 1, GTK_FILL, 0, 2, 0); +- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); +- gtk_table_attach(GTK_TABLE(table), +- txt_lat = gtk_entry_new(), +- 1, (DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use ? 2 : 4), +- 0, 1, GTK_FILL, 0, 2, 0); ++ gtk_dialog_add_button(GTK_DIALOG(dialog), ++ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT); + +- if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use) ++ if(!compact) + { ++ /* Set the lat/lon strings. */ ++ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), ++ table = gtk_table_new(6, 4, FALSE), TRUE, TRUE, 0); ++ + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat] +- .short_field_2), +- 2, 3, 0, 1, GTK_FILL, 0, 2, 0); ++ .short_field_1), ++ 0, 1, 0, 1, GTK_FILL, 0, 2, 0); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), +- txt_lon = gtk_entry_new(), +- 3, 4, 0, 1, GTK_FILL, 0, 2, 0); ++ txt_lat = gtk_entry_new(), ++ 1, (DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use ? 2 : 4), ++ 0, 1, GTK_FILL, 0, 2, 0); ++ ++ if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use) ++ { ++ gtk_table_attach(GTK_TABLE(table), ++ label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat] ++ .short_field_2), ++ 2, 3, 0, 1, GTK_FILL, 0, 2, 0); ++ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); ++ gtk_table_attach(GTK_TABLE(table), ++ txt_lon = gtk_entry_new(), ++ 3, 4, 0, 1, GTK_FILL, 0, 2, 0); ++ } ++ ++ gtk_table_attach(GTK_TABLE(table), ++ label = gtk_label_new(_("Label")), ++ 0, 1, 1, 2, GTK_FILL, 0, 2, 0); ++ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); ++ gtk_table_attach(GTK_TABLE(table), ++ txt_label = gtk_entry_new(), ++ 1, 4, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 0); ++ ++ gtk_table_attach(GTK_TABLE(table), ++ label = gtk_label_new(_("Category")), ++ 0, 1, 3, 4, GTK_FILL, 0, 2, 0); ++ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); ++ gtk_table_attach(GTK_TABLE(table), ++ hbox = gtk_hbox_new(FALSE, 4), ++ 1, 4, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 0); ++ gtk_box_pack_start(GTK_BOX(hbox), ++ cmb_category = poi_create_cat_combo(), ++ FALSE, FALSE, 0); ++ ++ gtk_box_pack_start(GTK_BOX(hbox), ++ btn_catedit = gtk_button_new_with_label( ++ _("Edit Categories...")), ++ FALSE, FALSE, 0); ++ ++ gtk_table_attach(GTK_TABLE(table), ++ label = gtk_label_new(_("Description")), ++ 0, 1, 5, 6, GTK_FILL, GTK_FILL, 2, 0); ++ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.0f); ++ ++ txt_scroll = gtk_scrolled_window_new(NULL, NULL); ++ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll), ++ GTK_SHADOW_IN); ++ gtk_table_attach(GTK_TABLE(table), ++ txt_scroll, ++ 1, 4, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 0); ++ ++ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll), ++ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); ++ ++ txt_desc = gtk_text_view_new(); ++ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD); ++ ++ gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc); ++ gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 550, 120); ++ ++ desc_txt = gtk_text_view_get_buffer(GTK_TEXT_VIEW (txt_desc)); + } ++ else ++ { ++ gint cols = (DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use) ? 6 : 4; ++ /* Set the lat/lon strings. */ ++ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), ++ table = gtk_table_new(6, cols, FALSE), TRUE, TRUE, 0); + +- gtk_table_attach(GTK_TABLE(table), +- label = gtk_label_new(_("Label")), +- 0, 1, 1, 2, GTK_FILL, 0, 2, 0); +- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); +- gtk_table_attach(GTK_TABLE(table), +- txt_label = gtk_entry_new(), +- 1, 4, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 0); ++ gtk_table_attach(GTK_TABLE(table), ++ label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat] ++ .short_field_1), ++ 0, 1, 0, 1, GTK_FILL, 0, 2, 0); ++ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); ++ gtk_table_attach(GTK_TABLE(table), ++ txt_lat = gtk_entry_new(), ++ 1, (DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use ? 2 : 4), ++ 0, 1, GTK_FILL, 0, 2, 0); + +- gtk_table_attach(GTK_TABLE(table), +- label = gtk_label_new(_("Category")), +- 0, 1, 3, 4, GTK_FILL, 0, 2, 0); +- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); +- gtk_table_attach(GTK_TABLE(table), +- hbox = gtk_hbox_new(FALSE, 4), +- 1, 4, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 0); +- gtk_box_pack_start(GTK_BOX(hbox), +- cmb_category = poi_create_cat_combo(), +- FALSE, FALSE, 0); ++ if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use) ++ { ++ gtk_table_attach(GTK_TABLE(table), ++ label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat] ++ .short_field_2), ++ 2, 3, 0, 1, GTK_FILL, 0, 2, 0); ++ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); ++ gtk_table_attach(GTK_TABLE(table), ++ txt_lon = gtk_entry_new(), ++ 3, 4, 0, 1, GTK_FILL, 0, 2, 0); ++ } ++ ++ gtk_table_attach(GTK_TABLE(table), ++ label = gtk_label_new(_("Cat")), ++ cols - 2, cols - 1, 0, 1, GTK_FILL, 0, 2, 0); ++ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); ++ gtk_table_attach(GTK_TABLE(table), ++ cmb_category = poi_create_cat_combo(), ++ cols - 1, cols - 0, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 0); + +- gtk_box_pack_start(GTK_BOX(hbox), +- btn_catedit = gtk_button_new_with_label( +- _("Edit Categories...")), +- FALSE, FALSE, 0); ++ gtk_table_attach(GTK_TABLE(table), ++ label = gtk_label_new(_("Label")), ++ 0, 1, 1, 2, GTK_FILL, 0, 2, 0); ++ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); ++ gtk_table_attach(GTK_TABLE(table), ++ txt_label = gtk_entry_new(), ++ 1, cols, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 0); + +- gtk_table_attach(GTK_TABLE(table), +- label = gtk_label_new(_("Description")), +- 0, 1, 5, 6, GTK_FILL, GTK_FILL, 2, 0); +- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.0f); ++ gtk_table_attach(GTK_TABLE(table), ++ label = gtk_label_new(_("Desc")), ++ 0, 1, 5, 6, GTK_FILL, GTK_FILL, 2, 0); ++ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.0f); + +- txt_scroll = gtk_scrolled_window_new(NULL, NULL); +- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll), +- GTK_SHADOW_IN); +- gtk_table_attach(GTK_TABLE(table), +- txt_scroll, +- 1, 4, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 0); ++ txt_scroll = gtk_scrolled_window_new(NULL, NULL); ++ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll), ++ GTK_SHADOW_IN); ++ gtk_table_attach(GTK_TABLE(table), ++ txt_scroll, ++ 1, cols, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 0); + +- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll), +- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); ++ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll), ++ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + +- txt_desc = gtk_text_view_new(); +- gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD); ++ txt_desc = gtk_text_view_new(); ++ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), ++ GTK_WRAP_WORD_CHAR); + +- gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc); +- gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 550, 120); ++ gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc); ++ gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 600, 200); + +- desc_txt = gtk_text_view_get_buffer(GTK_TEXT_VIEW (txt_desc)); ++ desc_txt = gtk_text_view_get_buffer(GTK_TEXT_VIEW (txt_desc)); ++ } + + g_signal_connect(G_OBJECT(btn_catedit), "clicked", + G_CALLBACK(poi_edit_cat), &pcedit); +@@ -1348,9 +1419,6 @@ + dpoi.dialog = dialog; + dpoi.txt_label = g_strdup(poi->label); + dpoi.id = poi->poi_id; +- +- g_signal_connect(G_OBJECT(btn_delete), "clicked", +- G_CALLBACK(poi_delete), &dpoi); + } + + /* Lat/Lon */ Index: src/poi.c.dialog-size =================================================================== --- src/poi.c.dialog-size (revision 0) +++ src/poi.c.dialog-size (revision 14) @@ -0,0 +1,3265 @@ +/* + * Copyright (C) 2006, 2007 John Costigan. + * + * POI and GPS-Info code originally written by Cezary Jackiewicz. + * + * Default map data provided by http://www.openstreetmap.org/ + * + * This file is part of Maemo Mapper. + * + * Maemo Mapper is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Maemo Mapper is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Maemo Mapper. If not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define _GNU_SOURCE + +#include +#include + +#ifndef LEGACY +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +#endif + +#include + +#include "types.h" +#include "data.h" +#include "defines.h" + +#include "display.h" +#include "gdk-pixbuf-rotate.h" +#include "gpx.h" +#include "main.h" +#include "poi.h" +#include "util.h" + +static sqlite3 *_poi_db = NULL; +static sqlite3_stmt *_stmt_browse_poi = NULL; +static sqlite3_stmt *_stmt_browsecat_poi = NULL; +static sqlite3_stmt *_stmt_select_poi = NULL; +static sqlite3_stmt *_stmt_select_nearest_poi = NULL; +static sqlite3_stmt *_stmt_select_cat_poi = NULL; +static sqlite3_stmt *_stmt_insert_poi = NULL; +static sqlite3_stmt *_stmt_update_poi = NULL; +static sqlite3_stmt *_stmt_delete_poi = NULL; +static sqlite3_stmt *_stmt_delete_poi_by_catid = NULL; +static sqlite3_stmt *_stmt_nextlabel_poi = NULL; +static sqlite3_stmt *_stmt_select_cat = NULL; +static sqlite3_stmt *_stmt_insert_cat = NULL; +static sqlite3_stmt *_stmt_update_cat = NULL; +static sqlite3_stmt *_stmt_delete_cat = NULL; +static sqlite3_stmt *_stmt_toggle_cat = NULL; +static sqlite3_stmt *_stmt_selall_cat = NULL; + +typedef struct _PoiListInfo PoiListInfo; +struct _PoiListInfo +{ + GtkWidget *dialog; + GtkWidget *dialog2; + GtkTreeViewColumn *select_column; + GtkWidget *tree_view; + gboolean select_all; +}; + +typedef struct _OriginToggleInfo OriginToggleInfo; +struct _OriginToggleInfo { + GtkWidget *rad_use_gps; + GtkWidget *rad_use_route; + GtkWidget *rad_use_text; + GtkWidget *txt_origin; + GtkWidget *txt_query; +}; + +typedef struct _PoiCategoryEditInfo PoiCategoryEditInfo; +struct _PoiCategoryEditInfo +{ + GtkWidget *dialog; + GtkWidget *cmb_category; + gint cat_id; + GtkWidget *tree_view; +}; + +/** Data used during action: add or edit category/poi **/ +typedef struct _DeletePOI DeletePOI; +struct _DeletePOI { + GtkWidget *dialog; + gchar *txt_label; + gint id; + gboolean deleted; +}; + +void +poi_db_connect() +{ + gchar buffer[100]; + gchar **pszResult; + gint nRow, nColumn; + gchar *db_dirname = NULL; + printf("%s()\n", __PRETTY_FUNCTION__); + + if(_poi_db) + { + sqlite3_close(_poi_db); + _poi_db = NULL; + } + + if(!_poi_db_filename) + { + /* Do nothing. */ + } + else if(NULL == (db_dirname = g_path_get_dirname(_poi_db_filename)) + || (g_mkdir_with_parents(db_dirname, 0755), /* comma operator */ + (SQLITE_OK != (sqlite3_open(_poi_db_filename, &_poi_db))))) + { + gchar buffer2[BUFFER_SIZE]; + snprintf(buffer2, sizeof(buffer2), + "%s: %s", _("Error with POI database"), + sqlite3_errmsg(_poi_db)); + sqlite3_close(_poi_db); + _poi_db = NULL; + popup_error(_window, buffer2); + } + else if(SQLITE_OK != sqlite3_get_table(_poi_db, + "select label from poi limit 1", + &pszResult, &nRow, &nColumn, NULL)) + { + gchar *create_sql = sqlite3_mprintf( + "create table poi (poi_id integer PRIMARY KEY, lat real, " + "lon real, label text, desc text, cat_id integer);" + "create table category (cat_id integer PRIMARY KEY," + "label text, desc text, enabled integer);" + /* Add some default categories... */ + "insert into category (label, desc, enabled) " + "values ('%q', '%q', 1); " + "insert into category (label, desc, enabled) " + "values ('%q', '%q', 1); " + "insert into category (label, desc, enabled) " + "values ('%q', '%q', 1); " + "insert into category (label, desc, enabled) " + "values ('%q', '%q', 1); " + "insert into category (label, desc, enabled) " + "values ('%q', '%q', 1); " + "insert into category (label, desc, enabled) " + "values ('%q', '%q', 1); " + "insert into category (label, desc, enabled) " + "values ('%q', '%q', 1); " + "insert into category (label, desc, enabled) " + "values ('%q', '%q', 1); " + "insert into category (label, desc, enabled) " + "values ('%q', '%q', 1); " + "insert into category (label, desc, enabled) " + "values ('%q', '%q', 1); " + "insert into category (label, desc, enabled) " + "values ('%q', '%q', 1); ", + _("Service Station"), + _("Stations for purchasing fuel for vehicles."), + _("Residence"), + _("Houses, apartments, or other residences of import."), + _("Restaurant"), + _("Places to eat or drink."), + _("Shopping/Services"), + _("Places to shop or acquire services."), + _("Recreation"), + _("Indoor or Outdoor places to have fun."), + _("Transportation"), + _("Bus stops, airports, train stations, etc."), + _("Lodging"), + _("Places to stay temporarily or for the night."), + _("School"), + _("Elementary schools, college campuses, etc."), + _("Business"), + _("General places of business."), + _("Landmark"), + _("General landmarks."), + _("Other"), + _("Miscellaneous category for everything else.")); + + if(SQLITE_OK != sqlite3_exec(_poi_db, create_sql, NULL, NULL, NULL) + && (SQLITE_OK != sqlite3_get_table(_poi_db, + "select label from poi limit 1", + &pszResult, &nRow, &nColumn, NULL))) + { + snprintf(buffer, sizeof(buffer), "%s:\n%s", + _("Failed to open or create database"), + sqlite3_errmsg(_poi_db)); + sqlite3_close(_poi_db); + _poi_db = NULL; + popup_error(_window, buffer); + } + } + else + sqlite3_free_table(pszResult); + + g_free(db_dirname); + + if(_poi_db) + { + /* Prepare our SQL statements. */ + /* browse poi */ + sqlite3_prepare(_poi_db, + "select p.poi_id, p.cat_id, p.lat, p.lon," + " p.label, p.desc, c.label" + " from poi p inner join category c" + " on p.cat_id = c.cat_id" + " where c.enabled = 1" + " and p.label like $QUERY or p.desc like $QUERY" + " order by (($LAT - p.lat) * ($LAT - p.lat) " + "+ ($LON - p.lon) * ($LON - p.lon)) DESC " + " limit 100", + -1, &_stmt_browse_poi, NULL); + + /* browse poi by category */ + sqlite3_prepare(_poi_db, + "select p.poi_id, p.cat_id, p.lat, p.lon," + " p.label, p.desc, c.label" + " from poi p inner join category c" + " on p.cat_id = c.cat_id" + " where c.enabled = 1" + " and p.cat_id = $CATID" + " and ( p.label like $QUERY or p.desc like $QUERY )" + " order by (($LAT - p.lat) * ($LAT - p.lat) " + "+ ($LON - p.lon) * ($LON - p.lon)) DESC" + " limit 100", + -1, &_stmt_browsecat_poi, NULL); + + /* Prepare our SQL statements. */ + /* select from poi */ + sqlite3_prepare(_poi_db, + "select p.lat, p.lon, p.poi_id, p.label, p.desc," + " p.cat_id, c.label, c.desc" + " from poi p inner join category c" + " on p.cat_id = c.cat_id" + " where c.enabled = 1" + " and p.lat between ? and ? " + " and p.lon between ? and ? ", + -1, &_stmt_select_poi, NULL); + + /* select nearest pois */ + sqlite3_prepare(_poi_db, + "select p.poi_id, p.cat_id, p.lat, p.lon," + " p.label, p.desc, c.label" + " from poi p inner join category c" + " on p.cat_id = c.cat_id" + " where c.enabled = 1" + " order by (($LAT - p.lat) * ($LAT - p.lat) " + "+ ($LON - p.lon) * ($LON - p.lon)) limit 1", + -1, &_stmt_select_nearest_poi, NULL); + + /* select lat/lon for all pois in category*/ + sqlite3_prepare(_poi_db, + "select p.lat, p.lon" + " from poi p inner join category c" + " on p.cat_id = c.cat_id" + " where c.cat_id = ?", + -1, &_stmt_select_cat_poi, NULL); + + /* insert poi */ + sqlite3_prepare(_poi_db, + "insert into poi (lat, lon, label, desc, cat_id)" + " values (?, ?, ?, ?, ?)", + -1, &_stmt_insert_poi, NULL); + /* update poi */ + sqlite3_prepare(_poi_db, + "update poi set lat = ?, lon = ?, " + "label = ?, desc = ?, cat_id = ? where poi_id = ?", + -1, &_stmt_update_poi, NULL); + /* delete from poi */ + sqlite3_prepare(_poi_db, + " delete from poi where poi_id = ?", + -1, &_stmt_delete_poi, NULL); + /* delete from poi by cat_id */ + sqlite3_prepare(_poi_db, + "delete from poi where cat_id = ?", + -1, &_stmt_delete_poi_by_catid, NULL); + /* get next poilabel */ + sqlite3_prepare(_poi_db, + "select ifnull(max(poi_id) + 1,1) from poi", + -1, &_stmt_nextlabel_poi, NULL); + + /* select from category */ + sqlite3_prepare(_poi_db, + "select c.label, c.desc, c.enabled" + " from category c where c.cat_id = ?", + -1, &_stmt_select_cat, NULL); + /* insert into category */ + sqlite3_prepare(_poi_db, + "insert into category (label, desc, enabled)" + " values (?, ?, ?)", + -1, &_stmt_insert_cat, NULL); + /* update category */ + sqlite3_prepare(_poi_db, + "update category set label = ?, desc = ?," + " enabled = ? where cat_id = ?", + -1, &_stmt_update_cat, NULL); + /* delete from category */ + sqlite3_prepare(_poi_db, + "delete from category where cat_id = ?", + -1, &_stmt_delete_cat, NULL); + /* enable category */ + sqlite3_prepare(_poi_db, + "update category set enabled = ?" + " where cat_id = ?", + -1, &_stmt_toggle_cat, NULL); + /* select all category */ + sqlite3_prepare(_poi_db, + "select c.cat_id, c.label, c.desc, c.enabled," + " count(p.poi_id)" + " from category c" + " left outer join poi p on c.cat_id = p.cat_id" + " group by c.cat_id, c.label, c.desc, c.enabled " + " order by c.label", + -1, &_stmt_selall_cat, NULL); + } + + _poi_enabled = _poi_db != NULL; + + gtk_widget_set_sensitive(_menu_poi_item, _poi_enabled); + gtk_widget_set_sensitive(_cmenu_loc_add_poi_item, _poi_enabled); + gtk_widget_set_sensitive(_cmenu_loc_download_poi_item, _poi_enabled); + gtk_widget_set_sensitive(_cmenu_loc_browse_poi_item, _poi_enabled); + gtk_widget_set_sensitive(_cmenu_way_add_poi_item, _poi_enabled); + gtk_widget_set_sensitive(_cmenu_poi_submenu, _poi_enabled); + + vprintf("%s(): return\n", __PRETTY_FUNCTION__); +} + +gboolean +get_nearest_poi(gint unitx, gint unity, PoiInfo *poi) +{ + printf("%s(%d, %d)\n", __PRETTY_FUNCTION__, unitx, unity); + gboolean result; + gdouble lat, lon; + unit2latlon(unitx, unity, lat, lon); + + if(SQLITE_OK == sqlite3_bind_double(_stmt_select_nearest_poi, 1, lat) + && SQLITE_OK == sqlite3_bind_double(_stmt_select_nearest_poi, 2, lon) + && SQLITE_ROW == sqlite3_step(_stmt_select_nearest_poi)) + { + poi->poi_id = sqlite3_column_int(_stmt_select_nearest_poi, 0); + poi->cat_id = sqlite3_column_int(_stmt_select_nearest_poi, 1); + poi->lat = sqlite3_column_double(_stmt_select_nearest_poi, 2); + poi->lon = sqlite3_column_double(_stmt_select_nearest_poi, 3); + poi->label =g_strdup(sqlite3_column_text(_stmt_select_nearest_poi, 4)); + poi->desc = g_strdup(sqlite3_column_text(_stmt_select_nearest_poi, 5)); + poi->clabel=g_strdup(sqlite3_column_text(_stmt_select_nearest_poi, 6)); + result = TRUE; + } + else + result = FALSE; + sqlite3_reset(_stmt_select_nearest_poi); + vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, result); + return result; +} + +static void +write_selected_poi(PoiInfo *poi, gint *id, + GtkTreeModel *model, GtkTreeIter *iter) +{ + gtk_tree_model_get(model, iter, + POI_POIID, &(poi->poi_id), + POI_CATID, &(poi->cat_id), + POI_LAT, &(poi->lat), + POI_LON, &(poi->lon), + POI_LABEL, &(poi->label), + POI_DESC, &(poi->desc), + POI_CLABEL, &(poi->clabel), + -1); + *id = poi->poi_id; +} + +GSList * +get_category_pois(gint cat) +{ + GSList *list = NULL; + printf("%s(%d, %d)\n", __PRETTY_FUNCTION__); + + if(SQLITE_OK != sqlite3_bind_double(_stmt_select_cat_poi, 1, cat)) + { + g_printerr("Failed to bind values for _stmt_select_cat_poi\n"); + return NULL; + } + + while(SQLITE_ROW == sqlite3_step(_stmt_select_cat_poi)) + { + PoiInfo *poi = g_new0(PoiInfo, 1); + poi->lat = sqlite3_column_double(_stmt_select_cat_poi, 0); + poi->lon = sqlite3_column_double(_stmt_select_cat_poi, 1); + list = g_slist_append(list, poi); + } + sqlite3_reset(_stmt_select_cat_poi); + vprintf("%s(): return\n", __PRETTY_FUNCTION__); + return list; +} + +gboolean +select_poi(gint unitx, gint unity, PoiInfo *poi, gboolean quick) +{ + static gint selected_poi_id = -1; + GtkTreeIter *selected_poi = NULL; + gint x, y; + gdouble lat1, lon1, lat2, lon2; + GtkListStore *store; + gboolean selected = FALSE; + gchar tmp1[LL_FMT_LEN], tmp2[LL_FMT_LEN], tmp3[LL_FMT_LEN + 4]; + gint num_pois = 0; + printf("%s()\n", __PRETTY_FUNCTION__); + + x = unitx - pixel2unit(3 * _draw_width); + y = unity + pixel2unit(3 * _draw_width); + unit2latlon(x, y, lat1, lon1); + + x = unitx + pixel2unit(3 * _draw_width); + y = unity - pixel2unit(3 * _draw_width); + unit2latlon(x, y, lat2, lon2); + + if(SQLITE_OK != sqlite3_bind_double(_stmt_select_poi, 1, lat1) || + SQLITE_OK != sqlite3_bind_double(_stmt_select_poi, 2, lat2) || + SQLITE_OK != sqlite3_bind_double(_stmt_select_poi, 3, lon1) || + SQLITE_OK != sqlite3_bind_double(_stmt_select_poi, 4, lon2)) + { + g_printerr("Failed to bind values for _stmt_select_poi\n"); + return FALSE; + } + + /* Initialize store. */ + store = gtk_list_store_new(POI_NUM_COLUMNS, + G_TYPE_BOOLEAN,/* Selected */ + G_TYPE_INT, /* POI ID */ + G_TYPE_INT, /* Category ID */ + G_TYPE_DOUBLE, /* Latitude */ + G_TYPE_DOUBLE, /* Longitude */ + G_TYPE_STRING, /* Lat/Lon */ + G_TYPE_FLOAT, /* Bearing */ + G_TYPE_FLOAT, /* Distance */ + G_TYPE_STRING, /* POI Label */ + G_TYPE_STRING, /* POI Desc. */ + G_TYPE_STRING);/* Category Label */ + + while(SQLITE_ROW == sqlite3_step(_stmt_select_poi)) + { + GtkTreeIter iter; + gdouble lat, lon; + gint poi_id; + lat = sqlite3_column_double(_stmt_select_poi, 0); + lon = sqlite3_column_double(_stmt_select_poi, 1); + poi_id = sqlite3_column_int(_stmt_select_poi, 2); + + format_lat_lon(lat, lon, tmp1, tmp2); + //lat_format(lat, tmp1); + //lon_format(lon, tmp2); + snprintf(tmp3, sizeof(tmp3), "%s, %s", tmp1, tmp2); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + POI_POIID, poi_id, + POI_CATID, sqlite3_column_int(_stmt_select_poi, 5), + POI_LAT, lat, + POI_LON, lon, + POI_LATLON, tmp3, + POI_LABEL, sqlite3_column_text(_stmt_select_poi, 3), + POI_DESC, sqlite3_column_text(_stmt_select_poi, 4), + POI_CLABEL, sqlite3_column_text(_stmt_select_poi, 6), + -1); + + /* get previously selected POI or the first one on the list */ + if(poi_id == selected_poi_id || num_pois == 0) + { + if(selected_poi) + gtk_tree_iter_free(selected_poi); + selected_poi = gtk_tree_iter_copy(&iter); + } + + num_pois++; + } + sqlite3_reset(_stmt_select_poi); + + /* nothing found */ + if(num_pois == 0) + { + if(!quick) + MACRO_BANNER_SHOW_INFO(_window, _("No POIs found.")); + selected_poi_id = -1; + selected = FALSE; + } + /* one match */ + else if(num_pois == 1) + { + write_selected_poi(poi, &selected_poi_id, + GTK_TREE_MODEL(store), selected_poi); + selected = TRUE; + } + /* two or more -- picking the nearest */ + else if(quick) + { + selected = get_nearest_poi(unitx, unity, poi); + if (selected) + selected_poi_id = poi->poi_id; + } + /* multiple matches -- let user decide */ + else + { + GtkWidget *dialog; + GtkWidget *list; + GtkWidget *sw; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + + dialog = gtk_dialog_new_with_buttons(_("Select POI"), + GTK_WINDOW(_window), GTK_DIALOG_MODAL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, + NULL); + + gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 300); + + sw = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), + GTK_SHADOW_ETCHED_IN); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), + GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + sw, TRUE, TRUE, 0); + + list = gtk_tree_view_new(); + gtk_container_add(GTK_CONTAINER(sw), list); + + gtk_tree_selection_set_mode( + gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), + GTK_SELECTION_SINGLE); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes( + _("Location"), renderer, "text", POI_LATLON, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes( + _("Label"), renderer, "text", POI_LABEL, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes( + _("Category"), renderer, "text", POI_CLABEL, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); + + gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store)); + + gtk_tree_selection_select_iter( + gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), + selected_poi); + + gtk_widget_show_all(dialog); + + while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) + { + GtkTreeIter iter; + if(gtk_tree_selection_get_selected( + gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), + NULL, &iter)) + { + gtk_tree_iter_free(selected_poi); + selected_poi = gtk_tree_iter_copy(&iter); + selected = TRUE; + break; + } + else + popup_error(dialog, _("Select one POI from the list.")); + } + + map_force_redraw(); + + if (selected) + write_selected_poi(poi, &selected_poi_id, + GTK_TREE_MODEL(store), selected_poi); + + gtk_widget_destroy(dialog); + } + + if (selected_poi) + gtk_tree_iter_free(selected_poi); + g_object_unref(G_OBJECT(store)); + + vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, selected); + return selected; +} + +static gboolean +category_delete(GtkWidget *widget, DeletePOI *dpoi) +{ + GtkWidget *confirm; + gint i; + gchar *buffer; + printf("%s()\n", __PRETTY_FUNCTION__); + + buffer = g_strdup_printf("%s\n\t%s\n%s", + _("Delete category?"), + dpoi->txt_label, + _("WARNING: All POIs in that category will also be deleted!")); + confirm = hildon_note_new_confirmation(GTK_WINDOW(dpoi->dialog), buffer); + g_free(buffer); + i = gtk_dialog_run(GTK_DIALOG(confirm)); + gtk_widget_destroy(GTK_WIDGET(confirm)); + + if(i == GTK_RESPONSE_OK) + { + /* delete dpoi->poi_id */ + if(SQLITE_OK != sqlite3_bind_int(_stmt_delete_poi_by_catid, 1, + dpoi->id) || + SQLITE_DONE != sqlite3_step(_stmt_delete_poi_by_catid)) + { + MACRO_BANNER_SHOW_INFO(dpoi->dialog, _("Error deleting POI")); + sqlite3_reset(_stmt_delete_poi_by_catid); + return FALSE; + } + sqlite3_reset(_stmt_delete_poi_by_catid); + + if(SQLITE_OK != sqlite3_bind_int(_stmt_delete_cat, 1, dpoi->id) || + SQLITE_DONE != sqlite3_step(_stmt_delete_cat)) + { + MACRO_BANNER_SHOW_INFO(dpoi->dialog, _("Error deleting category")); + sqlite3_reset(_stmt_delete_cat); + return FALSE; + } + sqlite3_reset(_stmt_delete_cat); + + map_force_redraw(); + } + gtk_widget_destroy(confirm); + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +gboolean +category_edit_dialog(GtkWidget *parent, gint cat_id) +{ + gchar *cat_label = NULL, *cat_desc = NULL; + gint cat_enabled; + GtkWidget *dialog; + GtkWidget *table; + GtkWidget *label; + GtkWidget *txt_label; + GtkWidget *txt_desc; + GtkWidget *btn_delete = NULL; + GtkWidget *txt_scroll; + GtkWidget *chk_enabled; + GtkTextBuffer *desc_txt; + GtkTextIter begin, end; + gboolean results = TRUE; + DeletePOI dpoi = {NULL, NULL, 0}; + printf("%s()\n", __PRETTY_FUNCTION__); + + if(cat_id > 0) + { + if(SQLITE_OK != sqlite3_bind_double(_stmt_select_cat, 1, cat_id) || + SQLITE_ROW != sqlite3_step(_stmt_select_cat)) + { + vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__); + sqlite3_reset(_stmt_select_cat); + return FALSE; + } + + cat_label = g_strdup(sqlite3_column_text(_stmt_select_cat, 0)); + cat_desc = g_strdup(sqlite3_column_text(_stmt_select_cat, 1)); + cat_enabled = sqlite3_column_int(_stmt_select_cat, 2); + + sqlite3_reset(_stmt_select_cat); + + dialog = gtk_dialog_new_with_buttons(_("Edit Category"), + GTK_WINDOW(parent), GTK_DIALOG_MODAL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + NULL); + + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), + btn_delete = gtk_button_new_with_label(_("Delete..."))); + + dpoi.dialog = dialog; + dpoi.txt_label = g_strdup(cat_label); + dpoi.id = cat_id; + dpoi.deleted = FALSE; + + g_signal_connect(G_OBJECT(btn_delete), "clicked", + G_CALLBACK(category_delete), &dpoi); + + gtk_dialog_add_button(GTK_DIALOG(dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT); + } + else + { + cat_enabled = 1; + cat_label = g_strdup(""); + cat_id = -1; + cat_desc = g_strdup(""); + + dialog = gtk_dialog_new_with_buttons(_("Add Category"), + GTK_WINDOW(parent), GTK_DIALOG_MODAL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, + NULL); + } + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + table = gtk_table_new(6, 4, FALSE), TRUE, TRUE, 0); + + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(_("Label")), + 0, 1, 0, 1, GTK_FILL, 0, 2, 4); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), + txt_label = gtk_entry_new(), + 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4); + + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(_("Description")), + 0, 1, 1, 2, GTK_FILL, 0, 2, 4); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + + txt_scroll = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll), + GTK_SHADOW_IN); + gtk_table_attach(GTK_TABLE(table), + txt_scroll, + 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + txt_desc = gtk_text_view_new(); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD); + + gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc); + gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 400, 60); + + desc_txt = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_desc)); + + gtk_table_attach(GTK_TABLE(table), + chk_enabled = gtk_check_button_new_with_label( + _("Enabled")), + 0, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4); + + /* label */ + gtk_entry_set_text(GTK_ENTRY(txt_label), cat_label); + + /* desc */ + gtk_text_buffer_set_text(desc_txt, cat_desc, -1); + + /* enabled */ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_enabled), + (cat_enabled == 1 ? TRUE : FALSE)); + + g_free(cat_label); + cat_label = NULL; + g_free(cat_desc); + cat_desc = NULL; + + gtk_widget_show_all(dialog); + + while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) + { + if(strlen(gtk_entry_get_text(GTK_ENTRY(txt_label)))) + cat_label = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_label))); + else + { + popup_error(dialog, _("Please specify a name for the category.")); + continue; + } + + gtk_text_buffer_get_iter_at_offset(desc_txt, &begin,0 ); + gtk_text_buffer_get_end_iter (desc_txt, &end); + cat_desc = gtk_text_buffer_get_text(desc_txt, &begin, &end, TRUE); + + cat_enabled = (gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON(chk_enabled)) ? 1 : 0); + + if(cat_id > 0) + { + /* edit category */ + if(SQLITE_OK != sqlite3_bind_text(_stmt_update_cat, 1, cat_label, + -1, g_free) || + SQLITE_OK != sqlite3_bind_text(_stmt_update_cat, 2, cat_desc, + -1, g_free) || + SQLITE_OK != sqlite3_bind_int(_stmt_update_cat, 3,cat_enabled)|| + SQLITE_OK != sqlite3_bind_int(_stmt_update_cat, 4, cat_id) || + SQLITE_DONE != sqlite3_step(_stmt_update_cat)) + { + MACRO_BANNER_SHOW_INFO(parent,_("Error updating category")); + results = FALSE; + } + sqlite3_reset(_stmt_update_cat); + } + else + { + /* add category */ + if(SQLITE_OK != sqlite3_bind_text(_stmt_insert_cat, 1, cat_label, + -1, g_free) || + SQLITE_OK != sqlite3_bind_text(_stmt_insert_cat, 2, cat_desc, + -1, g_free) || + SQLITE_OK != sqlite3_bind_int(_stmt_insert_cat, 3,cat_enabled)|| + SQLITE_DONE != sqlite3_step(_stmt_insert_cat)) + { + MACRO_BANNER_SHOW_INFO(parent, _("Error adding category")); + results = FALSE; + } + sqlite3_reset(_stmt_insert_cat); + } + break; + } + + g_free(dpoi.txt_label); + + g_object_unref (desc_txt); + + if(results) + map_force_redraw(); + + gtk_widget_hide(dialog); + + vprintf("%s(): return\n", __PRETTY_FUNCTION__); + return results; +} + +static void +category_toggled(GtkCellRendererToggle *cell, gchar *path, GtkListStore *data) +{ + GtkTreeIter iter; + gboolean cat_enabled; + gint cat_id; + printf("%s()\n", __PRETTY_FUNCTION__); + + GtkTreeModel *model = GTK_TREE_MODEL(data); + if( !gtk_tree_model_get_iter_from_string(model, &iter, path) ) + return; + + gtk_tree_model_get(model, &iter, + CAT_ENABLED, &cat_enabled, + CAT_ID, &cat_id, + -1); + + cat_enabled ^= 1; + + if(SQLITE_OK != sqlite3_bind_int(_stmt_toggle_cat, 1, cat_enabled) || + SQLITE_OK != sqlite3_bind_int(_stmt_toggle_cat, 2, cat_id) || + SQLITE_DONE != sqlite3_step(_stmt_toggle_cat)) + { + MACRO_BANNER_SHOW_INFO(_window, _("Error updating Category")); + } + else + { + gtk_list_store_set(GTK_LIST_STORE(model), &iter, + CAT_ENABLED, cat_enabled, -1); + map_force_redraw(); + } + + sqlite3_reset(_stmt_toggle_cat); + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); +} + +static GtkListStore* +generate_store() +{ + GtkTreeIter iter; + GtkListStore *store; + printf("%s()\n", __PRETTY_FUNCTION__); + + store = gtk_list_store_new(CAT_NUM_COLUMNS, + G_TYPE_UINT, + G_TYPE_BOOLEAN, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_UINT); + + while(SQLITE_ROW == sqlite3_step(_stmt_selall_cat)) + { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + CAT_ID, sqlite3_column_int(_stmt_selall_cat, 0), + CAT_ENABLED, sqlite3_column_int(_stmt_selall_cat, 3), + CAT_LABEL, sqlite3_column_text(_stmt_selall_cat, 1), + CAT_DESC, sqlite3_column_text(_stmt_selall_cat, 2), + CAT_POI_CNT, sqlite3_column_int(_stmt_selall_cat, 4), + -1); + } + sqlite3_reset(_stmt_selall_cat); + + vprintf("%s(): return %p\n", __PRETTY_FUNCTION__, store); + return store; +} + +GtkListStore * +poi_create_poi_store() +{ + GtkTreeIter iter; + GtkListStore *store; + printf("%s()\n", __PRETTY_FUNCTION__); + + store = gtk_list_store_new(CAT_NUM_COLUMNS, + G_TYPE_UINT, + G_TYPE_BOOLEAN, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_UINT); + + while(SQLITE_ROW == sqlite3_step(_stmt_selall_cat)) + { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + CAT_ID, sqlite3_column_int(_stmt_selall_cat, 0), + CAT_ENABLED, sqlite3_column_int(_stmt_selall_cat, 3), + CAT_LABEL, sqlite3_column_text(_stmt_selall_cat, 1), + CAT_DESC, sqlite3_column_text(_stmt_selall_cat, 2), + CAT_POI_CNT, sqlite3_column_int(_stmt_selall_cat, 4), + -1); + } + sqlite3_reset(_stmt_selall_cat); + + vprintf("%s(): return %p\n", __PRETTY_FUNCTION__, store); + return store; +} + +static gboolean +category_add(GtkWidget *widget, PoiCategoryEditInfo *pcedit) +{ + GtkListStore *store; + printf("%s()\n", __PRETTY_FUNCTION__); + + if(category_edit_dialog(pcedit->dialog, 0)) + { + store = generate_store(); + gtk_tree_view_set_model( + GTK_TREE_VIEW(pcedit->tree_view), + GTK_TREE_MODEL(store)); + g_object_unref(G_OBJECT(store)); + } + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +static gboolean +category_edit(GtkWidget *widget, PoiCategoryEditInfo *pcedit) +{ + GtkTreeIter iter; + GtkTreeModel *store; + GtkTreeSelection *selection; + printf("%s()\n", __PRETTY_FUNCTION__); + + store = gtk_tree_view_get_model(GTK_TREE_VIEW(pcedit->tree_view)); + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(pcedit->tree_view)); + if(gtk_tree_selection_get_selected(selection, &store, &iter)) + { + GValue val; + memset(&val, 0, sizeof(val)); + gtk_tree_model_get_value(store, &iter, 0, &val); + if(category_edit_dialog(pcedit->dialog, g_value_get_uint(&val))) + { + GtkListStore *new_store = generate_store(); + gtk_tree_view_set_model( + GTK_TREE_VIEW(pcedit->tree_view), + GTK_TREE_MODEL(new_store)); + g_object_unref(G_OBJECT(new_store)); + } + } + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +gboolean +category_list_dialog(GtkWidget *parent) +{ + GtkWidget *dialog; + GtkWidget *tree_view; + GtkWidget *sw; + GtkWidget *btn_edit; + GtkWidget *btn_add; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkListStore *store; + PoiCategoryEditInfo pcedit; + printf("%s()\n", __PRETTY_FUNCTION__); + + store = generate_store(); + + if(!store) + return TRUE; + + dialog = gtk_dialog_new_with_buttons(_("POI Categories"), + GTK_WINDOW(parent), GTK_DIALOG_MODAL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + NULL); + + /* Enable the help button. */ +#ifndef LEGACY + hildon_help_dialog_help_enable( +#else + ossohelp_dialog_help_enable( +#endif + GTK_DIALOG(dialog), HELP_ID_POICAT, _osso); + + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), + btn_edit = gtk_button_new_with_label(_("Edit..."))); + + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), + btn_add = gtk_button_new_with_label(_("Add..."))); + + sw = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (sw), + GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + sw, TRUE, TRUE, 0); + + tree_view = gtk_tree_view_new(); + /* Maemo-related? */ + g_object_set(tree_view, "allow-checkbox-mode", FALSE, NULL); + gtk_container_add (GTK_CONTAINER (sw), tree_view); + + gtk_tree_selection_set_mode( + gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)), + GTK_SELECTION_SINGLE); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), TRUE); + + renderer = gtk_cell_renderer_toggle_new(); + g_signal_connect (renderer, "toggled", + G_CALLBACK (category_toggled), store); + column = gtk_tree_view_column_new_with_attributes( + _("Enabled"), renderer, "active", CAT_ENABLED, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes( + _("Label"), renderer, "text", CAT_LABEL, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes( + _("Description"), renderer, "text", CAT_DESC, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes( + _("# POIs"), renderer, "text", CAT_POI_CNT, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); + + gtk_window_set_default_size(GTK_WINDOW(dialog), -1, 400); + + pcedit.dialog = dialog; + pcedit.tree_view = tree_view; + + g_signal_connect(G_OBJECT(btn_edit), "clicked", + G_CALLBACK(category_edit), &pcedit); + + g_signal_connect(G_OBJECT(btn_add), "clicked", + G_CALLBACK(category_add), &pcedit); + + gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view), GTK_TREE_MODEL(store)); + g_object_unref(G_OBJECT(store)); + + gtk_widget_show_all(dialog); + + while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) + { + break; + } + + gtk_widget_destroy(dialog); + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +static gboolean +poi_delete(GtkWidget *widget, DeletePOI *dpoi) +{ + GtkWidget *confirm; + gint i; + gchar *buffer; + printf("%s()\n", __PRETTY_FUNCTION__); + + buffer = g_strdup_printf("%s\n%s", _("Delete POI?"), dpoi->txt_label); + confirm = hildon_note_new_confirmation(GTK_WINDOW(dpoi->dialog), buffer); + g_free(buffer); + i = gtk_dialog_run(GTK_DIALOG(confirm)); + gtk_widget_destroy(GTK_WIDGET(confirm)); + + if(i == GTK_RESPONSE_OK) + { + if(SQLITE_OK != sqlite3_bind_int(_stmt_delete_poi, 1, dpoi->id) || + SQLITE_DONE != sqlite3_step(_stmt_delete_poi)) + { + MACRO_BANNER_SHOW_INFO(dpoi->dialog, _("Error deleting POI")); + } + else + { + dpoi->deleted = TRUE; + gtk_widget_hide(dpoi->dialog); + map_force_redraw(); + } + sqlite3_reset(_stmt_delete_poi); + } + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +static gboolean +poi_populate_categories(GtkListStore *store, gint cat_id, + GtkTreeIter *out_active) +{ + gboolean has_active = FALSE; + printf("%s()\n", __PRETTY_FUNCTION__); + + gtk_list_store_clear(store); + + while(SQLITE_ROW == sqlite3_step(_stmt_selall_cat)) + { + GtkTreeIter iter; + gint cid = sqlite3_column_int(_stmt_selall_cat, 0); + const gchar *clab = sqlite3_column_text(_stmt_selall_cat, 1); + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, cid, 1, clab, -1); + + if(cid == cat_id || !has_active) + { + if(out_active) + *out_active = iter; + has_active = TRUE; + } + } + sqlite3_reset(_stmt_selall_cat); + + vprintf("%s(): return\n", __PRETTY_FUNCTION__); + return has_active; +} + +static gboolean +poi_edit_cat(GtkWidget *widget, PoiCategoryEditInfo *data) +{ + printf("%s()\n", __PRETTY_FUNCTION__); + if(category_list_dialog(data->dialog)) + { + GtkTreeIter active; + if(poi_populate_categories(GTK_LIST_STORE(gtk_combo_box_get_model( + GTK_COMBO_BOX(data->cmb_category))), + data->cat_id, &active)) + { + gtk_combo_box_set_active_iter( + GTK_COMBO_BOX(data->cmb_category), &active); + } + } + vprintf("%s(): return\n", __PRETTY_FUNCTION__); + return TRUE; +} + +static GtkWidget* +poi_create_cat_combo() +{ + GtkWidget *cmb_category; + GtkTreeModel *model; + printf("%s()\n", __PRETTY_FUNCTION__); + + model = GTK_TREE_MODEL(gtk_list_store_new(2, + G_TYPE_INT, /* Category ID */ + G_TYPE_STRING)); /* Category Label */ + cmb_category = gtk_combo_box_new_with_model(model); + g_object_unref(model); + + /* Set up the view for the combo box. */ + { + GtkCellRenderer *renderer; + GtkTreeIter active; + renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start( + GTK_CELL_LAYOUT(cmb_category), renderer, TRUE); + gtk_cell_layout_set_attributes( + GTK_CELL_LAYOUT(cmb_category), renderer, "text", 1, NULL); + + poi_populate_categories(GTK_LIST_STORE(gtk_combo_box_get_model( + GTK_COMBO_BOX(cmb_category))), -1, &active); + } + vprintf("%s(): return\n", __PRETTY_FUNCTION__); + return cmb_category; +} + +gboolean +poi_dialog(GtkWidget *parent, PoiInfo *poi, gboolean is_add_dialog) +{ + static int last_deg_format = 0; + GtkTreeIter iter; + GtkWidget *dialog; + GtkWidget *table; + GtkWidget *label; + GtkWidget *txt_label; + GtkWidget *txt_lat; + GtkWidget *txt_lon; + GtkWidget *cmb_category; + GtkWidget *txt_desc; + GtkWidget *btn_delete; + GtkWidget *btn_catedit; + GtkWidget *hbox; + GtkWidget *txt_scroll; + GtkTextBuffer *desc_txt; + GtkTextIter begin, end; + DeletePOI dpoi; + PoiCategoryEditInfo pcedit; + gboolean compact = TRUE; + + gchar tmp1[LL_FMT_LEN], tmp2[LL_FMT_LEN]; + + printf("%s()\n", __PRETTY_FUNCTION__); + + gint fallback_deg_format = _degformat; + + if(!coord_system_check_lat_lon(poi->lat, poi->lon, &fallback_deg_format)) + { + last_deg_format = _degformat; + _degformat = fallback_deg_format; + } + else if(_degformat != last_deg_format) + last_deg_format = _degformat; + + dialog = gtk_dialog_new_with_buttons(_("Add POI"), + GTK_WINDOW(parent), GTK_DIALOG_MODAL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + NULL); + + if (!is_add_dialog) + { + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), + btn_delete = gtk_button_new_with_label(_("Delete..."))); + g_signal_connect(G_OBJECT(btn_delete), "clicked", + G_CALLBACK(poi_delete), &dpoi); + } + + if (compact) + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), + btn_catedit = gtk_button_new_with_label(_("Edit Cats..."))); + + gtk_dialog_add_button(GTK_DIALOG(dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT); + + if(!compact) + { + /* Set the lat/lon strings. */ + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + table = gtk_table_new(6, 4, FALSE), TRUE, TRUE, 0); + + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat] + .short_field_1), + 0, 1, 0, 1, GTK_FILL, 0, 2, 0); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), + txt_lat = gtk_entry_new(), + 1, (DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use ? 2 : 4), + 0, 1, GTK_FILL, 0, 2, 0); + + if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use) + { + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat] + .short_field_2), + 2, 3, 0, 1, GTK_FILL, 0, 2, 0); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), + txt_lon = gtk_entry_new(), + 3, 4, 0, 1, GTK_FILL, 0, 2, 0); + } + + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(_("Label")), + 0, 1, 1, 2, GTK_FILL, 0, 2, 0); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), + txt_label = gtk_entry_new(), + 1, 4, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 0); + + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(_("Category")), + 0, 1, 3, 4, GTK_FILL, 0, 2, 0); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), + hbox = gtk_hbox_new(FALSE, 4), + 1, 4, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 0); + gtk_box_pack_start(GTK_BOX(hbox), + cmb_category = poi_create_cat_combo(), + FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(hbox), + btn_catedit = gtk_button_new_with_label( + _("Edit Categories...")), + FALSE, FALSE, 0); + + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(_("Description")), + 0, 1, 5, 6, GTK_FILL, GTK_FILL, 2, 0); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.0f); + + txt_scroll = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll), + GTK_SHADOW_IN); + gtk_table_attach(GTK_TABLE(table), + txt_scroll, + 1, 4, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 0); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + txt_desc = gtk_text_view_new(); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD); + + gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc); + gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 550, 120); + + desc_txt = gtk_text_view_get_buffer(GTK_TEXT_VIEW (txt_desc)); + } + else + { + gint cols = (DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use) ? 6 : 4; + /* Set the lat/lon strings. */ + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + table = gtk_table_new(6, cols, FALSE), TRUE, TRUE, 0); + + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat] + .short_field_1), + 0, 1, 0, 1, GTK_FILL, 0, 2, 0); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), + txt_lat = gtk_entry_new(), + 1, (DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use ? 2 : 4), + 0, 1, GTK_FILL, 0, 2, 0); + + if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use) + { + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(DEG_FORMAT_ENUM_TEXT[_degformat] + .short_field_2), + 2, 3, 0, 1, GTK_FILL, 0, 2, 0); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), + txt_lon = gtk_entry_new(), + 3, 4, 0, 1, GTK_FILL, 0, 2, 0); + } + + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(_("Cat")), + cols - 2, cols - 1, 0, 1, GTK_FILL, 0, 2, 0); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), + cmb_category = poi_create_cat_combo(), + cols - 1, cols - 0, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 0); + + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(_("Label")), + 0, 1, 1, 2, GTK_FILL, 0, 2, 0); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), + txt_label = gtk_entry_new(), + 1, cols, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 0); + + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(_("Desc")), + 0, 1, 5, 6, GTK_FILL, GTK_FILL, 2, 0); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.0f); + + txt_scroll = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll), + GTK_SHADOW_IN); + gtk_table_attach(GTK_TABLE(table), + txt_scroll, + 1, cols, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 0); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + txt_desc = gtk_text_view_new(); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), + GTK_WRAP_WORD_CHAR); + + gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc); + gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 600, 200); + + desc_txt = gtk_text_view_get_buffer(GTK_TEXT_VIEW (txt_desc)); + } + + g_signal_connect(G_OBJECT(btn_catedit), "clicked", + G_CALLBACK(poi_edit_cat), &pcedit); + + dpoi.txt_label = NULL; + dpoi.deleted = FALSE; + if (!is_add_dialog) + { + dpoi.dialog = dialog; + dpoi.txt_label = g_strdup(poi->label); + dpoi.id = poi->poi_id; + } + + /* Lat/Lon */ + format_lat_lon(poi->lat, poi->lon, tmp1, tmp2); + //lat_format(poi->lat, tmp1); + //lon_format(poi->lon, tmp2); + + gtk_entry_set_text(GTK_ENTRY(txt_lat), tmp1); + + if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use) + gtk_entry_set_text(GTK_ENTRY(txt_lon), tmp2); + else + gtk_entry_set_text(GTK_ENTRY(txt_lon), ""); + + /* Label */ + gtk_entry_set_text(GTK_ENTRY(txt_label), poi->label); + + /* Poi_desc */ + gtk_text_buffer_set_text(desc_txt, poi->desc, -1); + + /* Category. */ + gtk_list_store_clear(GTK_LIST_STORE(gtk_combo_box_get_model( + GTK_COMBO_BOX(cmb_category)))); + if(poi_populate_categories(GTK_LIST_STORE(gtk_combo_box_get_model( + GTK_COMBO_BOX(cmb_category))), poi->cat_id, &iter)) + gtk_combo_box_set_active_iter(GTK_COMBO_BOX(cmb_category), &iter); + + pcedit.dialog = dialog; + pcedit.cmb_category = cmb_category; + pcedit.cat_id = poi->cat_id; + + gtk_widget_show_all(dialog); + + while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) + { + GtkTreeIter iter; + const gchar *lat, *lon = NULL; + + lat = gtk_entry_get_text(GTK_ENTRY(txt_lat)); + if(txt_lon != NULL) + lon = gtk_entry_get_text(GTK_ENTRY(txt_lon)); + + if(!parse_coords(lat, lon, &poi->lat, &poi->lon)) + { + popup_error(dialog, _("Invalid Coordinate specified")); + continue; + } + + if(strlen(gtk_entry_get_text(GTK_ENTRY(txt_label)))) + { + g_free(poi->label); + poi->label = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_label))); + } + else + { + popup_error(dialog, _("Please specify a name.")); + continue; + } + + if(!gtk_combo_box_get_active_iter( + GTK_COMBO_BOX(cmb_category), &iter)) + { + popup_error(dialog, _("Please specify a category.")); + continue; + } + + gtk_text_buffer_get_iter_at_offset(desc_txt, &begin, 0); + gtk_text_buffer_get_end_iter(desc_txt, &end); + g_free(poi->desc); + poi->desc = gtk_text_buffer_get_text(desc_txt, &begin, &end, TRUE); + + g_free(poi->clabel); + gtk_tree_model_get( + gtk_combo_box_get_model(GTK_COMBO_BOX(cmb_category)), &iter, + 0, &poi->cat_id, + 1, &poi->clabel, + -1); + + if (is_add_dialog) + { + if(SQLITE_OK != sqlite3_bind_double(_stmt_insert_poi, 1, poi->lat) + || SQLITE_OK != sqlite3_bind_double(_stmt_insert_poi, 2, poi->lon) + || SQLITE_OK != sqlite3_bind_text(_stmt_insert_poi, 3, poi->label, + -1, SQLITE_STATIC) + || SQLITE_OK != sqlite3_bind_text(_stmt_insert_poi, 4, poi->desc, + -1, SQLITE_STATIC) + || SQLITE_OK != sqlite3_bind_int(_stmt_insert_poi, 5, poi->cat_id) + || SQLITE_DONE != sqlite3_step(_stmt_insert_poi)) + { + MACRO_BANNER_SHOW_INFO(parent, _("Error adding POI")); + } + sqlite3_reset(_stmt_insert_poi); + } + else + { + if(SQLITE_OK != sqlite3_bind_double(_stmt_update_poi, 1, poi->lat) + || SQLITE_OK != sqlite3_bind_double(_stmt_update_poi, 2, poi->lon) + || SQLITE_OK != sqlite3_bind_text(_stmt_update_poi, 3, poi->label, + -1, SQLITE_STATIC) + || SQLITE_OK != sqlite3_bind_text(_stmt_update_poi, 4, poi->desc, + -1, SQLITE_STATIC) + || SQLITE_OK != sqlite3_bind_int(_stmt_update_poi, 5, poi->cat_id) + || SQLITE_OK != sqlite3_bind_int(_stmt_update_poi, 6, poi->poi_id) + || SQLITE_DONE != sqlite3_step(_stmt_update_poi)) + { + MACRO_BANNER_SHOW_INFO(parent, _("Error updating POI")); + } + sqlite3_reset(_stmt_update_poi); + } + break; + } + + g_free(dpoi.txt_label); + map_force_redraw(); + _degformat = last_deg_format; + + gtk_widget_destroy(dialog); + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return !dpoi.deleted; +} + +gint +poi_get_next_id() +{ + gint id; + if(SQLITE_ROW == sqlite3_step(_stmt_nextlabel_poi)) + id = sqlite3_column_int(_stmt_nextlabel_poi, 0); + else + id = -1; + sqlite3_reset(_stmt_nextlabel_poi); + return id; +} + +static gint +poi_list_insert(GtkWidget *parent, GList *poi_list, GtkComboBox *cmb_category) +{ + gint default_cat_id; + gchar *default_cat_label; + gint num_inserts = 0; + GList *curr; + GtkTreeIter iter; + printf("%s()\n", __PRETTY_FUNCTION__); + + /* Get defaults from the given GtkComboBox */ + if(!gtk_combo_box_get_active_iter( + GTK_COMBO_BOX(cmb_category), &iter)) + { + vprintf("%s(): return 0\n", __PRETTY_FUNCTION__); + return 0; + } + gtk_tree_model_get( + gtk_combo_box_get_model(GTK_COMBO_BOX(cmb_category)), + &iter, + 0, &default_cat_id, + 1, &default_cat_label, + -1); + + /* Iterate through the data model and import as desired. */ + for(curr = poi_list; curr; ) + { + PoiInfo *poi = curr->data; + if( + ( SQLITE_OK != sqlite3_bind_double(_stmt_insert_poi, 1, poi->lat) + || SQLITE_OK != sqlite3_bind_double(_stmt_insert_poi, 2, poi->lon) + || SQLITE_OK != sqlite3_bind_text(_stmt_insert_poi, 3, poi->label, + -1, SQLITE_STATIC) + || SQLITE_OK != sqlite3_bind_text(_stmt_insert_poi, 4, poi->desc, + -1, SQLITE_STATIC) + || SQLITE_OK != sqlite3_bind_int(_stmt_insert_poi, 5, + poi->cat_id = default_cat_id) + || SQLITE_DONE != sqlite3_step(_stmt_insert_poi) + )) + { + /* Failure. */ + GList *tmp = curr->next; + if(poi->label) + g_free(poi->label); + if(poi->desc) + g_free(poi->desc); + g_slice_free(PoiInfo, poi); + poi_list = g_list_delete_link(poi_list, curr); + curr = tmp; + } + else + { + /* Success. */ + ++num_inserts; + if(default_cat_label) + poi->clabel = g_strdup(default_cat_label); + poi->poi_id = sqlite3_last_insert_rowid(_poi_db); + curr = curr->next; + } + sqlite3_reset(_stmt_insert_poi); + } + + if(num_inserts) + { + gchar buffer[BUFFER_SIZE]; + map_force_redraw(); + snprintf(buffer, sizeof(buffer), "%d %s", num_inserts, + _("POIs were added to the POI database. The following screen will " + "allow you to modify or delete any of the new POIs.")); + popup_error(parent, buffer); + } + else + { + popup_error(parent, _("No POIs were found.")); + } + + if(default_cat_label) + g_free(default_cat_label); + + vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, num_inserts); + return num_inserts; +} + +static void +poi_list_free(GList *poi_list) +{ + GList *curr; + printf("%s()\n", __PRETTY_FUNCTION__); + + for(curr = poi_list; curr; curr = curr->next) + { + PoiInfo *poi_info = curr->data; + if(poi_info) + { + if(poi_info->label) + g_free(poi_info->label); + if(poi_info->desc) + g_free(poi_info->desc); + if(poi_info->clabel) + g_free(poi_info->clabel); + g_slice_free(PoiInfo, poi_info); + } + } + + g_list_free(poi_list); + + vprintf("%s(): return\n", __PRETTY_FUNCTION__); +} + +static void +poi_list_bearing_cell_data_func( + GtkTreeViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + gchar buffer[80]; + gfloat f; + vprintf("%s()\n", __PRETTY_FUNCTION__); + + gtk_tree_model_get(tree_model, iter, POI_BEARING, &f, -1); + snprintf(buffer, sizeof(buffer), "%.1f", f); + g_object_set(cell, "text", buffer, NULL); + + vprintf("%s(): return\n", __PRETTY_FUNCTION__); +} + +static void +poi_list_distance_cell_data_func( + GtkTreeViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + gchar buffer[80]; + gfloat f; + vprintf("%s()\n", __PRETTY_FUNCTION__); + + gtk_tree_model_get(tree_model, iter, POI_DISTANCE, &f, -1); + snprintf(buffer, sizeof(buffer), "%.2f", f); + g_object_set(cell, "text", buffer, NULL); + + vprintf("%s(): return\n", __PRETTY_FUNCTION__); +} + +static gboolean +poi_list_row_selected(GtkCellRendererToggle *renderer, + gchar *path_string, GtkTreeModel *tree_model) +{ + GtkTreeIter iter; + vprintf("%s()\n", __PRETTY_FUNCTION__); + + if(gtk_tree_model_get_iter_from_string(tree_model, &iter, path_string)) + { + gboolean old_value; + gtk_tree_model_get(tree_model, &iter, POI_SELECTED, &old_value, -1); + gtk_list_store_set(GTK_LIST_STORE(tree_model), &iter, + POI_SELECTED, !old_value, + -1); + } + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +static gboolean +poi_list_set_category(GtkWidget *widget, PoiListInfo *pli) +{ + static GtkWidget *dialog = NULL; + static GtkWidget *cmb_category = NULL; + static GtkWidget *btn_catedit = NULL; + static PoiCategoryEditInfo pcedit; + printf("%s()\n", __PRETTY_FUNCTION__); + + if(dialog == NULL) + { + GtkWidget *hbox; + GtkWidget *label; + + dialog = gtk_dialog_new_with_buttons(_("Set Category..."), + GTK_WINDOW(pli->dialog2), GTK_DIALOG_MODAL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, + NULL); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + hbox = gtk_hbox_new(FALSE, 4), FALSE, FALSE, 4); + + gtk_box_pack_start(GTK_BOX(hbox), + label = gtk_label_new(_("Category")), + FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(hbox), + cmb_category = poi_create_cat_combo(), + FALSE, FALSE, 4); + + gtk_box_pack_start(GTK_BOX(hbox), + btn_catedit = gtk_button_new_with_label( + _("Edit Categories...")), + FALSE, FALSE, 0); + + /* Connect Signals */ + pcedit.dialog = dialog; + pcedit.cmb_category = cmb_category; + pcedit.cat_id = -1; + g_signal_connect(G_OBJECT(btn_catedit), "clicked", + G_CALLBACK(poi_edit_cat), &pcedit); + } + + gtk_widget_show_all(dialog); + + while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) + { + GtkTreeIter iter; + GtkListStore *store; + gint cat_id; + const gchar *cat_label; + + /* Get the text of the chosen category. */ + if(!gtk_combo_box_get_active_iter( + GTK_COMBO_BOX(cmb_category), &iter)) + { + popup_error(dialog, _("Please specify a category.")); + continue; + } + + gtk_tree_model_get( + gtk_combo_box_get_model(GTK_COMBO_BOX(cmb_category)), + &iter, + 0, &cat_id, + 1, &cat_label, + -1); + + /* Iterate through the data store and categorize as desired. */ + store = GTK_LIST_STORE(gtk_tree_view_get_model( + GTK_TREE_VIEW(pli->tree_view))); + if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) do + { + PoiInfo poi; + gboolean selected; + + memset(&poi, 0, sizeof(poi)); + + gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, + POI_SELECTED, &selected, + POI_POIID, &(poi.poi_id), + POI_LAT, &(poi.lat), + POI_LON, &(poi.lon), + POI_LABEL, &(poi.label), + POI_DESC, &(poi.desc), + -1); + + if(selected) + { + gtk_list_store_set(store, &iter, + POI_CATID, cat_id, + POI_CLABEL, cat_label, + -1); + /* edit poi */ + if(SQLITE_OK != sqlite3_bind_double( + _stmt_update_poi, 1, poi.lat) || + SQLITE_OK != sqlite3_bind_double( + _stmt_update_poi, 2, poi.lon) || + SQLITE_OK != sqlite3_bind_text(_stmt_update_poi, + 3, poi.label, -1, SQLITE_STATIC) || + SQLITE_OK != sqlite3_bind_text(_stmt_update_poi, + 4, poi.desc, -1, SQLITE_STATIC) || + SQLITE_OK != sqlite3_bind_int( + _stmt_update_poi, 5, cat_id) || + SQLITE_OK != sqlite3_bind_int( + _stmt_update_poi, 6, poi.poi_id) || + SQLITE_DONE != sqlite3_step(_stmt_update_poi)) + { + MACRO_BANNER_SHOW_INFO(pli->dialog2, + _("Error updating POI")); + } + sqlite3_reset(_stmt_update_poi); + } + } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter)); + + break; + } + + map_force_redraw(); + gtk_widget_hide(dialog); + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +static gboolean +poi_list_select_all(GtkTreeViewColumn *column, PoiListInfo *pli) +{ + GtkTreeIter iter; + GtkListStore *store; + printf("%s()\n", __PRETTY_FUNCTION__); + + /* Iterate through the data store and select as desired. */ + store = GTK_LIST_STORE(gtk_tree_view_get_model( + GTK_TREE_VIEW(pli->tree_view))); + if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) do + { + gtk_list_store_set(store, &iter, + POI_SELECTED, pli->select_all, + -1); + } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter)); + + pli->select_all = !pli->select_all; + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +static gboolean +poi_list_view(GtkWidget *widget, PoiListInfo *pli) +{ + GtkTreeIter iter; + GtkTreeSelection *selection; + GtkListStore *store; + printf("%s()\n", __PRETTY_FUNCTION__); + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(pli->tree_view)); + store = GTK_LIST_STORE(gtk_tree_view_get_model( + GTK_TREE_VIEW(pli->tree_view))); + + /* Iterate through the data store and import as desired. */ + if(gtk_tree_selection_get_selected(selection, NULL, &iter)) + { + PoiInfo poi; + memset(&poi, 0, sizeof(poi)); + + gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, + POI_POIID, &(poi.poi_id), + POI_CATID, &(poi.cat_id), + POI_LAT, &(poi.lat), + POI_LON, &(poi.lon), + POI_LABEL, &(poi.label), + POI_DESC, &(poi.desc), + POI_CLABEL, &(poi.clabel), + -1); + + if(poi_dialog(pli->dialog, &poi, FALSE)) + { + gtk_list_store_set(store, &iter, + POI_POIID, poi.poi_id, + POI_CATID, poi.cat_id, + POI_LAT, poi.lat, + POI_LON, poi.lon, + POI_LABEL, poi.label, + POI_DESC, poi.desc, + POI_CLABEL, poi.clabel, + -1); + } + else + { + /* POI was deleted. */ + gtk_list_store_remove(store, &iter); + } + g_free(poi.label); + g_free(poi.desc); + g_free(poi.clabel); + } + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +static void +poi_list_row_activated(GtkTreeView *tree_view, GtkTreePath *path, + GtkTreeViewColumn *column, PoiListInfo *pli) +{ + printf("%s()\n", __PRETTY_FUNCTION__); + + if(column != pli->select_column) + poi_list_view(GTK_WIDGET(tree_view), pli); + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); +} + +static gboolean +poi_list_goto(GtkWidget *widget, PoiListInfo *pli) +{ + GtkTreeIter iter; + GtkTreeSelection *selection; + GtkListStore *store; + printf("%s()\n", __PRETTY_FUNCTION__); + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(pli->tree_view)); + store = GTK_LIST_STORE(gtk_tree_view_get_model( + GTK_TREE_VIEW(pli->tree_view))); + + /* Iterate through the data store and import as desired. */ + if(gtk_tree_selection_get_selected(selection, NULL, &iter)) + { + gdouble lat, lon; + Point unit; + + gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, + POI_LAT, &lat, + POI_LON, &lon, + -1); + + latlon2unit(lat, lon, unit.unitx, unit.unity); + + if(_center_mode > 0) + gtk_check_menu_item_set_active( + GTK_CHECK_MENU_ITEM(_menu_view_ac_none_item), TRUE); + + map_center_unit(unit); + } + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +static gboolean +poi_list_delete(GtkWidget *widget, PoiListInfo *pli) +{ + GtkWidget *confirm; + printf("%s()\n", __PRETTY_FUNCTION__); + + confirm = hildon_note_new_confirmation( + GTK_WINDOW(pli->dialog2), _("Delete selected POI?")); + + if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) + { + GtkTreeIter iter; + GtkListStore *store; + gboolean already_next; + gboolean must_iterate;; + + /* Iterate through the data store and import as desired. */ + store = GTK_LIST_STORE(gtk_tree_view_get_model( + GTK_TREE_VIEW(pli->tree_view))); + if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) do + { + gboolean selected; + must_iterate = TRUE; + already_next = FALSE; + gint poi_id; + gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, + POI_SELECTED, &selected, + POI_POIID, &poi_id, + -1); + if(selected) + { + /* Delete POI. */ + if(SQLITE_OK != sqlite3_bind_int(_stmt_delete_poi, 1, poi_id) + || SQLITE_DONE != sqlite3_step(_stmt_delete_poi)) + { + MACRO_BANNER_SHOW_INFO(pli->dialog2, + _("Error deleting POI")); + } + else + { + already_next = gtk_list_store_remove(store, &iter); + must_iterate = FALSE; + } + sqlite3_reset(_stmt_delete_poi); + } + } while(already_next || (must_iterate + && gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter))); + } + + map_force_redraw(); + + gtk_widget_destroy(confirm); + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +static gboolean +poi_list_export_gpx(GtkWidget *widget, PoiListInfo *pli) +{ + GnomeVFSHandle *handle; + printf("%s()\n", __PRETTY_FUNCTION__); + + if(display_open_file(GTK_WINDOW(pli->dialog2), NULL, &handle, NULL, + NULL, NULL, GTK_FILE_CHOOSER_ACTION_SAVE)) + { + gint num_exported = gpx_poi_write( + gtk_tree_view_get_model(GTK_TREE_VIEW(pli->tree_view)), handle); + if(num_exported >= 0) + { + gchar buffer[80]; + snprintf(buffer, sizeof(buffer), "%d %s\n", num_exported, + _("POIs Exported")); + MACRO_BANNER_SHOW_INFO(pli->dialog2, buffer); + } + else + popup_error(pli->dialog2, _("Error writing GPX file.")); + gnome_vfs_close(handle); + } + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +static gboolean +poi_list_manage_checks(GtkWidget *widget, PoiListInfo *pli) +{ + GtkWidget *btn_category; + GtkWidget *btn_delete; + GtkWidget *btn_export_gpx; + + printf("%s()\n", __PRETTY_FUNCTION__); + + pli->dialog2 = gtk_dialog_new_with_buttons(_("Checked POI Actions..."), + GTK_WINDOW(pli->dialog), GTK_DIALOG_MODAL, + NULL); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pli->dialog2)->vbox), + gtk_label_new(_("Select an operation to perform\n" + "on the POIs that you checked\n" + "in the POI list.")), + FALSE, FALSE, 4); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pli->dialog2)->vbox), + btn_category = gtk_button_new_with_label(_("Set Category...")), + FALSE, FALSE, 4); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pli->dialog2)->vbox), + btn_delete = gtk_button_new_with_label(_("Delete...")), + FALSE, FALSE, 4); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pli->dialog2)->vbox), + btn_export_gpx = gtk_button_new_with_label( + _("Export to GPX...")), + FALSE, FALSE, 4); + + gtk_dialog_add_button(GTK_DIALOG(pli->dialog2), + GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT); + + g_signal_connect(G_OBJECT(btn_category), "clicked", + G_CALLBACK(poi_list_set_category), pli); + + g_signal_connect(G_OBJECT(btn_delete), "clicked", + G_CALLBACK(poi_list_delete), pli); + + g_signal_connect(G_OBJECT(btn_export_gpx), "clicked", + G_CALLBACK(poi_list_export_gpx), pli); + + gtk_widget_show_all(pli->dialog2); + + gtk_dialog_run(GTK_DIALOG(pli->dialog2)); + + gtk_widget_destroy(pli->dialog2); + pli->dialog2 = NULL; + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +static gboolean +poi_list_dialog(GtkWidget *parent, gint unitx, gint unity, GList *poi_list) +{ + static PoiListInfo pli = { NULL, NULL }; + static GtkWidget *scroller; + static GtkWidget *btn_goto; + static GtkWidget *btn_edit; + static GtkWidget *btn_manage_checks; + static GtkListStore *store; + GtkTreeIter iter; + GList *curr; + gdouble src_lat, src_lon; + printf("%s()\n", __PRETTY_FUNCTION__); + + if(pli.dialog == NULL) + { + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + pli.dialog = gtk_dialog_new_with_buttons(_("POI List"), + GTK_WINDOW(parent), GTK_DIALOG_MODAL, + NULL); + + store = gtk_list_store_new(POI_NUM_COLUMNS, + G_TYPE_BOOLEAN,/* Selected */ + G_TYPE_INT, /* POI ID */ + G_TYPE_INT, /* Category ID */ + G_TYPE_DOUBLE, /* Latitude */ + G_TYPE_DOUBLE, /* Longitude */ + G_TYPE_STRING, /* Lat/Lon */ + G_TYPE_FLOAT, /* Bearing */ + G_TYPE_FLOAT, /* Distance */ + G_TYPE_STRING, /* POI Label */ + G_TYPE_STRING, /* POI Desc. */ + G_TYPE_STRING);/* Category Label */ + + /* Set up the tree view. */ + pli.tree_view = gtk_tree_view_new(); + g_object_set(G_OBJECT(pli.tree_view), + "allow-checkbox-mode", FALSE, NULL); + + gtk_tree_selection_set_mode( + gtk_tree_view_get_selection(GTK_TREE_VIEW(pli.tree_view)), + GTK_SELECTION_SINGLE); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(pli.tree_view), TRUE); + + renderer = gtk_cell_renderer_toggle_new(); + gtk_cell_renderer_toggle_set_active(GTK_CELL_RENDERER_TOGGLE(renderer), + TRUE); + g_signal_connect(G_OBJECT(renderer), "toggled", + G_CALLBACK(poi_list_row_selected), store); + pli.select_column = gtk_tree_view_column_new_with_attributes( + "*", renderer, "active", POI_SELECTED, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(pli.tree_view), + pli.select_column); + gtk_tree_view_column_set_clickable(pli.select_column, TRUE); + g_signal_connect(G_OBJECT(pli.select_column), "clicked", + G_CALLBACK(poi_list_select_all), &pli); + + renderer = gtk_cell_renderer_combo_new(); + column = gtk_tree_view_column_new_with_attributes( + _("Category"), renderer, "text", POI_CLABEL, NULL); + gtk_tree_view_column_set_sizing(column,GTK_TREE_VIEW_COLUMN_GROW_ONLY); + gtk_tree_view_column_set_sort_column_id(column, POI_CLABEL); + gtk_tree_view_append_column(GTK_TREE_VIEW(pli.tree_view), column); + + renderer = gtk_cell_renderer_text_new(); + g_object_set(renderer, "xalign", 1.f, NULL); + column = gtk_tree_view_column_new_with_attributes( + _("Dist."), renderer, "text", POI_DISTANCE, NULL); + gtk_tree_view_column_set_cell_data_func(column, renderer, + (GtkTreeCellDataFunc)poi_list_distance_cell_data_func, + NULL, NULL); + gtk_tree_view_column_set_sort_column_id(column, POI_DISTANCE); + gtk_tree_view_append_column(GTK_TREE_VIEW(pli.tree_view), column); + + renderer = gtk_cell_renderer_text_new(); + g_object_set(renderer, "xalign", 1.f, NULL); + column = gtk_tree_view_column_new_with_attributes( + _("Bear."), renderer, "text", POI_BEARING, NULL); + gtk_tree_view_column_set_cell_data_func(column, renderer, + (GtkTreeCellDataFunc)poi_list_bearing_cell_data_func, + NULL, NULL); + gtk_tree_view_column_set_sort_column_id(column, POI_BEARING); + gtk_tree_view_append_column(GTK_TREE_VIEW(pli.tree_view), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes( + _("Label"), renderer, "text", POI_LABEL, NULL); + gtk_tree_view_column_set_sort_column_id(column, POI_LABEL); + gtk_tree_view_append_column(GTK_TREE_VIEW(pli.tree_view), column); + + g_signal_connect(G_OBJECT(pli.tree_view), "row-activated", + G_CALLBACK(poi_list_row_activated), &pli); + + gtk_tree_view_set_model(GTK_TREE_VIEW(pli.tree_view), + GTK_TREE_MODEL(store)); + g_object_unref(G_OBJECT(store)); + + /* Enable the help button. */ +#ifndef LEGACY + hildon_help_dialog_help_enable( +#else + ossohelp_dialog_help_enable( +#endif + GTK_DIALOG(pli.dialog), HELP_ID_POILIST, _osso); + + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(pli.dialog)->action_area), + btn_goto = gtk_button_new_with_label(_("Go to"))); + + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(pli.dialog)->action_area), + btn_edit = gtk_button_new_with_label(_("Edit..."))); + + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(pli.dialog)->action_area), + btn_manage_checks = gtk_button_new_with_label( + _("Checked POI Actions..."))); + + gtk_dialog_add_button(GTK_DIALOG(pli.dialog), + GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT); + + gtk_window_set_default_size(GTK_WINDOW(pli.dialog), 500, 400); + + scroller = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroller), + GTK_SHADOW_ETCHED_IN); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroller), + GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pli.dialog)->vbox), + scroller, TRUE, TRUE, 0); + + gtk_container_add(GTK_CONTAINER(scroller), pli.tree_view); + + g_signal_connect(G_OBJECT(btn_goto), "clicked", + G_CALLBACK(poi_list_goto), &pli); + + g_signal_connect(G_OBJECT(btn_edit), "clicked", + G_CALLBACK(poi_list_view), &pli); + + g_signal_connect(G_OBJECT(btn_manage_checks), "clicked", + G_CALLBACK(poi_list_manage_checks), &pli); + } + + /* Initialize the tree store. */ + + gtk_list_store_clear(store); + pli.select_all = FALSE; + + unit2latlon(unitx, unity, src_lat, src_lon); + + for(curr = poi_list; curr; curr = curr->next) + { + PoiInfo *poi_info = curr->data; + gchar tmp1[LL_FMT_LEN], tmp2[LL_FMT_LEN]; + + printf("poi: (%f, %f, %s, %s)\n", + poi_info->lat, poi_info->lon, + poi_info->label, poi_info->desc); + + format_lat_lon(poi_info->lat, poi_info->lon, tmp1, tmp2); + //lat_format(poi_info->lat, tmp1); + //lon_format(poi_info->lon, tmp2); + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + POI_SELECTED, TRUE, + POI_POIID, poi_info->poi_id, + POI_LAT, poi_info->lat, + POI_LON, poi_info->lon, + POI_BEARING, calculate_bearing(src_lat, src_lon, + poi_info->lat, poi_info->lon), + POI_DISTANCE, calculate_distance(src_lat,src_lon, + poi_info->lat, poi_info->lon) * UNITS_CONVERT[_units], + POI_LABEL, poi_info->label, + POI_DESC, poi_info->desc, + POI_CATID, poi_info->cat_id, + POI_CLABEL, poi_info->clabel, + -1); + } + + gtk_widget_show_all(pli.dialog); + + GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(pli.dialog)); + + map_force_redraw(); + + gtk_widget_hide(pli.dialog); + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +gboolean +poi_import_dialog(gint unitx, gint unity) +{ + GtkWidget *dialog = NULL; + gboolean success = FALSE; + printf("%s()\n", __PRETTY_FUNCTION__); + + dialog = hildon_file_chooser_dialog_new(GTK_WINDOW(_window), + GTK_FILE_CHOOSER_ACTION_OPEN); + + gtk_widget_show_all(dialog); + + while(!success && gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) + { + gchar *file_uri_str = NULL; + gchar *bytes = NULL; + gint size; + GnomeVFSResult vfs_result; + GList *poi_list = NULL; + + file_uri_str = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog)); + + /* Parse the given file as GPX. */ + if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file( + file_uri_str, &size, &bytes))) + { + popup_error(dialog, gnome_vfs_result_to_string(vfs_result)); + } + else if(gpx_poi_parse(bytes, size, &poi_list)) + { + static GtkWidget *cat_dialog = NULL; + static GtkWidget *cmb_category = NULL; + static GtkWidget *btn_catedit = NULL; + static PoiCategoryEditInfo pcedit; + + if(!cat_dialog) + { + GtkWidget *hbox; + GtkWidget *label; + cat_dialog = gtk_dialog_new_with_buttons(_("Default Category"), + GTK_WINDOW(dialog), GTK_DIALOG_MODAL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, + NULL); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(cat_dialog)->vbox), + hbox = gtk_hbox_new(FALSE, 4), FALSE, FALSE, 4); + + gtk_box_pack_start(GTK_BOX(hbox), + label = gtk_label_new(_("Category")), + FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(hbox), + cmb_category = poi_create_cat_combo(), + FALSE, FALSE, 4); + + gtk_box_pack_start(GTK_BOX(hbox), + btn_catedit = gtk_button_new_with_label( + _("Edit Categories...")), + FALSE, FALSE, 0); + + /* Connect Signals */ + pcedit.dialog = dialog; + pcedit.cmb_category = cmb_category; + pcedit.cat_id = -1; + g_signal_connect(G_OBJECT(btn_catedit), "clicked", + G_CALLBACK(poi_edit_cat), &pcedit); + } + + gtk_widget_show_all(cat_dialog); + + while(GTK_RESPONSE_ACCEPT ==gtk_dialog_run(GTK_DIALOG(cat_dialog))) + { + if(gtk_combo_box_get_active(GTK_COMBO_BOX(cmb_category)) == -1) + { + popup_error(dialog, + _("Please specify a default category.")); + continue; + } + + /* Insert the POIs into the database. */ + gint num_inserts = poi_list_insert(dialog, + poi_list, GTK_COMBO_BOX(cmb_category)); + + if(num_inserts) + { + /* Hide the dialogs. */ + gtk_widget_hide(cat_dialog); + + /* Create a new dialog with the results. */ + poi_list_dialog(dialog, unitx, unity, poi_list); + success = TRUE; + } + break; + } + + gtk_widget_hide(cat_dialog); + + poi_list_free(poi_list); + } + else + popup_error(dialog, _("Error parsing GPX file.")); + + g_free(file_uri_str); + g_free(bytes); + } + + /* Hide the dialog. */ + gtk_widget_destroy(dialog); + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return success; +} + +static gboolean +poi_download_cat_selected(GtkComboBox *cmb_category, GtkEntry *txt_query) +{ + GtkTreeIter iter; + printf("%s()\n", __PRETTY_FUNCTION__); + + if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(cmb_category), &iter)) + { + gchar buffer[BUFFER_SIZE]; + GtkWidget *confirm = NULL; + gchar *category = NULL; + + gtk_tree_model_get( + gtk_combo_box_get_model(GTK_COMBO_BOX(cmb_category)), &iter, + 1, &category, + -1); + + if(*gtk_entry_get_text(txt_query)) + { + snprintf(buffer, sizeof(buffer), "%s\n %s", + _("Overwrite query with the following text?"), category); + confirm = hildon_note_new_confirmation(GTK_WINDOW(_window),buffer); + + } + + if(confirm == NULL + || GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) + gtk_entry_set_text(txt_query, category); + + if(confirm) + gtk_widget_destroy(confirm); + } + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + + +static gboolean +origin_type_selected(GtkWidget *toggle, OriginToggleInfo *oti) +{ + printf("%s()\n", __PRETTY_FUNCTION__); + + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle))) + gtk_widget_set_sensitive(oti->txt_origin, toggle == oti->rad_use_text); + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +gboolean +poi_download_dialog(gint unitx, gint unity) +{ + static GtkWidget *dialog = NULL; + static GtkWidget *hbox = NULL; + static GtkWidget *table = NULL; + static GtkWidget *table2 = NULL; + static GtkWidget *label = NULL; + static GtkWidget *num_page = NULL; + static GtkWidget *txt_source_url = NULL; + static OriginToggleInfo oti; + static GtkWidget *cmb_category; + printf("%s()\n", __PRETTY_FUNCTION__); + + conic_recommend_connected(); + + if(!dialog) + { + GtkEntryCompletion *origin_comp; + + dialog = gtk_dialog_new_with_buttons(_("Download POIs"), + GTK_WINDOW(_window), GTK_DIALOG_MODAL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, + NULL); + + /* Enable the help button. */ +#ifndef LEGACY + hildon_help_dialog_help_enable( +#else + ossohelp_dialog_help_enable( +#endif + GTK_DIALOG(dialog), HELP_ID_DOWNPOI, _osso); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + table = gtk_table_new(4, 4, FALSE), TRUE, TRUE, 0); + + /* Source URL. */ + gtk_table_attach(GTK_TABLE(table), + hbox = gtk_hbox_new(FALSE, 4), + 0, 4, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4); + gtk_box_pack_start(GTK_BOX(hbox), + label = gtk_label_new(_("Source URL")), FALSE, TRUE, 4); + gtk_box_pack_start(GTK_BOX(hbox), + txt_source_url = gtk_entry_new(), TRUE, TRUE, 4); + + /* Auto. */ + gtk_table_attach(GTK_TABLE(table), + oti.rad_use_gps = gtk_radio_button_new_with_label(NULL, + _("Use GPS Location")), + 0, 1, 1, 2, GTK_FILL, 0, 2, 4); + + /* Use End of Route. */ + gtk_table_attach(GTK_TABLE(table), + oti.rad_use_route = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(oti.rad_use_gps), _("Use End of Route")), + 0, 1, 2, 3, GTK_FILL, 0, 2, 4); + + + gtk_table_attach(GTK_TABLE(table), + gtk_vseparator_new(), + 1, 2, 1, 3, GTK_FILL, GTK_FILL, 2,4); + + /* Category. */ + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(_("Category")), + 2, 3, 1, 2, GTK_FILL, 0, 2, 4); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), + cmb_category = poi_create_cat_combo(), + 3, 4, 1, 2, GTK_FILL, 0, 2, 4); + + /* Page. */ + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(_("Page")), + 2, 3, 2, 3, GTK_FILL, 0, 2, 4); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), + num_page = hildon_number_editor_new(1, 999), + 3, 4, 2, 3, GTK_FILL, 0, 2, 4); + + + /* Another table for the Origin and Query. */ + gtk_table_attach(GTK_TABLE(table), + table2 = gtk_table_new(2, 2, FALSE), + 0, 4, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4); + + /* Origin. */ + gtk_table_attach(GTK_TABLE(table2), + oti.rad_use_text = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(oti.rad_use_gps), _("Origin")), + 0, 1, 0, 1, GTK_FILL, 0, 2, 4); + gtk_table_attach(GTK_TABLE(table2), + oti.txt_origin = gtk_entry_new(), + 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4); + gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_origin), 25); +#ifdef MAEMO_CHANGES +#ifndef LEGACY + g_object_set(G_OBJECT(oti.txt_origin), "hildon-input-mode", + HILDON_GTK_INPUT_MODE_FULL, NULL); +#else + g_object_set(G_OBJECT(oti.txt_origin), HILDON_AUTOCAP, FALSE, NULL); +#endif +#endif + + /* Query. */ + gtk_table_attach(GTK_TABLE(table2), + label = gtk_label_new(_("Query")), + 0, 1, 1, 2, GTK_FILL, 0, 2, 4); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table2), + oti.txt_query = gtk_entry_new(), + 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4); + gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_query), 25); +#ifdef MAEMO_CHANGES +#ifndef LEGACY + g_object_set(G_OBJECT(oti.txt_query), "hildon-input-mode", + HILDON_GTK_INPUT_MODE_FULL, NULL); +#else + g_object_set(G_OBJECT(oti.txt_query), HILDON_AUTOCAP, FALSE, NULL); +#endif +#endif + + /* Set up auto-completion. */ + origin_comp = gtk_entry_completion_new(); + gtk_entry_completion_set_model(origin_comp,GTK_TREE_MODEL(_loc_model)); + gtk_entry_completion_set_text_column(origin_comp, 0); + gtk_entry_set_completion(GTK_ENTRY(oti.txt_origin), origin_comp); + + g_signal_connect(G_OBJECT(oti.rad_use_gps), "toggled", + G_CALLBACK(origin_type_selected), &oti); + g_signal_connect(G_OBJECT(oti.rad_use_route), "toggled", + G_CALLBACK(origin_type_selected), &oti); + g_signal_connect(G_OBJECT(oti.rad_use_text), "toggled", + G_CALLBACK(origin_type_selected), &oti); + + g_signal_connect(G_OBJECT(cmb_category), "changed", + G_CALLBACK(poi_download_cat_selected), oti.txt_query); + } + + /* Initialize fields. */ + + hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(num_page), 1); + + gtk_entry_set_text(GTK_ENTRY(txt_source_url), _poi_dl_url); + if(unity != 0) + { + gchar buffer[80]; + gchar strlat[32]; + gchar strlon[32]; + gdouble lat, lon; + + unit2latlon(unitx, unity, lat, lon); + + g_ascii_formatd(strlat, 32, "%.06f", lat); + g_ascii_formatd(strlon, 32, "%.06f", lon); + snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon); + + gtk_entry_set_text(GTK_ENTRY(oti.txt_origin), buffer); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(oti.rad_use_text), TRUE); + } + /* Else use "End of Route" by default if they have a route. */ + else if(_route.head != _route.tail) + { + /* There is no route, so make it the default. */ + gtk_widget_set_sensitive(oti.rad_use_route, TRUE); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(oti.rad_use_route), TRUE); + gtk_widget_grab_focus(oti.rad_use_route); + } + /* Else use "GPS Location" if they have GPS enabled. */ + else + { + /* There is no route, so desensitize "Use End of Route." */ + gtk_widget_set_sensitive(oti.rad_use_route, FALSE); + if(_enable_gps) + { + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(oti.rad_use_gps), TRUE); + gtk_widget_grab_focus(oti.rad_use_gps); + } + /* Else use text. */ + else + { + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(oti.rad_use_text), TRUE); + gtk_widget_grab_focus(oti.txt_origin); + } + } + + gtk_widget_show_all(dialog); + + while(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) + { + gchar origin_buffer[BUFFER_SIZE]; + const gchar *source_url, *origin, *query; + gchar *file_uri_str = NULL; + gchar *bytes = NULL; + gint size; + GnomeVFSResult vfs_result; + GList *poi_list = NULL; + + source_url = gtk_entry_get_text(GTK_ENTRY(txt_source_url)); + if(!strlen(source_url)) + { + popup_error(dialog, _("Please specify a source URL.")); + continue; + } + else + { + g_free(_poi_dl_url); + _poi_dl_url = g_strdup(source_url); + } + + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps))) + { + gchar strlat[32]; + gchar strlon[32]; + latlon2unit(_gps.lat, _gps.lon, unitx, unity); + g_ascii_formatd(strlat, 32, "%.06f", _gps.lat); + g_ascii_formatd(strlon, 32, "%.06f", _gps.lon); + snprintf(origin_buffer, sizeof(origin_buffer), + "%s, %s", strlat, strlon); + origin = origin_buffer; + } + else if(gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON(oti.rad_use_route))) + { + gchar strlat[32]; + gchar strlon[32]; + Point *p; + gdouble lat, lon; + + /* Use last non-zero route point. */ + for(p = _route.tail; !p->unity; p--) { } + + unitx = p->unitx; + unity = p->unity; + unit2latlon(p->unitx, p->unity, lat, lon); + g_ascii_formatd(strlat, 32, "%.06f", lat); + g_ascii_formatd(strlon, 32, "%.06f", lon); + snprintf(origin_buffer, sizeof(origin_buffer), + "%s, %s", strlat, strlon); + origin = origin_buffer; + } + else + { + Point porig; + origin = gtk_entry_get_text(GTK_ENTRY(oti.txt_origin)); + if(*origin) + { + porig = locate_address(dialog, origin); + if(!porig.unity) + continue; + } + } + + if(!*origin) + { + popup_error(dialog, _("Please specify an origin.")); + continue; + } + + if(gtk_combo_box_get_active(GTK_COMBO_BOX(cmb_category)) == -1) + { + popup_error(dialog, _("Please specify a default category.")); + continue; + } + + query = gtk_entry_get_text(GTK_ENTRY(oti.txt_query)); + if(!strlen(query)) + { + popup_error(dialog, _("Please specify a query.")); + continue; + } + + /* Construct the URL. */ + { + gchar *origin_escaped; + gchar *query_escaped; + + origin_escaped = gnome_vfs_escape_string(origin); + query_escaped = gnome_vfs_escape_string(query); + file_uri_str = g_strdup_printf( + source_url, origin_escaped, query_escaped, + hildon_number_editor_get_value( + HILDON_NUMBER_EDITOR(num_page))); + g_free(origin_escaped); + g_free(query_escaped); + } + + /* Parse the given file as GPX. */ + if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file( + file_uri_str, &size, &bytes))) + { + popup_error(dialog, gnome_vfs_result_to_string(vfs_result)); + } + else if(strncmp(bytes, "vbox), + table = gtk_table_new(3, 4, FALSE), TRUE, TRUE, 0); + + /* Auto. */ + gtk_table_attach(GTK_TABLE(table), + oti.rad_use_gps = gtk_radio_button_new_with_label(NULL, + _("Use GPS Location")), + 0, 1, 0, 1, GTK_FILL, 0, 2, 4); + + /* Use End of Route. */ + gtk_table_attach(GTK_TABLE(table), + oti.rad_use_route = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(oti.rad_use_gps), _("Use End of Route")), + 0, 1, 1, 2, GTK_FILL, 0, 2, 4); + + gtk_table_attach(GTK_TABLE(table), + gtk_vseparator_new(), + 1, 2, 0, 2, GTK_FILL, GTK_FILL, 2, 4); + + /* Category. */ + gtk_table_attach(GTK_TABLE(table), + label = gtk_label_new(_("Category")), + 2, 3, 0, 1, GTK_FILL, 0, 2, 4); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table), + cmb_category = poi_create_cat_combo(), + 3, 4, 0, 1, GTK_FILL, 0, 2, 4); + /* Add an extra, "" category. */ + { + GtkTreeIter iter; + GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model( + GTK_COMBO_BOX(cmb_category))); + gtk_list_store_prepend(store, &iter); + gtk_list_store_set(store, &iter, 0, -1, 1, "", -1); + gtk_combo_box_set_active_iter(GTK_COMBO_BOX(cmb_category), &iter); + } + + + /* Another table for the Origin and Query. */ + gtk_table_attach(GTK_TABLE(table), + table2 = gtk_table_new(2, 2, FALSE), + 0, 4, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4); + + /* Origin. */ + gtk_table_attach(GTK_TABLE(table2), + oti.rad_use_text = gtk_radio_button_new_with_label_from_widget( + GTK_RADIO_BUTTON(oti.rad_use_gps), _("Origin")), + 0, 1, 0, 1, GTK_FILL, 0, 2, 4); + gtk_table_attach(GTK_TABLE(table2), + oti.txt_origin = gtk_entry_new(), + 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4); + gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_origin), 25); +#ifdef MAEMO_CHANGES +#ifndef LEGACY + g_object_set(G_OBJECT(oti.txt_origin), "hildon-input-mode", + HILDON_GTK_INPUT_MODE_FULL, NULL); +#else + g_object_set(G_OBJECT(oti.txt_origin), HILDON_AUTOCAP, FALSE, NULL); +#endif +#endif + + /* Destination. */ + gtk_table_attach(GTK_TABLE(table2), + label = gtk_label_new(_("Query")), + 0, 1, 1, 2, GTK_FILL, 0, 2, 4); + gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); + gtk_table_attach(GTK_TABLE(table2), + oti.txt_query = gtk_entry_new(), + 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4); + gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_query), 25); +#ifdef MAEMO_CHANGES +#ifndef LEGACY + g_object_set(G_OBJECT(oti.txt_query), "hildon-input-mode", + HILDON_GTK_INPUT_MODE_FULL, NULL); +#else + g_object_set(G_OBJECT(oti.txt_query), HILDON_AUTOCAP, FALSE, NULL); +#endif +#endif + + /* Set up auto-completion. */ + origin_comp = gtk_entry_completion_new(); + gtk_entry_completion_set_model(origin_comp,GTK_TREE_MODEL(_loc_model)); + gtk_entry_completion_set_text_column(origin_comp, 0); + gtk_entry_set_completion(GTK_ENTRY(oti.txt_origin), origin_comp); + + g_signal_connect(G_OBJECT(oti.rad_use_gps), "toggled", + G_CALLBACK(origin_type_selected), &oti); + g_signal_connect(G_OBJECT(oti.rad_use_route), "toggled", + G_CALLBACK(origin_type_selected), &oti); + g_signal_connect(G_OBJECT(oti.rad_use_text), "toggled", + G_CALLBACK(origin_type_selected), &oti); + } + + /* Initialize fields. */ + + if(unity != 0) + { + gchar buffer[80]; + gchar strlat[32]; + gchar strlon[32]; + gdouble lat, lon; + + unit2latlon(unitx, unity, lat, lon); + + g_ascii_formatd(strlat, 32, "%.06f", lat); + g_ascii_formatd(strlon, 32, "%.06f", lon); + snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon); + + gtk_entry_set_text(GTK_ENTRY(oti.txt_origin), buffer); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(oti.rad_use_text), TRUE); + } + /* Else use "End of Route" by default if they have a route. */ + else if(_route.head != _route.tail) + { + /* There is no route, so make it the default. */ + gtk_widget_set_sensitive(oti.rad_use_route, TRUE); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(oti.rad_use_route), TRUE); + gtk_widget_grab_focus(oti.rad_use_route); + } + /* Else use "GPS Location" if they have GPS enabled. */ + else + { + /* There is no route, so desensitize "Use End of Route." */ + gtk_widget_set_sensitive(oti.rad_use_route, FALSE); + if(_enable_gps) + { + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(oti.rad_use_gps), TRUE); + gtk_widget_grab_focus(oti.rad_use_gps); + } + /* Else use text. */ + else + { + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(oti.rad_use_text), TRUE); + gtk_widget_grab_focus(oti.txt_origin); + } + } + + gtk_widget_show_all(dialog); + + while(gtk_dialog_run(GTK_DIALOG(dialog)) ==GTK_RESPONSE_ACCEPT) + { + gchar buffer[BUFFER_SIZE]; + const gchar *origin, *query; + gdouble lat, lon; + GList *poi_list = NULL; + gint cat_id; + gboolean is_cat = FALSE; + sqlite3_stmt *stmt; + + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps))) + { + gchar strlat[32]; + gchar strlon[32]; + latlon2unit(_gps.lat, _gps.lon, unitx, unity); + g_ascii_formatd(strlat, 32, "%.06f", _gps.lat); + g_ascii_formatd(strlon, 32, "%.06f", _gps.lon); + snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon); + origin = buffer; + } + else if(gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON(oti.rad_use_route))) + { + gchar strlat[32]; + gchar strlon[32]; + Point *p; + gdouble lat, lon; + + /* Use last non-zero route point. */ + for(p = _route.tail; !p->unity; p--) { } + + unitx = p->unitx; + unity = p->unity; + unit2latlon(p->unitx, p->unity, lat, lon); + g_ascii_formatd(strlat, 32, "%.06f", lat); + g_ascii_formatd(strlon, 32, "%.06f", lon); + snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon); + origin = buffer; + } + else + { + Point porig; + origin = gtk_entry_get_text(GTK_ENTRY(oti.txt_origin)); + porig = locate_address(dialog, origin); + if(!porig.unity) + continue; + } + + if(!strlen(origin)) + { + popup_error(dialog, _("Please specify an origin.")); + continue; + } + + /* Check if we're doing a category search. */ + { + GtkTreeIter iter; + if(gtk_combo_box_get_active_iter( + GTK_COMBO_BOX(cmb_category), &iter)) + { + gtk_tree_model_get( + gtk_combo_box_get_model(GTK_COMBO_BOX(cmb_category)), + &iter, 0, &cat_id, -1); + if(cat_id >= 0) + { + is_cat = TRUE; + } + } + } + + query = g_strdup_printf("%%%s%%", + gtk_entry_get_text(GTK_ENTRY(oti.txt_query))); + + unit2latlon(unitx, unity, lat, lon); + + if(is_cat) + { + if(SQLITE_OK != sqlite3_bind_int(_stmt_browsecat_poi, 1, cat_id) || + SQLITE_OK != sqlite3_bind_text(_stmt_browsecat_poi, 2, query, + -1, g_free) || + SQLITE_OK != sqlite3_bind_double(_stmt_browsecat_poi, 3, lat) || + SQLITE_OK != sqlite3_bind_double(_stmt_browsecat_poi, 4, lon)) + { + g_printerr("Failed to bind values for _stmt_browsecat_poi\n"); + continue; + } + stmt = _stmt_browsecat_poi; + } + else + { + if(SQLITE_OK != sqlite3_bind_text(_stmt_browse_poi, 1, query, + -1, g_free) || + SQLITE_OK != sqlite3_bind_double(_stmt_browse_poi, 2, lat) || + SQLITE_OK != sqlite3_bind_double(_stmt_browse_poi, 3, lon)) + { + g_printerr("Failed to bind values for _stmt_browse_poi\n"); + continue; + } + stmt = _stmt_browse_poi; + } + + while(SQLITE_ROW == sqlite3_step(stmt)) + { + PoiInfo *poi = g_slice_new(PoiInfo); + poi->poi_id = sqlite3_column_int(stmt, 0); + poi->cat_id = sqlite3_column_int(stmt, 1); + poi->lat = sqlite3_column_double(stmt, 2); + poi->lon = sqlite3_column_double(stmt, 3); + poi->label =g_strdup(sqlite3_column_text(stmt, 4)); + poi->desc = g_strdup(sqlite3_column_text(stmt, 5)); + poi->clabel=g_strdup(sqlite3_column_text(stmt, 6)); + poi_list = g_list_prepend(poi_list, poi); + } + sqlite3_reset(stmt); + + if(poi_list) + { + /* Create a new dialog with the results. */ + poi_list_dialog(dialog, unitx, unity, poi_list); + poi_list_free(poi_list); + } + else + popup_error(dialog, _("No POIs found.")); + } + + map_force_redraw(); + + /* Hide the dialog. */ + gtk_widget_hide(dialog); + + vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); + return TRUE; +} + +/** + * Render all the POI data. This should be done before rendering track data. + */ +void +map_render_poi() +{ + gint unitx, unity; + gdouble lat1, lat2, lon1, lon2; + gchar buffer[100]; + gint poix, poiy; + GdkPixbuf *pixbuf = NULL; + GError *error = NULL; + printf("%s()\n", __PRETTY_FUNCTION__); + + if(_poi_db && _poi_zoom > _zoom) + { + gint diag_offset = pixel2unit(MAX(_view_width_pixels, + _view_height_pixels) / 2); + buf2unit(0, _view_height_pixels, unitx, unity); + unitx = _center.unitx - diag_offset; + unity = _center.unity + diag_offset; + unit2latlon(unitx, unity, lat1, lon1); + unitx = _center.unitx + diag_offset; + unity = _center.unity - diag_offset; + unit2latlon(unitx, unity, lat2, lon2); + + if(SQLITE_OK != sqlite3_bind_double(_stmt_select_poi, 1, lat1) || + SQLITE_OK != sqlite3_bind_double(_stmt_select_poi, 2, lat2) || + SQLITE_OK != sqlite3_bind_double(_stmt_select_poi, 3, lon1) || + SQLITE_OK != sqlite3_bind_double(_stmt_select_poi, 4, lon2)) + { + g_printerr("Failed to bind values for _stmt_select_poi\n"); + return; + } + + while(SQLITE_ROW == sqlite3_step(_stmt_select_poi)) + { + lat1 = sqlite3_column_double(_stmt_select_poi, 0); + lon1 = sqlite3_column_double(_stmt_select_poi, 1); + gchar *poi_label = g_utf8_strdown(sqlite3_column_text( + _stmt_select_poi, 3), -1); + gchar *cat_label = g_utf8_strdown(sqlite3_column_text( + _stmt_select_poi, 6), -1); + + latlon2unit(lat1, lon1, unitx, unity); + unit2buf(unitx, unity, poix, poiy); + + /* Try to get icon for specific POI first. */ + snprintf(buffer, sizeof(buffer), "%s/%s.jpg", + _poi_db_dirname, poi_label); + pixbuf = gdk_pixbuf_new_from_file(buffer, &error); + if(error) + { + /* No icon for specific POI - try for category. */ + g_error_free(error); + error = NULL; + snprintf(buffer, sizeof(buffer), "%s/%s.jpg", + _poi_db_dirname, cat_label); + pixbuf = gdk_pixbuf_new_from_file(buffer, &error); + } + if(error) + { + /* No icon for POI or for category. + * Try default POI icon file. */ + g_error_free(error); + error = NULL; + snprintf(buffer, sizeof(buffer), "%s/poi.jpg", + _poi_db_dirname); + pixbuf = gdk_pixbuf_new_from_file(buffer, &error); + } + if(error) + { + /* No icon for POI or for category or default POI icon file. + Draw default purple square. */ + g_error_free(error); + error = NULL; + gdk_draw_rectangle(_map_pixmap, _gc[COLORABLE_POI], TRUE, + poix - (gint)(1.5f * _draw_width), + poiy - (gint)(1.5f * _draw_width), + 3 * _draw_width, + 3 * _draw_width); + } + else + { + /* We found an icon to draw. */ + gdk_draw_pixbuf( + _map_pixmap, + _gc[COLORABLE_POI], + pixbuf, + 0, 0, + poix - gdk_pixbuf_get_width(pixbuf) / 2, + poiy - gdk_pixbuf_get_height(pixbuf) / 2, + -1,-1, + GDK_RGB_DITHER_NONE, 0, 0); + g_object_unref(pixbuf); + } + + g_free(poi_label); + g_free(cat_label); + } + sqlite3_reset(_stmt_select_poi); + } + + vprintf("%s(): return\n", __PRETTY_FUNCTION__); +} + +void +poi_destroy() +{ + printf("%s()\n", __PRETTY_FUNCTION__); + + if(_poi_db) + { + sqlite3_close(_poi_db); + _poi_db = NULL; + } + + vprintf("%s(): return\n", __PRETTY_FUNCTION__); +} + +#ifdef INCLUDE_APRS +extern AprsDataRow *n_first; // pointer to first element in name sorted station list + + +///////////////////// + +/** + * Render all the APRS data. + */ +void +map_render_aprs() +{ + printf("%s()\n", __PRETTY_FUNCTION__); + + if(_poi_zoom > _zoom) + { + + AprsDataRow *p_station = n_first; + + while ( (p_station) != NULL) + { + if( p_station->coord_lat != 0.0f + || p_station->coord_lon != 0.0f ) + { + plot_aprs_station( p_station, FALSE); + } // If valid data + + (p_station) = (p_station)->n_next; // Next element in list + } // End of while loop + + + } // check for zoom level + + vprintf("%s(): return\n", __PRETTY_FUNCTION__); +} + +#endif // INCLUDE_APRS +