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