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