2 * This file is part of Mapper
4 * Copyright (C) 2007-2008 Kaj-Michael Lang
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 * Contains extra path functions, specific to mapper.
27 #include <libgnomevfs/gnome-vfs.h>
33 #include "mapper-types.h"
34 #include "ui-common.h"
39 #include "path-mapper.h"
41 typedef struct _OriginToggleInfo OriginToggleInfo;
42 struct _OriginToggleInfo {
43 GtkWidget *rad_use_gps;
44 GtkWidget *rad_use_route;
45 GtkWidget *rad_use_text;
52 static gboolean route_auto_dl_idle_cb();
53 static void route_cancel_autoroute(Path *route, gboolean temporary);
60 * Ask confirmation to clear given path, using msg as the question.
62 * Returns: TRUE if path was cleared.
65 path_clear_ask(Path *path, const gchar *msg)
70 g_return_val_if_fail(path, FALSE);
72 confirm=hildon_note_new_confirmation(GTK_WINDOW(_window), msg);
73 if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) {
77 gtk_widget_destroy(confirm);
82 * path_show_distance_from:
86 path_show_distance_from(Path *path, Point *point)
91 if (path && path_has_points(path)) {
92 dist=path_calculate_distance_from(path, point);
93 g_snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"), dist * UNITS_CONVERT[_units], UNITS_TEXT[_units]);
94 MACRO_BANNER_SHOW_INFO(_window, buffer);
96 MACRO_BANNER_SHOW_INFO(_window, _("The current path is empty."));
101 * path_show_distance_from_last:
105 path_show_distance_from_last(Path *path)
109 g_return_if_fail(path);
111 point=path_find_last_point(path);
112 g_return_if_fail(point);
114 path_show_distance_from(path, point);
118 * path_show_distance_from_first:
122 path_show_distance_from_first(Path *path)
124 g_return_if_fail(path);
126 path_show_distance_from(path, path->head);
130 * path_show_distance_to:
132 * Show the distance from the current GPS location to the given point,
133 * following the route. If point is NULL, then the distance is shown to the
137 path_show_distance_to(Path *route, Point *point)
143 g_return_val_if_fail(route, FALSE);
145 unit2latlon(point->unitx, point->unity, &lat, &lon);
146 sum=path_get_distance_to(route, point, lat, lon);
147 g_snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"), sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]);
148 MACRO_BANNER_SHOW_INFO(_window, buffer);
154 * path_show_distance_to_next_waypoint:
156 * Display distance to next waypoint in given route
160 path_show_distance_to_next_waypoint(Path *route)
162 g_return_if_fail(route);
164 if (!path_show_distance_to(route, NULL))
165 MACRO_BANNER_SHOW_INFO(_window, _("There is no next waypoint."));
169 * path_show_distance_to_last:
171 * Show distance to last point in given route
175 path_show_distance_to_last(Path *route)
177 g_return_if_fail(route);
179 if (route->head != route->tail) {
180 path_show_distance_to(route, path_find_last_point(route));
182 MACRO_BANNER_SHOW_INFO(_window, _("The current route is empty."));
187 * route_autoroute_check:
189 * Check if we should re-calculate route
192 route_autoroute_check(Path *path)
194 g_return_if_fail(path);
196 if (_autoroute_data.enabled && !_autoroute_data.in_progress && path->near_point_dist_squared > 400) {
197 _autoroute_data.in_progress = TRUE;
198 g_idle_add((GSourceFunc)route_auto_dl_idle_cb, NULL);
199 MACRO_BANNER_SHOW_INFO(_window, _("Recalculating directions..."));
205 path_open(Path *track)
211 if (file_open_get_contents(&_track_file_uri, &buffer, &size)) {
212 if (path_gpx_parse(track, buffer, size, GPX_PATH_NEW)) {
213 MACRO_BANNER_SHOW_INFO(_window, _("Track Opened"));
216 popup_error(_window, _("Error parsing track GPX file."));
224 path_save(Path *track)
226 GnomeVFSHandle *handle;
229 if (file_save(&_track_file_uri, &_track_file_uri, &handle)) {
230 if (path_gpx_write(track, handle, NULL)) {
231 MACRO_BANNER_SHOW_INFO(_window, _("Track Saved"));
233 path_clear_ask(track, _("Clear track ?"));
235 popup_error(_window, _("Error writing track GPX file."));
237 gnome_vfs_close(handle);
246 * Open a route GPX file
250 route_open_file(Path *route)
255 g_return_val_if_fail(route, FALSE);
257 if (file_open_get_contents(&_route_dir_uri, &buffer, &size)) {
258 /* If auto is enabled, append the route, otherwise replace it. */
259 if (path_gpx_parse(route, buffer, size, _autoroute_data.enabled ? GPX_PATH_APPEND : GPX_PATH_NEW)) {
260 route_cancel_autoroute(route, FALSE);
262 MACRO_BANNER_SHOW_INFO(_window, _("Route Opened"));
263 /* Find the nearest route point, if we're connected. */
264 path_find_nearest_point(route, _gps->data.lat, _gps->data.lon);
265 path_set_destination_from_last(route, &_dest);
268 popup_error(_window, _("Error parsing route GPX file."));
279 * Ask user to save route to GPX file.
283 route_save(Path *route)
285 GnomeVFSHandle *handle;
287 g_return_val_if_fail(route, FALSE);
289 if (route->head==route->tail) {
290 MACRO_BANNER_SHOW_INFO(_window, _("No route exist."));
294 if (file_save(&_route_dir_uri, &_route_dir_uri, &handle)) {
295 if (path_gpx_write(route, handle, NULL)) {
296 MACRO_BANNER_SHOW_INFO(_window, _("Route Saved"));
298 popup_error(_window, _("Error writing route GPX file."));
300 gnome_vfs_close(handle);
307 route_origin_type_selected_cb(GtkWidget *toggle, OriginToggleInfo *oti)
313 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle))) {
314 if (toggle == oti->rad_use_gps) {
315 g_ascii_formatd(strlat, 32, "%.06f", _gps->data.lat);
316 g_ascii_formatd(strlon, 32, "%.06f", _gps->data.lon);
317 g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon);
318 gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer);
319 } else if (toggle == oti->rad_use_route) {
323 p=path_find_last_point(oti->path);
325 unit2latlon(p->unitx, p->unity, &lat, &lon);
326 g_ascii_formatd(strlat, 32, "%.06f", lat);
327 g_ascii_formatd(strlon, 32, "%.06f", lon);
328 g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon);
329 gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer);
332 gtk_widget_set_sensitive(oti->txt_from, toggle == oti->rad_use_text);
333 gtk_widget_set_sensitive(oti->chk_auto, toggle == oti->rad_use_gps);
339 * route_cancel_autoroute:
341 * Cancel the current auto-route.
344 route_cancel_autoroute(Path *route, gboolean temporary)
346 if (_autoroute_data.enabled) {
348 _autoroute_data.enabled=FALSE;
350 g_free(_autoroute_data.dest);
351 _autoroute_data.dest=NULL;
353 g_free(_autoroute_data.src_str);
354 _autoroute_data.src_str=NULL;
357 if (_autoroute_data.curl_easy) {
358 if (_autoroute_data.curl_multi)
359 curl_multi_remove_handle(_autoroute_data.curl_multi, _autoroute_data.curl_easy);
360 curl_easy_cleanup(_autoroute_data.curl_easy);
361 curl_multi_cleanup(_autoroute_data.curl_multi);
362 _autoroute_data.curl_easy=NULL;
363 _autoroute_data.curl_multi=NULL;
366 g_free(_autoroute_data.rdl_data.bytes);
367 _autoroute_data.rdl_data.bytes=NULL;
368 _autoroute_data.rdl_data.bytes_read=0;
369 _autoroute_data.in_progress=FALSE;
374 route_auto_download_timeout()
379 if (!_autoroute_data.curl_multi) {
380 route_cancel_autoroute(_route, TRUE);
384 while (_autoroute_data.curl_multi && (msg = curl_multi_info_read(_autoroute_data.curl_multi, &num_msgs))) {
385 if (msg->msg == CURLMSG_DONE) {
386 /* Now, parse the autoroute and update the display. */
387 if (_autoroute_data.enabled && path_gpx_parse(_route, _autoroute_data.rdl_data.bytes, _autoroute_data.rdl_data.bytes_read, 0)) {
388 /* Find the nearest route point, if we're connected. */
389 path_find_nearest_point(_route, _gps->data.lat, _gps->data.lon);
391 route_cancel_autoroute(_route, TRUE); /* We're done. Clean up. */
399 * Read the data provided by the given handle as GPX data, updating the
400 * auto-route with that data.
403 route_auto_dl_read_cb(void *ptr, size_t size, size_t nmemb, RouteDownloadData * rdl_data)
405 size_t old_size = rdl_data->bytes_read;
407 rdl_data->bytes_read += size * nmemb;
408 rdl_data->bytes = g_renew(gchar, rdl_data->bytes, rdl_data->bytes_read);
409 g_memmove(rdl_data->bytes + old_size, ptr, size * nmemb);
411 return (size * nmemb);
415 route_auto_dl_idle_cb()
417 gchar latstr[32], lonstr[32], *latlonstr;
419 g_ascii_dtostr(latstr, 32, _gps->data.lat);
420 g_ascii_dtostr(lonstr, 32, _gps->data.lon);
421 latlonstr = g_strdup_printf("%s,%s", latstr, lonstr);
422 _autoroute_data.src_str = g_strdup_printf(_route_dl_url, latlonstr, _autoroute_data.dest);
425 MACRO_CURL_EASY_INIT(_autoroute_data.curl_easy);
426 curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_URL, _autoroute_data.src_str);
427 curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_WRITEFUNCTION, route_auto_dl_read_cb);
428 curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_WRITEDATA, &_autoroute_data.rdl_data);
429 _autoroute_data.curl_multi=curl_multi_init();
430 curl_multi_add_handle(_autoroute_data.curl_multi, _autoroute_data.curl_easy);
432 if (iap_is_connected() && !_autoroute_data.curl_sid)
433 _autoroute_data.curl_sid=g_timeout_add(250, (GSourceFunc)route_auto_download_timeout, NULL);
435 _autoroute_data.in_progress=TRUE;
441 * Display a dialog box to the user asking them to download a route. The
442 * "From" and "To" textfields may be initialized using the first two
443 * parameters. The third parameter, if set to TRUE, will cause the "Use GPS
444 * Location" checkbox to be enabled, which automatically sets the "From" to the
445 * current GPS position (this overrides any value that may have been passed as
446 * the "To" initializer).
447 * None of the passed strings are freed - that is left to the caller, and it is
448 * safe to free either string as soon as this function returns.
451 route_download_dialog(Path *route, gchar *to)
456 GtkWidget *txt_source_url;
458 OriginToggleInfo oti;
459 GtkEntryCompletion *from_comp;
460 GtkEntryCompletion *to_comp;
465 memset(&_autoroute_data, 0, sizeof(_autoroute_data));
467 dialog = gtk_dialog_new_with_buttons(_("Download Route"),
469 GTK_DIALOG_MODAL, GTK_STOCK_OK,
472 GTK_RESPONSE_REJECT, NULL);
474 help_dialog_help_enable(GTK_DIALOG(dialog), HELP_ID_DOWNROUTE);
475 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table = gtk_table_new(2, 5, FALSE), TRUE, TRUE, 0);
477 from_comp = gtk_entry_completion_new();
478 gtk_entry_completion_set_model(from_comp, GTK_TREE_MODEL(_loc_model));
479 gtk_entry_completion_set_text_column(from_comp, 0);
480 to_comp = gtk_entry_completion_new();
481 gtk_entry_completion_set_model(to_comp, GTK_TREE_MODEL(_loc_model));
482 gtk_entry_completion_set_text_column(to_comp, 0);
485 gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Source URL")), 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
486 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
487 gtk_table_attach(GTK_TABLE(table), txt_source_url = gtk_entry_new(), 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
488 gtk_entry_set_width_chars(GTK_ENTRY(txt_source_url), 25);
491 gtk_table_attach(GTK_TABLE(table), hbox = gtk_hbox_new(FALSE, 6), 0, 2, 1, 2, GTK_FILL, 0, 2, 4);
492 gtk_box_pack_start(GTK_BOX(hbox), oti.rad_use_gps = gtk_radio_button_new_with_label(NULL, _("Use GPS Location")), TRUE, TRUE, 0);
493 gtk_box_pack_start(GTK_BOX(hbox), oti.chk_auto = gtk_check_button_new_with_label(_("Auto-Update")), TRUE, TRUE, 0);
494 gtk_widget_set_sensitive(oti.chk_auto, FALSE);
496 /* Use End of Route. */
497 gtk_table_attach(GTK_TABLE(table), hbox = gtk_hbox_new(FALSE, 6), 0, 2, 2, 3, GTK_FILL, 0, 2, 4);
498 gtk_box_pack_start(GTK_BOX(hbox), oti.rad_use_route = gtk_radio_button_new_with_label_from_widget
499 (GTK_RADIO_BUTTON(oti.rad_use_gps), _("Use End of Route")), TRUE, TRUE, 0);
500 gtk_widget_set_sensitive(oti.rad_use_route, route->head != route->tail);
503 gtk_table_attach(GTK_TABLE(table), oti.rad_use_text = gtk_radio_button_new_with_label_from_widget
504 (GTK_RADIO_BUTTON(oti.rad_use_gps), _("Origin")), 0, 1, 3, 4, GTK_FILL, 0, 2, 4);
505 gtk_table_attach(GTK_TABLE(table), oti.txt_from = gtk_entry_new(), 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
506 gtk_entry_set_completion(GTK_ENTRY(oti.txt_from), from_comp);
507 gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_from), 25);
510 gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Destination")), 0, 1, 4, 5, GTK_FILL, 0, 2, 4);
511 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
512 gtk_table_attach(GTK_TABLE(table), oti.txt_to = gtk_entry_new(), 1, 2, 4, 5, GTK_EXPAND | GTK_FILL, 0, 2, 4);
513 gtk_entry_set_completion(GTK_ENTRY(oti.txt_to), to_comp);
514 gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_to), 25);
516 g_signal_connect(G_OBJECT(oti.rad_use_gps), "toggled", G_CALLBACK(route_origin_type_selected_cb), &oti);
517 g_signal_connect(G_OBJECT(oti.rad_use_route), "toggled", G_CALLBACK(route_origin_type_selected_cb), &oti);
518 g_signal_connect(G_OBJECT(oti.rad_use_text), "toggled", G_CALLBACK(route_origin_type_selected_cb), &oti);
520 #if defined (WITH_HILDON) && defined (HILDON_AUTOCAP)
521 g_object_set(G_OBJECT(oti.txt_from), HILDON_AUTOCAP, FALSE, NULL);
522 g_object_set(G_OBJECT(oti.txt_to), HILDON_AUTOCAP, FALSE, NULL);
525 /* Initialize fields. */
526 gtk_entry_set_text(GTK_ENTRY(txt_source_url), _route_dl_url);
527 gtk_entry_set_text(GTK_ENTRY(oti.txt_to), (to ? to : ""));
529 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_text), TRUE);
531 if (path_has_points(route)) {
532 /* Use "End of Route" by default if they have a route. */
533 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_route), TRUE);
534 gtk_widget_grab_focus(oti.rad_use_route);
535 } else if (_enable_gps) {
536 /* Else use "GPS Location" if they have GPS enabled. */
537 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps), TRUE);
538 gtk_widget_grab_focus(oti.rad_use_gps);
541 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_text), TRUE);
542 gtk_widget_grab_focus(oti.txt_from);
545 gtk_widget_show_all(dialog);
547 while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
549 RouteDownloadData rdl_data = { 0, 0 };
550 gchar buffer[BUFFER_SIZE];
551 const gchar *source_url, *from, *to;
552 gchar *from_escaped, *to_escaped;
554 source_url = gtk_entry_get_text(GTK_ENTRY(txt_source_url));
555 if (!strlen(source_url)) {
556 popup_error(dialog, _("Please specify a source URL."));
559 g_free(_route_dl_url);
560 _route_dl_url = g_strdup(source_url);
563 from = gtk_entry_get_text(GTK_ENTRY(oti.txt_from));
565 popup_error(dialog, _("Please specify a start location."));
569 to = gtk_entry_get_text(GTK_ENTRY(oti.txt_to));
571 popup_error(dialog, _("Please specify an end location."));
575 from_escaped = gnome_vfs_escape_string(from);
576 to_escaped = gnome_vfs_escape_string(to);
577 g_snprintf(buffer, sizeof(buffer), source_url, from_escaped, to_escaped);
578 g_free(from_escaped);
583 /* Attempt to download the route from the server. */
584 MACRO_CURL_EASY_INIT(curl_easy);
585 curl_easy_setopt(curl_easy, CURLOPT_URL, buffer);
586 curl_easy_setopt(curl_easy, CURLOPT_WRITEFUNCTION, route_auto_dl_read_cb);
587 curl_easy_setopt(curl_easy, CURLOPT_WRITEDATA, &rdl_data);
588 if (CURLE_OK != curl_easy_perform(curl_easy)) {
589 popup_error(dialog, _("Failed to connect to GPX Directions server"));
590 curl_easy_cleanup(curl_easy);
591 g_free(rdl_data.bytes);
592 /* Let them try again */
595 curl_easy_cleanup(curl_easy);
597 if (strncmp(rdl_data.bytes, "<?xml", strlen("<?xml"))) {
598 /* Not an XML document - must be bad locations. */
599 popup_error(dialog, _("Could not generate directions. Make sure your source and destination are valid."));
600 g_free(rdl_data.bytes);
601 /* Let them try again. */
603 /* Else, if GPS is enabled, replace the route, otherwise append it. */
604 else if (path_gpx_parse(route, rdl_data.bytes, rdl_data.bytes_read,
605 (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps)) ? GPX_PATH_NEW : GPX_PATH_APPEND))) {
608 /* Find the nearest route point, if we're connected. */
609 path_find_nearest_point(route, _gps->data.lat, _gps->data.lon);
611 /* Cancel any autoroute that might be occurring. */
612 route_cancel_autoroute(route, FALSE);
614 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.chk_auto))) {
615 /* Kick off a timeout to start the first update. */
616 _autoroute_data.dest = gnome_vfs_escape_string(to);
617 _autoroute_data.enabled = TRUE;
620 /* Save Origin in Route Locations list if not from GPS. */
621 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps)) && !g_slist_find_custom(_loc_list, from, (GCompareFunc) strcmp)) {
622 _loc_list = g_slist_prepend(_loc_list, g_strdup(from));
623 gtk_list_store_insert_with_values(_loc_model, &iter, INT_MAX, 0, from, -1);
626 /* Save Destination in Route Locations list. */
627 if (!g_slist_find_custom(_loc_list, to, (GCompareFunc) strcmp)) {
628 _loc_list = g_slist_prepend(_loc_list, g_strdup(to));
629 gtk_list_store_insert_with_values(_loc_model, &iter, INT_MAX, 0, to, -1);
632 g_free(rdl_data.bytes);
633 path_set_destination_from_last(route, &_dest);
635 MACRO_BANNER_SHOW_INFO(_window, _("Route Downloaded"));
637 /* Success! Get out of the while loop. */
641 popup_error(dialog, _("Error parsing route GPX data."));
642 g_free(rdl_data.bytes);
643 /* Let them try again. */
647 gtk_widget_hide(dialog); /* Destroying causes a crash (!?!?!??!) */
653 * Ask for a text description for the current point
657 path_insert_mark_ask(Path *track)
659 gchar tmp1[16], tmp2[16], *p_latlon;
663 GtkWidget *txt_scroll;
667 dialog = gtk_dialog_new_with_buttons(_("Insert Mark"),
668 GTK_WINDOW(_window), GTK_DIALOG_MODAL,
669 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
670 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
673 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table = gtk_table_new(2, 2, FALSE), TRUE, TRUE, 0);
675 gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Near Lat, Lon")), 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
676 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
678 lat_format(_degformat, _gps->data.lat, tmp1);
679 lon_format(_degformat, _gps->data.lon, tmp2);
680 p_latlon=g_strdup_printf("%s, %s", tmp1, tmp2);
681 gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(p_latlon), 1, 2, 0, 1, GTK_FILL, 0, 2, 4);
682 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
685 gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Description")), 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
686 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
688 txt_scroll=gtk_scrolled_window_new(NULL, NULL);
689 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll), GTK_SHADOW_IN);
690 gtk_table_attach(GTK_TABLE(table), txt_scroll, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
692 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
694 txt_desc=gtk_text_view_new();
695 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD);
697 gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc);
698 gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 450, 100);
700 gtk_widget_show_all(dialog);
703 while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
705 GtkTextIter ti1, ti2;
707 tbuf=gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_desc));
708 gtk_text_buffer_get_iter_at_offset(tbuf, &ti1, 0);
709 gtk_text_buffer_get_end_iter(tbuf, &ti2);
711 if (gtk_text_buffer_get_char_count(tbuf)>0) {
712 path_insert_mark_text(track, gtk_text_buffer_get_text(tbuf, &ti1, &ti2, TRUE));
714 popup_error(dialog, _("Please provide a description for the mark."));
721 gtk_widget_destroy(dialog);