]> err.no Git - mapper/blob - src/track.c
Go back to strcmp
[mapper] / src / track.c
1 #include <config.h>
2
3 #include "utils.h"
4 #include "gps.h"
5 #include "map.h"
6 #include "route.h"
7 #include "settings.h"
8 #include "mapper-types.h"
9 #include "ui-common.h"
10 #include "file.h"
11
12 #include "track.h"
13 #include "latlon.h"
14 #include "path.h"
15 #include "gpx.h"
16 #include "speak.h"
17
18 struct sql_select_stmt {
19         sqlite3_stmt *select_track;
20         sqlite3_stmt *select_track_nodes;
21         sqlite3_stmt *insert_track;
22         sqlite3_stmt *insert_track_node;
23         sqlite3_stmt *delete_track_nodes;
24         sqlite3_stmt *delete_track;
25 };
26 static struct sql_select_stmt sql;
27
28 void
29 track_init(void)
30 {
31 memset(&_track, 0, sizeof(_track));
32 MACRO_PATH_INIT(_track);
33 }
34
35 void
36 track_deinit(void)
37 {
38 MACRO_PATH_FREE(_track);
39 }
40
41 void 
42 track_clear(void)
43 {
44 GtkWidget *confirm;
45
46 confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), _("Clear the track?"));
47
48 if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) {
49         _track.tail = _track.head;
50         map_force_redraw();
51 }
52 gtk_widget_destroy(confirm);
53 }
54
55 gdouble
56 track_calculate_distance_from(Point *point)
57 {
58 gdouble lat1, lon1, lat2, lon2;
59 gdouble sum = 0.0;
60 Point *curr;
61 unit2latlon(_gps->data.unitx, _gps->data.unity, lat1, lon1);
62
63 /* Skip _track.tail because that should be _gps. */
64 for (curr = _track.tail; curr > point; --curr) {
65         if (curr->unity) {
66                 unit2latlon(curr->unitx, curr->unity, lat2, lon2);
67                 sum += calculate_distance(lat1, lon1, lat2, lon2);
68                 lat1 = lat2;
69                 lon1 = lon2;
70         }
71 }
72 return sum;
73 }
74
75 void 
76 track_show_distance_from(Point * point)
77 {
78 gchar buffer[80];
79 gdouble sum;
80
81 sum = track_calculate_distance_from(point);
82
83 g_snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"),
84          sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]);
85 MACRO_BANNER_SHOW_INFO(_window, buffer);
86 }
87
88 void 
89 track_show_distance_from_last()
90 {
91 /* Find last zero point. */
92 if (_track.head != _track.tail) {
93         Point *point;
94         /* Find last zero point. */
95         for (point = _track.tail; point->unity; point--) {
96         }
97         track_show_distance_from(point);
98 } else {
99         MACRO_BANNER_SHOW_INFO(_window, _("The current track is empty."));
100 }
101 }
102
103 void 
104 track_show_distance_from_first()
105 {
106 if (_track.head != _track.tail) {
107         track_show_distance_from(_track.head);
108 } else {
109         MACRO_BANNER_SHOW_INFO(_window, _("The current track is empty."));
110 }
111 }
112
113 /**
114  * Add a point to the _track list.  This function is slightly overloaded,
115  * since it is what houses the check for "have we moved
116  * significantly": it also initiates the re-calculation of the _near_point
117  * data, as well as calling osso_display_state_on() when we have the focus.
118  *
119  * If a non-zero time is given, then the current position (as taken from the
120  * _gps variable) is appended to _track with the given time.  If time is zero,
121  * then _point_null is appended to _track with time zero (this produces a "break"
122  * in the track).
123  */
124 void 
125 track_add(GpsData *gps, gboolean newly_fixed)
126 {
127 gboolean show_directions = TRUE;
128 gint announce_thres_unsquared;
129
130 if (!gps) {
131         MACRO_PATH_INCREMENT_TAIL(_track);
132         *_track.tail=_point_null;
133         return;
134 }
135
136 if (abs((gint)gps->unitx-_track.tail->unitx) > _draw_width || abs((gint)gps->unity-_track.tail->unity) > _draw_width) {
137
138         /* If gps is available, update the nearest-waypoint data. */
139         if (gps && _route.head != _route.tail && (newly_fixed ? (route_find_nearest_point(), TRUE) : route_update_nears(TRUE))) {
140                 /* Nearest waypoint has changed - re-render paths. */
141                 map_render_paths();
142                 MACRO_QUEUE_DRAW_AREA();
143         }
144
145         if (_show_tracks & TRACKS_MASK) {
146                 gint tx1, ty1, tx2, ty2;
147
148                 /* Instead of calling map_render_paths(), we'll draw the new line
149                  * ourselves and call gtk_widget_queue_draw_area(). */
150                 map_render_segment(_gc[COLORABLE_TRACK], _gc[COLORABLE_TRACK_BREAK],
151                                         _track.tail->unitx, _track.tail->unity, gps->unitx, gps->unity);
152
153                 if (_track.tail->unity && _track.tail->unitx) {
154                         tx1 = unit2x(_track.tail->unitx);
155                         ty1 = unit2y(_track.tail->unity);
156                         tx2 = unit2x(gps->unitx);
157                         ty2 = unit2y(gps->unity);
158                         gtk_widget_queue_draw_area(_map_widget,
159                                            MIN(tx1, tx2) - _draw_width, 
160                                            MIN(ty1, ty2) - _draw_width,
161                                            abs(tx1 - tx2) + (2 * _draw_width),
162                                            abs(ty1 - ty2) + (2 * _draw_width));
163                 }
164         }
165
166         MACRO_PATH_INCREMENT_TAIL(_track);
167         _track.tail->unitx=gps->unitx;
168         _track.tail->unity=gps->unity;
169         _track.tail->time=gps->time;
170         _track.tail->altitude=gps->altitude;
171 }
172
173 if (_autoroute_data.enabled && !_autoroute_data.in_progress && _near_point_dist_squared > 400) {
174         MACRO_BANNER_SHOW_INFO(_window, _("Recalculating directions..."));
175         _autoroute_data.in_progress = TRUE;
176         show_directions = FALSE;
177         g_idle_add((GSourceFunc)auto_route_dl_idle, NULL);
178 }
179
180 announce_thres_unsquared=(20+(guint)gps->speed)*_announce_notice_ratio*3;
181
182 /* Check if we should announce upcoming waypoints. */
183 if (gps && show_directions && _next_way_dist_squared < (announce_thres_unsquared * announce_thres_unsquared)) {
184         if (_enable_voice && strcmp(_next_way->desc, _last_spoken_phrase)) {
185                 g_free(_last_spoken_phrase);
186                 _last_spoken_phrase=g_strdup(_next_way->desc);
187                 speak_text(_last_spoken_phrase);
188         }
189         MACRO_BANNER_SHOW_INFO(_window, _next_way->desc);
190 }
191
192 /* Keep the display on if we are moving. */
193 KEEP_DISPLAY_ON();
194 }
195
196 void 
197 track_insert_break(void)
198 {
199 if (_track.tail->unity) {
200         guint x1, y1;
201
202 /* To mark a "waypoint" in a track, we'll add a (0, 0) point and then
203  * another instance of the most recent track point. */
204 MACRO_PATH_INCREMENT_TAIL(_track);
205 *_track.tail=_point_null;
206 MACRO_PATH_INCREMENT_TAIL(_track);
207 *_track.tail=_track.tail[-2];
208
209 /* Instead of calling map_render_paths(), we'll just add the waypoint ourselves. */
210 x1 = unit2bufx(_track.tail->unitx);
211 y1 = unit2bufy(_track.tail->unity);
212 /* Make sure this circle will be visible. */
213 if ((x1 < BUF_WIDTH_PIXELS) && ((unsigned)y1 < BUF_HEIGHT_PIXELS))
214         gdk_draw_arc(_map_pixmap, _gc[COLORABLE_TRACK_BREAK], FALSE,
215                 x1 - _draw_width, y1 - _draw_width,
216                 2 * _draw_width, 2 * _draw_width, 0,
217                 360 * 64);
218 } else {
219         MACRO_BANNER_SHOW_INFO(_window, _("Break already inserted."));
220 }
221 }
222
223 gboolean
224 track_open(void)
225 {
226 gchar *buffer;
227 gint size;
228 gboolean r = FALSE;
229
230 if (file_open_get_contents(&_track_file_uri, &buffer, &size)) {
231         if (parse_gpx(&_track, buffer, size, -1)) {
232                 map_force_redraw();
233                 MACRO_BANNER_SHOW_INFO(_window, _("Track Opened"));
234                 r = TRUE;
235         } else {
236                 popup_error(_window, _("Error parsing GPX file."));
237         }
238         g_free(buffer);
239 }
240 return r;
241 }
242
243 gboolean
244 track_save(void)
245 {
246 GnomeVFSHandle *handle;
247 gboolean r = FALSE;
248
249 if (file_save(&_track_file_uri, &_track_file_uri, &handle)) {
250         if (write_gpx(&_track, handle)) {
251                 MACRO_BANNER_SHOW_INFO(_window, _("Track Saved"));
252                 r = TRUE;
253                 track_clear();
254         } else {
255                 popup_error(_window, _("Error writing GPX file."));
256         }
257         gnome_vfs_close(handle);
258 }
259 return r;
260 }
261
262 /**
263  * Add a text description at current point
264  * 
265  */
266 void 
267 track_insert_mark_text(gchar *text)
268 {
269 MACRO_PATH_INCREMENT_WTAIL(_track);
270 _track.wtail->point = _track.tail;
271 _track.wtail->desc = text;
272 }
273
274 /**
275  * Ask for a text description for the current point
276  *
277  */
278 gboolean
279 track_insert_mark(void)
280 {
281 gdouble lat, lon;
282 gchar tmp1[16], tmp2[16], *p_latlon;
283 GtkWidget *dialog;
284 GtkWidget *table;
285 GtkWidget *label;
286 GtkWidget *txt_scroll;
287 GtkWidget *txt_desc;
288
289 dialog = gtk_dialog_new_with_buttons(_("Insert Mark"),
290                                      GTK_WINDOW(_window),
291                                      GTK_DIALOG_MODAL, GTK_STOCK_OK,
292                                      GTK_RESPONSE_ACCEPT,
293                                      GTK_STOCK_CANCEL,
294                                      GTK_RESPONSE_REJECT, NULL);
295
296 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table = gtk_table_new(2, 2, FALSE), TRUE, TRUE, 0);
297
298 gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Lat, Lon")), 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
299 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
300
301 unit2latlon(_gps->data.unitx, _gps->data.unity, lat, lon);
302 lat_format(_degformat, lat, tmp1);
303 lon_format(_degformat, lon, tmp2);
304 p_latlon = g_strdup_printf("%s, %s", tmp1, tmp2);
305 gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(p_latlon), 1, 2, 0, 1, GTK_FILL, 0, 2, 4);
306 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
307 g_free(p_latlon);
308
309 gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Description")), 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
310 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
311
312 txt_scroll = gtk_scrolled_window_new(NULL, NULL);
313 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll), GTK_SHADOW_IN);
314 gtk_table_attach(GTK_TABLE(table), txt_scroll, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
315
316 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
317
318 txt_desc = gtk_text_view_new();
319 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD);
320
321 gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc);
322 gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 450, 80);
323
324 gtk_widget_show_all(dialog);
325
326 while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
327         GtkTextBuffer *tbuf;
328         GtkTextIter ti1, ti2;
329
330         tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_desc));
331         gtk_text_buffer_get_iter_at_offset(tbuf, &ti1, 0);
332         gtk_text_buffer_get_end_iter(tbuf, &ti2);
333
334         if (gtk_text_buffer_get_char_count(tbuf)>0) {
335                 track_insert_mark_text(gtk_text_buffer_get_text(tbuf, &ti1, &ti2, TRUE));
336         } else {
337                 popup_error(dialog, _("Please provide a description for the mark."));
338                 continue;
339         }
340
341         map_render_paths();
342         MACRO_QUEUE_DRAW_AREA();
343         break;
344 }
345 gtk_widget_destroy(dialog);
346 return TRUE;
347 }