]> err.no Git - mapper/blob - src/search.c
Use shared setter for search result.
[mapper] / src / search.c
1 /*
2  * This file is part of mapper
3  *
4  * Copyright (C) 2007 Kaj-Michael Lang
5  * Copyright (C) 2006-2007 John Costigan.
6  *
7  * POI and GPS-Info code originally written by Cezary Jackiewicz.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  */
24
25 #include <config.h>
26
27 #define _GNU_SOURCE
28
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <stddef.h>
34 #include <locale.h>
35 #include <math.h>
36 #include <errno.h>
37 #include <sys/wait.h>
38 #include <glib/gstdio.h>
39 #include <gtk/gtk.h>
40 #include <fcntl.h>
41 #include <libintl.h>
42 #include <locale.h>
43
44 #include "utils.h"
45 #include "poi.h"
46 #include "gps.h"
47 #include "map.h"
48 #include "mapper-types.h"
49 #include "ui-common.h"
50 #include "settings.h"
51 #include "poi-gui.h"
52 #include "osm.h"
53 #include "help.h"
54 #include "osm-db.h"
55 #include "search.h"
56
57 typedef struct _search_query poi_search_query;
58 struct _search_query {
59         gdouble lat;
60         gdouble lon;
61         guint cat_id;
62         gchar *query;
63 };
64
65 typedef struct _search_dialog search_dialog;
66 struct _search_dialog {
67         GtkWidget *dialog;
68         GtkWidget *cmb_type;
69         GtkWidget *cmb_category;
70         GtkWidget *list;
71         GtkWidget *search_entry;
72         GtkWidget *btn_edit;
73         GtkWidget *label;
74         GtkListStore *store;
75         gdouble lat;
76         gdouble lon;
77         mapper_search_type stype;
78 };
79
80 static search_dialog sd;
81
82 static gboolean
83 search_do_cb(GtkWidget *widget, gpointer data)
84 {
85 gchar *st;
86 guint cid;
87 GtkTreeIter iter;
88 guint slen;
89 search_dialog *s=(search_dialog *)data;
90 gboolean sres=FALSE;
91 slen=strlen(gtk_entry_get_text(GTK_ENTRY(s->search_entry)));
92
93 if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(s->cmb_category), &iter)==TRUE)
94         gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(s->cmb_category)), &iter, 0, &cid, -1);
95 else
96         cid=-1;
97 if (s->stype==SEARCH_TYPE_POI && cid==-1 && slen<2) {
98         popup_error(s->dialog, _("Query string too short. Minimum 2 characters."));
99         return TRUE;
100 } else if (slen<2 && s->stype!=SEARCH_TYPE_POI) {
101         popup_error(s->dialog, _("Query string too short. Minimum 2 characters."));
102         return TRUE;
103 }
104
105 st=g_strdup(gtk_entry_get_text(GTK_ENTRY(s->search_entry)));
106
107 switch (s->stype) {
108         case SEARCH_TYPE_POI:
109                 sres=poi_search((cid==-1) ? POI_SEARCH_TEXT : POI_SEARCH_TEXT_CAT, s->lat, s->lon, st, cid, &s->store);
110         break;
111         case SEARCH_TYPE_WAY:
112                 sres=osm_way_search(s->lat, s->lon, st, &s->store);
113         break;
114         case SEARCH_TYPE_PLACE:
115                 popup_error(s->dialog, "Not yet implemented");
116                 sres=FALSE;
117         break;
118 }
119
120 if (sres==TRUE) {
121         gtk_tree_view_set_model(GTK_TREE_VIEW(s->list), GTK_TREE_MODEL(s->store));
122         g_object_unref(G_OBJECT(s->store));
123 } else {
124         s->store=NULL;
125         gtk_tree_view_set_model(GTK_TREE_VIEW(s->list), GTK_TREE_MODEL(s->store));
126 }
127
128 g_free(st);
129 return TRUE;
130 }
131
132 static gboolean
133 search_get_list_item_latlon(GtkWidget *list, gdouble *lat, gdouble *lon)
134 {
135 GtkTreeIter iter;
136 GtkTreeModel *model;
137
138 if (!gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), NULL, &iter))
139         return FALSE;
140
141 model=gtk_tree_view_get_model(GTK_TREE_VIEW(list)); 
142 if (!model)
143         return FALSE;
144
145 gtk_tree_model_get(model, &iter, ITEM_LAT, lat, -1);
146 gtk_tree_model_get(model, &iter, ITEM_LON, lon, -1);
147 return TRUE;
148 }
149
150 static guint
151 search_get_list_item_id(GtkWidget *list)
152 {
153 guint id;
154 GtkTreeIter iter;
155 GtkTreeModel *model;
156
157 if (!gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), NULL, &iter))
158         return 0;
159
160 model=gtk_tree_view_get_model(GTK_TREE_VIEW(list)); 
161 if (!model)
162         return 0;
163
164 gtk_tree_model_get(model, &iter, ITEM_ID, &id, -1);
165 return id;
166 }
167
168 static gboolean
169 search_goto_cb(GtkWidget *widget, gpointer data)
170 {
171 gdouble lat, lon;
172 search_dialog *s=(search_dialog *)data;
173
174 if (search_get_list_item_latlon(s->list, &lat, &lon)==FALSE) {
175         popup_error(s->dialog, _("Select a location from the list."));
176         return TRUE;
177 }
178
179 map_center_latlon(lat, lon);
180 map_update_location_from_center();
181 return TRUE;
182 }
183
184 static gboolean
185 search_route_to_cb(GtkWidget *widget, gpointer data)
186 {
187 search_dialog *s=(search_dialog *)data;
188
189 if (search_get_list_item_latlon(s->list, &_dest.lat, &_dest.lon)==FALSE) {
190         popup_error(s->dialog, _("Select a location from the list."));
191         return TRUE;
192 }
193
194 _dest.valid=TRUE;
195 map_update_location_from_center();
196
197 return TRUE;
198 }
199
200 static gboolean
201 search_edit_cb(GtkWidget *widget, gpointer data)
202 {
203 search_dialog *s=(search_dialog *)data;
204
205 switch (s->stype) {
206         case SEARCH_TYPE_POI:
207         break;
208         default:
209         break;
210 }
211 return TRUE;
212 }
213
214 static void
215 search_set_dialog_mode(search_dialog *s)
216 {
217 s->stype=gtk_combo_box_get_active(GTK_COMBO_BOX(s->cmb_type));
218 switch (s->stype) {
219         case SEARCH_TYPE_POI:
220                 gtk_widget_show(s->cmb_category);
221                 gtk_widget_set_sensitive(s->btn_edit, TRUE);
222         break;
223         case SEARCH_TYPE_WAY:
224         case SEARCH_TYPE_PLACE:
225                 gtk_widget_hide(s->cmb_category);
226                 gtk_widget_set_sensitive(s->btn_edit, FALSE);
227         break;
228         default:
229                 g_assert_not_reached();
230         break;
231 }
232 }
233
234 static gboolean
235 search_type_changed_cb(GtkWidget *widget, gpointer data)
236 {
237 search_dialog *s=(search_dialog *)data;
238 search_set_dialog_mode(s);
239 if (s->store)
240         gtk_list_store_clear(s->store);
241 s->store=NULL;
242 gtk_tree_view_set_model(GTK_TREE_VIEW(s->list), GTK_TREE_MODEL(s->store));
243 return TRUE;
244 }
245
246 static void
247 search_item_activated_cb(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data)
248 {
249 #if 0
250 search_dialog *s=(search_dialog *)data;
251 gtk_widget_destroy(sd.dialog);
252 #endif
253 }
254
255 gboolean
256 mapper_search_dialog(mapper_search_type stype, gdouble lat, gdouble lon)
257 {
258 GtkWidget *sw, *hbox, *label, *btn_search, *btn_goto, *btn_route_to;
259 GtkTreeViewColumn *column;
260 GtkCellRenderer *renderer;
261
262 sd.store=NULL;
263 sd.lat=lat;
264 sd.lon=lon;
265 sd.stype=stype;
266
267 sd.dialog = gtk_dialog_new_with_buttons(_("Search"),
268                         GTK_WINDOW(_window),
269                         GTK_DIALOG_MODAL, 
270                         GTK_STOCK_CANCEL,
271                         GTK_RESPONSE_REJECT, 
272                         NULL);
273
274 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(sd.dialog)->action_area), btn_goto = gtk_button_new_with_label(_("Go to")));
275 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(sd.dialog)->action_area), btn_route_to = gtk_button_new_with_label(_("Route to")));
276 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(sd.dialog)->action_area), sd.btn_edit = gtk_button_new_with_label(_("Edit")));
277
278 gtk_window_set_default_size(GTK_WINDOW(sd.dialog), 500, 300);
279
280 hbox = gtk_hbox_new(FALSE, 4),
281 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sd.dialog)->vbox), hbox, FALSE, FALSE, 0);
282
283 label=gtk_label_new(_("Search:"));
284 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
285
286 sd.cmb_type=gtk_combo_box_new_text();
287 gtk_combo_box_append_text(GTK_COMBO_BOX(sd.cmb_type), "POI");
288 gtk_combo_box_append_text(GTK_COMBO_BOX(sd.cmb_type), "Street");
289 gtk_combo_box_append_text(GTK_COMBO_BOX(sd.cmb_type), "Place");
290 gtk_box_pack_start(GTK_BOX(hbox), sd.cmb_type, FALSE, FALSE, 0);
291
292 sd.cmb_category = category_combo_new();
293 gtk_box_pack_start(GTK_BOX(hbox), sd.cmb_category, FALSE, FALSE, 0);
294 poi_category_combo_populate(sd.cmb_category, 0, TRUE);
295
296 sd.search_entry=gtk_entry_new();
297 gtk_box_pack_start(GTK_BOX(hbox), sd.search_entry, TRUE, TRUE, 0);
298
299 btn_search=gtk_button_new_with_label(_("Search"));
300 gtk_box_pack_start(GTK_BOX(hbox), btn_search, FALSE, FALSE, 0);
301
302 sw = gtk_scrolled_window_new(NULL, NULL);
303 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
304 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
305 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sd.dialog)->vbox), sw, TRUE, TRUE, 0);
306
307 sd.list=gtk_tree_view_new();
308 gtk_tree_selection_set_mode(gtk_tree_view_get_selection (GTK_TREE_VIEW(sd.list)), GTK_SELECTION_SINGLE);
309 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(sd.list), TRUE);
310 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(sd.list), TRUE);
311
312 renderer = gtk_cell_renderer_text_new();
313 column = gtk_tree_view_column_new_with_attributes(_("Location"), renderer, "text", ITEM_LATLON, NULL);
314 gtk_tree_view_append_column(GTK_TREE_VIEW(sd.list), column);
315
316 renderer = gtk_cell_renderer_text_new();
317 column = gtk_tree_view_column_new_with_attributes(_("Distance"), renderer, "text", ITEM_DIST, NULL);
318 gtk_tree_view_column_set_sort_column_id (column, ITEM_DIST);
319 gtk_tree_view_append_column(GTK_TREE_VIEW(sd.list), column);
320
321 renderer = gtk_cell_renderer_text_new();
322 column = gtk_tree_view_column_new_with_attributes(_("Label"), renderer, "text", ITEM_LABEL, NULL);
323 gtk_tree_view_column_set_sort_column_id (column, ITEM_LABEL);
324 gtk_tree_view_append_column(GTK_TREE_VIEW(sd.list), column);
325
326 renderer = gtk_cell_renderer_text_new();
327 column = gtk_tree_view_column_new_with_attributes(_("Category"), renderer, "text", ITEM_CATLAB, NULL);
328 gtk_tree_view_column_set_sort_column_id (column, ITEM_CATLAB);
329 gtk_tree_view_append_column(GTK_TREE_VIEW(sd.list), column);
330
331 gtk_tree_view_set_search_column (GTK_TREE_VIEW(sd.list), ITEM_LABEL);
332 gtk_container_add(GTK_CONTAINER(sw), sd.list);
333
334 sd.label=gtk_label_new("");
335 gtk_box_pack_start(GTK_BOX(hbox), sd.label, FALSE, FALSE, 0);
336
337 g_signal_connect(G_OBJECT(btn_search), "clicked", G_CALLBACK(search_do_cb), &sd);
338 g_signal_connect(G_OBJECT(btn_goto), "clicked", G_CALLBACK(search_goto_cb), &sd);
339 g_signal_connect(G_OBJECT(btn_route_to), "clicked", G_CALLBACK(search_route_to_cb), &sd);
340 g_signal_connect(G_OBJECT(sd.btn_edit), "clicked", G_CALLBACK(search_edit_cb), &sd);
341 g_signal_connect(G_OBJECT(sd.cmb_type), "changed", G_CALLBACK(search_type_changed_cb), &sd);
342 g_signal_connect(G_OBJECT(sd.list), "row-activated", G_CALLBACK(search_item_activated_cb), &sd);
343
344 gtk_widget_show_all(sd.dialog);
345 gtk_combo_box_set_active(GTK_COMBO_BOX(sd.cmb_type), sd.stype);
346 search_set_dialog_mode(&sd);
347
348 gtk_dialog_run(GTK_DIALOG(sd.dialog));
349
350 gtk_widget_destroy(sd.dialog);
351 return TRUE;
352 }
353