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