]> git.street.me.uk Git - andy/viking.git/commitdiff
Add Acquiring 'My' OSM Traces as a datasource.
authorRob Norris <rw_norris@hotmail.com>
Tue, 27 Nov 2012 19:20:33 +0000 (19:20 +0000)
committerRob Norris <rw_norris@hotmail.com>
Wed, 23 Jan 2013 21:59:33 +0000 (21:59 +0000)
This is a two stage Acquire, first get a list of all the specified users traces (password required).
The dialog columns can be sorted to help select only those traces of interest.
Then get the Ids for the selected traces and download the individual GPX files.

po/POTFILES.in
src/Makefile.am
src/acquire.c
src/acquire.h
src/datasource_osm_my_traces.c [new file with mode: 0644]
src/datasources.h
src/menu.xml.h
src/osm-traces.c
src/osm-traces.h
src/viktrwlayer.c
src/vikwindow.c

index cc66eecf498ebdaea6766e8fa800fc8f35ea7e65..6bed62d3456f41fcbcda9862263827a8293650f9 100644 (file)
@@ -16,6 +16,7 @@ src/datasource_geotag.c
 src/datasource_google.c
 src/datasource_gps.c
 src/datasource_osm.c
+src/datasource_osm_my_traces.c
 src/datasource_wikipedia.c
 src/dem.c
 src/download.c
index ff9e542d142cd7aafbe47cdcd975dc6cbf39ae69..7c712e9c16b03417d7a2a3bc3ee1139d625d5e60 100644 (file)
@@ -151,6 +151,7 @@ if OPENSTREETMAP
 libviking_a_SOURCES += \
        osm.c osm.h \
        osm-traces.c osm-traces.h \
+       datasource_osm_my_traces.c \
        datasource_osm.c
 endif
 
index 5449155d5ef3c442a10f51a04b0d688a19737a01..a91497e6a91c5371e0c802c39d65b164a00f6b56 100644 (file)
@@ -361,6 +361,10 @@ static void acquire ( VikWindow *vw, VikLayersPanel *vlp, VikViewport *vvp, VikD
       wi->creating_new_layer = FALSE;
     }
   }
+  else if ( source_interface->mode == VIK_DATASOURCE_MANUAL_LAYER_MANAGEMENT ) {
+    // Don't create in acquire - as datasource will perform the necessary actions
+    wi->creating_new_layer = FALSE;
+  }
   if ( wi->creating_new_layer ) {
     wi->vtl = VIK_TRW_LAYER ( vik_layer_create ( VIK_LAYER_TRW, w->vvp, NULL, FALSE ) );
     vik_layer_rename ( VIK_LAYER ( wi->vtl ), _(source_interface->layer_title) );
index 75107810d93b529c1794379678e48af00c6f823e..50a8374c3ec50e891d3937e864062c8a5d622e73 100644 (file)
@@ -51,7 +51,8 @@ typedef struct {
 
 typedef enum {
   VIK_DATASOURCE_CREATENEWLAYER,
-  VIK_DATASOURCE_ADDTOLAYER
+  VIK_DATASOURCE_ADDTOLAYER,
+  VIK_DATASOURCE_MANUAL_LAYER_MANAGEMENT,
 } vik_datasource_mode_t;
 /* TODO: replace track/layer? */
 
diff --git a/src/datasource_osm_my_traces.c b/src/datasource_osm_my_traces.c
new file mode 100644 (file)
index 0000000..47a2363
--- /dev/null
@@ -0,0 +1,636 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
+ *
+ * Copyright (C) 2012, Rob Norris <rw_norris@hotmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <string.h>
+#include <limits.h>
+
+#include <glib/gprintf.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+
+#include <expat.h>
+
+#include "viking.h"
+#include "gpx.h"
+#include "acquire.h"
+#include "osm-traces.h"
+#include "preferences.h"
+#include "curl_download.h"
+#include "datasource_gps.h"
+
+/**
+ * See http://wiki.openstreetmap.org/wiki/API_v0.6#GPS_Traces
+ */
+#define DS_OSM_TRACES_GPX_URL_FMT "api.openstreetmap.org/api/0.6/gpx/%d/data"
+#define DS_OSM_TRACES_GPX_FILES "api.openstreetmap.org/api/0.6/user/gpx_files"
+
+typedef struct {
+       GtkWidget *user_entry;
+       GtkWidget *password_entry;
+       // NB actual user and password values are stored in oms-traces.c
+} datasource_osm_my_traces_t;
+
+static gpointer datasource_osm_my_traces_init( );
+static void datasource_osm_my_traces_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data );
+static void datasource_osm_my_traces_get_cmd_string ( gpointer user_data, gchar **args, gchar **extra, DownloadMapOptions *options );
+static gboolean datasource_osm_my_traces_process  ( VikTrwLayer *vtl, const gchar *cmd, const gchar *extra, BabelStatusFunc status_cb, acq_dialog_widgets_t *adw, DownloadMapOptions *options_unused );
+static void datasource_osm_my_traces_cleanup ( gpointer data );
+
+VikDataSourceInterface vik_datasource_osm_my_traces_interface = {
+  N_("OSM My Traces"),
+  N_("OSM My Traces"),
+  VIK_DATASOURCE_MANUAL_LAYER_MANAGEMENT, // we'll do this ourselves
+  VIK_DATASOURCE_INPUTTYPE_NONE,
+  TRUE,
+  TRUE,
+  FALSE, // Don't use thread method
+  (VikDataSourceInitFunc)                  datasource_osm_my_traces_init,
+  (VikDataSourceCheckExistenceFunc)    NULL,
+  (VikDataSourceAddSetupWidgetsFunc)datasource_osm_my_traces_add_setup_widgets,
+  (VikDataSourceGetCmdStringFunc)      datasource_osm_my_traces_get_cmd_string,
+  (VikDataSourceProcessFunc)           datasource_osm_my_traces_process,
+  (VikDataSourceProgressFunc)          NULL,
+  (VikDataSourceAddProgressWidgetsFunc)        NULL,
+  (VikDataSourceCleanupFunc)           datasource_osm_my_traces_cleanup,
+  (VikDataSourceOffFunc)            NULL,
+
+  NULL,
+  0,
+  NULL,
+  NULL,
+  0
+};
+
+static gpointer datasource_osm_my_traces_init ( )
+{
+  datasource_osm_my_traces_t *data = g_malloc(sizeof(*data));
+  // Reuse GPS functions
+  // Haven't been able to get the thread method to work reliably (or get progress feedback)
+  // So thread version is disabled ATM
+  /*
+  if ( vik_datasource_osm_my_traces_interface.is_thread ) {
+         vik_datasource_osm_my_traces_interface.progress_func = datasource_gps_progress;
+         vik_datasource_osm_my_traces_interface.add_progress_widgets_func = datasource_gps_add_progress_widgets;
+  }
+  */
+  return data;
+}
+
+static void datasource_osm_my_traces_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
+{
+       datasource_osm_my_traces_t *data = (datasource_osm_my_traces_t *)user_data;
+
+       GtkWidget *user_label;
+       GtkWidget *password_label;
+       user_label = gtk_label_new(_("Username:"));
+       data->user_entry = gtk_entry_new();
+
+       gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), user_label, FALSE, FALSE, 0 );
+       gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), data->user_entry, FALSE, FALSE, 0 );
+       gtk_widget_set_tooltip_markup ( GTK_WIDGET(data->user_entry), _("The email or username used to login to OSM") );
+
+       password_label = gtk_label_new ( _("Password:") );
+       data->password_entry = gtk_entry_new ();
+
+       gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), password_label, FALSE, FALSE, 0 );
+       gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), data->password_entry, FALSE, FALSE, 0 );
+       gtk_widget_set_tooltip_markup ( GTK_WIDGET(data->password_entry), _("The password used to login to OSM") );
+
+       osm_login_widgets (data->user_entry, data->password_entry);
+       gtk_widget_show_all ( dialog );
+}
+
+static void datasource_osm_my_traces_get_cmd_string ( gpointer user_data, gchar **args, gchar **extra, DownloadMapOptions *options )
+{
+       datasource_osm_my_traces_t *data = (datasource_osm_my_traces_t*) user_data;
+
+    /* overwrite authentication info */
+       osm_set_login ( gtk_entry_get_text ( GTK_ENTRY(data->user_entry) ),
+                       gtk_entry_get_text ( GTK_ENTRY(data->password_entry) ) );
+
+       // If going to use the values passed back into the process function parameters then these need to be set.
+       // But ATM we aren't
+       *args = NULL;
+       *extra = NULL;
+       options = NULL;
+}
+
+typedef enum {
+       tt_unknown = 0,
+       tt_osm,
+       tt_gpx_file,
+       tt_gpx_file_desc,
+       tt_gpx_file_tag,
+} xtag_type;
+
+typedef struct {
+       xtag_type tag_type;              /* enum from above for this tag */
+       const char *tag_name;           /* xpath-ish tag name */
+} xtag_mapping;
+
+typedef struct {
+       guint id;
+       gchar *name;
+       gchar *vis;
+       gchar *desc;
+       struct LatLon ll;
+       // ATM Only used for display - may want to convert to a time_t for other usage
+       gchar *timestamp;
+       // user made up tags - not being used yet - would be nice to sort/select on these but display will get complicated
+       // GList *tag_list;
+} gpx_meta_data_t;
+
+static gpx_meta_data_t *new_gpx_meta_data_t()
+{
+       gpx_meta_data_t *ret;
+
+       ret = (gpx_meta_data_t *)g_malloc(sizeof(gpx_meta_data_t));
+       ret->id = 0;
+       ret->name = NULL;
+       ret->vis  = NULL;
+       ret->desc = NULL;
+       ret->ll.lat = 0.0;
+       ret->ll.lon = 0.0;
+       ret->timestamp = NULL;
+
+       return ret;
+}
+
+static void free_gpx_meta_data ( gpx_meta_data_t *data, gpointer userdata )
+{
+       g_free(data->name);
+       g_free(data->vis);
+       g_free(data->desc);
+       g_free(data->timestamp);
+}
+
+static void free_gpx_meta_data_list (GList *list)
+{
+       g_list_foreach (list, (GFunc)free_gpx_meta_data, NULL);
+       g_list_free (list);
+}
+
+static gpx_meta_data_t *copy_gpx_meta_data_t (gpx_meta_data_t *src)
+{
+       gpx_meta_data_t *dest = new_gpx_meta_data_t();
+
+       dest->id = src->id;
+       dest->name = g_strdup(src->name);
+       dest->vis  = g_strdup(src->vis);
+       dest->desc = g_strdup(src->desc);
+       dest->ll.lat = src->ll.lat;
+       dest->ll.lon = src->ll.lon;
+       dest->timestamp = g_strdup(src->timestamp);
+
+       return dest;
+}
+
+typedef struct {
+       //GString *xpath;
+       GString *c_cdata;
+       xtag_type current_tag;
+       gpx_meta_data_t *current_gpx_meta_data;
+       GList *list_of_gpx_meta_data;
+} xml_data;
+
+// Same as the gpx.c function
+static const char *get_attr ( const char **attr, const char *key )
+{
+  while ( *attr ) {
+    if ( strcmp(*attr,key) == 0 )
+      return *(attr + 1);
+    attr += 2;
+  }
+  return NULL;
+}
+
+// ATM don't care about actual path as tags are all unique
+static xtag_mapping xtag_path_map[] = {
+       { tt_osm,           "osm" },
+       { tt_gpx_file,      "gpx_file" },
+       { tt_gpx_file_desc, "description" },
+       { tt_gpx_file_tag,  "tag" },
+};
+
+static xtag_type get_tag ( const char *t )
+{
+       xtag_mapping *tm;
+       for (tm = xtag_path_map; tm->tag_type != 0; tm++)
+               if (0 == strcmp(tm->tag_name, t))
+                       return tm->tag_type;
+       return tt_unknown;
+}
+
+static void gpx_meta_data_start ( xml_data *xd, const char *el, const char **attr )
+{
+       const gchar *tmp;
+       gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
+       buf[0] = '\0';
+
+       // Don't need to build a path - we can use the tag directly
+       //g_string_append_c ( xd->xpath, '/' );
+       //g_string_append ( xd->xpath, el );
+       //xd->current_tag = get_tag ( xd->xpath->str );
+       xd->current_tag = get_tag ( el );
+       switch ( xd->current_tag ) {
+       case tt_gpx_file:
+               if ( xd->current_gpx_meta_data )
+                       free_gpx_meta_data ( xd->current_gpx_meta_data, NULL );
+               xd->current_gpx_meta_data = new_gpx_meta_data_t();
+
+               if ( ( tmp = get_attr ( attr, "id" ) ) )
+                       xd->current_gpx_meta_data->id = atoi ( tmp );
+
+               if ( ( tmp = get_attr ( attr, "name" ) ) )
+                       xd->current_gpx_meta_data->name = g_strdup ( tmp );
+
+               if ( ( tmp = get_attr ( attr, "lat" ) ) ) {
+                       g_snprintf (buf, sizeof (buf), tmp);
+                       xd->current_gpx_meta_data->ll.lat = g_ascii_strtod ( buf, NULL );
+               }
+
+               if ( ( tmp = get_attr ( attr, "lon" ) ) ) {
+                       g_snprintf (buf, sizeof (buf), tmp);
+                       xd->current_gpx_meta_data->ll.lon = g_ascii_strtod ( buf, NULL );
+               }
+
+               if ( ( tmp = get_attr ( attr, "visibility" ) ) )
+                       xd->current_gpx_meta_data->vis = g_strdup ( tmp );
+
+               if ( ( tmp = get_attr ( attr, "timestamp" ) ) )
+                       xd->current_gpx_meta_data->timestamp = g_strdup ( tmp );
+
+               g_string_erase ( xd->c_cdata, 0, -1 ); // clear the cdata buffer
+               break;
+       case tt_gpx_file_desc:
+       case tt_gpx_file_tag:
+               g_string_erase ( xd->c_cdata, 0, -1 ); // clear the cdata buffer
+               break;
+       default:
+               g_string_erase ( xd->c_cdata, 0, -1 ); // clear the cdata buffer
+               break;
+       }
+}
+
+static void gpx_meta_data_end ( xml_data *xd, const char *el )
+{
+       //g_string_truncate ( xd->xpath, xd->xpath->len - strlen(el) - 1 );
+       //switch ( xd->current_tag ) {
+       switch ( get_tag ( el ) ) {
+       case tt_gpx_file: {
+               // End of the individual file metadata, thus save what we have read in to the list
+               // Copy it so we can reference it
+               gpx_meta_data_t *current = copy_gpx_meta_data_t ( xd->current_gpx_meta_data );
+               // Stick in the list
+               xd->list_of_gpx_meta_data = g_list_prepend(xd->list_of_gpx_meta_data, current);
+               g_string_erase ( xd->c_cdata, 0, -1 );
+               break;
+       }
+       case tt_gpx_file_desc:
+               // Store the description:
+               if ( xd->current_gpx_meta_data ) {
+                       // NB Limit description size as it's displayed on a single line
+                       // Hopefully this will prevent the dialog getting too wide...
+                       xd->current_gpx_meta_data->desc = g_strndup ( xd->c_cdata->str, 63 );
+               }
+               g_string_erase ( xd->c_cdata, 0, -1 );
+               break;
+       case tt_gpx_file_tag:
+               // One day do something with this...
+               g_string_erase ( xd->c_cdata, 0, -1 );
+               break;
+       default:
+               break;
+       }
+}
+
+static void gpx_meta_data_cdata ( xml_data *xd, const XML_Char *s, int len )
+{
+       switch ( xd->current_tag ) {
+    case tt_gpx_file_desc:
+    case tt_gpx_file_tag:
+               g_string_append_len ( xd->c_cdata, s, len );
+               break;
+       default: break;  // ignore cdata from other things
+       }
+}
+
+static gboolean read_gpx_files_metadata_xml ( gchar *tmpname, xml_data *xd )
+{
+       FILE *ff = g_fopen (tmpname, "r");
+       if ( !ff )
+               return FALSE;
+
+       XML_Parser parser = XML_ParserCreate(NULL);
+       enum XML_Status status = XML_STATUS_ERROR;
+
+       XML_SetElementHandler(parser, (XML_StartElementHandler) gpx_meta_data_start, (XML_EndElementHandler) gpx_meta_data_end);
+       XML_SetUserData(parser, xd);
+       XML_SetCharacterDataHandler(parser, (XML_CharacterDataHandler) gpx_meta_data_cdata);
+
+       gchar buf[4096];
+
+       int done=0, len;
+       while (!done) {
+               len = fread(buf, 1, sizeof(buf)-7, ff);
+               done = feof(ff) || !len;
+               status = XML_Parse(parser, buf, len, done);
+       }
+
+       XML_ParserFree (parser);
+
+       fclose  ( ff );
+
+       return status != XML_STATUS_ERROR;
+}
+
+static GList *select_from_list (GtkWindow *parent, GList *list, const gchar *title, const gchar *msg )
+{
+       GtkTreeIter iter;
+       GtkCellRenderer *renderer;
+       GtkWidget *view;
+       gchar *latlon_string;
+       int column_runner;
+
+       GtkWidget *dialog = gtk_dialog_new_with_buttons (title,
+                                                                                                        parent,
+                                                                                                        GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                                                                                        GTK_STOCK_CANCEL,
+                                                                                                        GTK_RESPONSE_REJECT,
+                                                                                                        GTK_STOCK_OK,
+                                                                                                        GTK_RESPONSE_ACCEPT,
+                                                                                                        NULL);
+       /* When something is selected then OK */
+       gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
+       GtkWidget *response_w = NULL;
+#if GTK_CHECK_VERSION (2, 20, 0)
+       /* Default to not apply - as initially nothing is selected! */
+       response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
+#endif
+       GtkWidget *label = gtk_label_new ( msg );
+       GtkTreeStore *store = gtk_tree_store_new ( 5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
+       GList *list_runner = list;
+       while (list_runner) {
+               gpx_meta_data_t *gpx_meta_data = (gpx_meta_data_t *)list_runner->data;
+               // To keep display compact three digits of precision for lat/lon should be plenty
+               latlon_string = g_strdup_printf("(%.3f,%.3f)", gpx_meta_data->ll.lat, gpx_meta_data->ll.lon);
+               gtk_tree_store_append(store, &iter, NULL);
+               gtk_tree_store_set ( store, &iter,
+                                    0, gpx_meta_data->name,
+                                    1, gpx_meta_data->desc,
+                                    2, gpx_meta_data->timestamp,
+                                    3, latlon_string,
+                                    4, gpx_meta_data->vis,
+                                    -1 );
+               list_runner = g_list_next ( list_runner );
+               g_free ( latlon_string );
+       }
+
+       view = gtk_tree_view_new();
+       renderer = gtk_cell_renderer_text_new();
+       column_runner = 0;
+       GtkTreeViewColumn *column;
+
+       column = gtk_tree_view_column_new_with_attributes ( _("Name"), renderer, "text", column_runner, NULL);
+       gtk_tree_view_column_set_sort_column_id (column, column_runner);
+       gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+       column_runner++;
+       column = gtk_tree_view_column_new_with_attributes ( _("Description"), renderer, "text", column_runner, NULL);
+       gtk_tree_view_column_set_sort_column_id (column, column_runner);
+       gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+       column_runner++;
+       column = gtk_tree_view_column_new_with_attributes ( _("Time"), renderer, "text", column_runner, NULL);
+       gtk_tree_view_column_set_sort_column_id (column, column_runner);
+       gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+       column_runner++;
+       column = gtk_tree_view_column_new_with_attributes ( _("Lat/Lon"), renderer, "text", column_runner, NULL);
+       gtk_tree_view_column_set_sort_column_id (column, column_runner);
+       gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+       column_runner++;
+       column = gtk_tree_view_column_new_with_attributes ( _("Privacy"), renderer, "text", column_runner, NULL); // AKA Visibility
+       gtk_tree_view_column_set_sort_column_id (column, column_runner);
+       gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+       gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
+       gtk_tree_selection_set_mode( gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), GTK_SELECTION_MULTIPLE );
+       g_object_unref(store);
+
+       GtkWidget *scrolledwindow = gtk_scrolled_window_new ( NULL, NULL );
+       gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );
+       gtk_container_add ( GTK_CONTAINER(scrolledwindow), view );
+
+       gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), scrolledwindow, TRUE, TRUE, 0);
+
+       // Ensure a reasonable number of items are shown, but let the width be automatically sized
+       gtk_widget_set_size_request ( dialog, -1, 400) ;
+       gtk_widget_show_all ( dialog );
+
+       if ( response_w )
+               gtk_widget_grab_focus ( response_w );
+
+       while ( gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT ) {
+
+               // Possibily not the fastest method but we don't have thousands of entries to process...
+               GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+               GList *selected = NULL;
+
+               //  because we don't store the full data in the gtk model, we have to scan & look it up
+               if ( gtk_tree_model_get_iter_first( GTK_TREE_MODEL(store), &iter) ) {
+                       do {
+                               if ( gtk_tree_selection_iter_is_selected ( selection, &iter ) ) {
+                                       // For every selected item,
+                                       // compare the name from the displayed view to every gpx entry to find the gpx this selection represents
+                                       gchar* name;
+                                       gtk_tree_model_get (GTK_TREE_MODEL(store), &iter, 0, &name, -1 );
+                                       // I believe the name of these items to be always unique
+                                       list_runner = list;
+                                       while (list_runner) {
+                                               if ( !strcmp ( ((gpx_meta_data_t*)list_runner->data)->name, name ) ) {
+                                                       gpx_meta_data_t *copied = copy_gpx_meta_data_t (list_runner->data);
+                                                       selected = g_list_prepend (selected, copied);
+                                                       break;
+                                               }
+                                               list_runner = g_list_next ( list_runner );
+                                       }
+                               }
+                       }
+                       while ( gtk_tree_model_iter_next ( GTK_TREE_MODEL(store), &iter ) );
+               }
+
+               if ( selected ) {
+                       gtk_widget_destroy ( dialog );
+                       return selected;
+               }
+               a_dialog_error_msg(parent, _("Nothing was selected"));
+       }
+       gtk_widget_destroy ( dialog );
+       return NULL;
+}
+
+static void none_found ( GtkWindow *gw )
+{
+       GtkWidget *dialog = NULL;
+
+       dialog = gtk_dialog_new_with_buttons ( "", gw, 0, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL );
+       gtk_window_set_title(GTK_WINDOW(dialog), _("GPS Traces"));
+
+       GtkWidget *search_label = gtk_label_new(_("None found!"));
+       gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), search_label, FALSE, FALSE, 5 );
+       gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
+       gtk_widget_show_all(dialog);
+
+       gtk_dialog_run ( GTK_DIALOG(dialog) );
+       gtk_widget_destroy(dialog);
+}
+
+static gboolean datasource_osm_my_traces_process ( VikTrwLayer *vtl, const gchar *cmd, const gchar *extra, BabelStatusFunc status_cb, acq_dialog_widgets_t *adw, DownloadMapOptions *options_unused )
+{
+       //datasource_osm_my_traces_t *data = (datasource_osm_my_traces_t *)adw->user_data;
+
+       gboolean result;
+
+       gchar *user_pass = osm_get_login();
+
+       DownloadMapOptions options = { FALSE, FALSE, NULL, 2, NULL, user_pass }; // Allow a couple of redirects
+
+       xml_data *xd = g_malloc ( sizeof (xml_data) );
+       //xd->xpath = g_string_new ( "" );
+       xd->c_cdata = g_string_new ( "" );
+       xd->current_tag = tt_unknown;
+       xd->current_gpx_meta_data = new_gpx_meta_data_t();
+       xd->list_of_gpx_meta_data = NULL;
+
+       gchar *tmpname = a_download_uri_to_tmp_file ( DS_OSM_TRACES_GPX_FILES, &options );
+       result = read_gpx_files_metadata_xml ( tmpname, xd );
+       // Test already downloaded metadata file: eg:
+       //result = read_gpx_files_metadata_xml ( "/tmp/vikingdl.9XX2NW", xd );
+
+       if ( tmpname ) {
+               g_remove ( tmpname );
+               g_free ( tmpname );
+       }
+
+       if ( ! result )
+               return FALSE;
+
+       if ( g_list_length ( xd->list_of_gpx_meta_data ) == 0 ) {
+               if (!vik_datasource_osm_my_traces_interface.is_thread)
+                       none_found ( GTK_WINDOW(adw->vw) );
+               return FALSE;
+       }
+
+       xd->list_of_gpx_meta_data = g_list_reverse ( xd->list_of_gpx_meta_data );
+
+    if (vik_datasource_osm_my_traces_interface.is_thread) gdk_threads_enter();
+       GList *selected = select_from_list ( GTK_WINDOW(adw->vw), xd->list_of_gpx_meta_data, "Select GPS Traces", "Select the GPS traces you want to add." );
+    if (vik_datasource_osm_my_traces_interface.is_thread) gdk_threads_leave();
+
+       // If passed in on an existing layer - we will create everything into that.
+       //  thus with many differing gpx's - this will combine all waypoints into this single layer!
+       // Hence the preference is to create multiple layers
+       //  and so this creation of the layers must be managed here
+
+       gboolean create_new_layer = ( !vtl );
+
+       // Only update the screen on the last layer acquired
+       VikTrwLayer *vtl_last = vtl;
+       gboolean got_something = FALSE;
+
+       GList *selected_iterator = selected;
+       while ( selected_iterator ) {
+
+               VikTrwLayer *vtlX = vtl;
+
+               if ( create_new_layer ) {
+                       // Have data but no layer - so create one
+                       vtlX = VIK_TRW_LAYER ( vik_layer_create ( VIK_LAYER_TRW, vik_window_viewport(adw->vw), NULL, FALSE ) );
+                       if ( ((gpx_meta_data_t*)selected_iterator->data)->name )
+                               vik_layer_rename ( VIK_LAYER ( vtlX ), ((gpx_meta_data_t*)selected_iterator->data)->name );
+                       else
+                               vik_layer_rename ( VIK_LAYER ( vtlX ), _("My OSM Traces") );
+                       vik_aggregate_layer_add_layer ( vik_layers_panel_get_top_layer (adw->vlp), VIK_LAYER(vtlX) );
+               }
+
+               result = FALSE;
+               gint gpx_id = ((gpx_meta_data_t*)selected_iterator->data)->id;
+               if ( gpx_id ) {
+                       gchar *url = g_strdup_printf ( DS_OSM_TRACES_GPX_URL_FMT, gpx_id );
+
+                       result = a_babel_convert_from_url ( vtlX, url, "gpx", status_cb, adw, &options );
+                       // TODO investigate using a progress bar:
+                       // http://developer.gnome.org/gtk/2.24/GtkProgressBar.html
+
+                       got_something = got_something || result;
+                       // TODO feedback to UI to inform which traces failed
+                       if ( !result )
+                               g_warning ( _("Unable to get trace: %s"), url );
+               }
+
+               if ( result ) {
+                       // Move to area of the track
+                       vik_trw_layer_auto_set_view ( vtlX, vik_window_viewport(adw->vw) );
+                       vik_layer_post_read ( VIK_LAYER(vtlX), vik_window_viewport(adw->vw), TRUE );
+                       vtl_last = vtlX;
+               }
+               else if ( create_new_layer ) {
+                       // Layer not needed as no data has been acquired
+                       g_object_unref ( vtlX );
+               }
+
+               selected_iterator = g_list_next ( selected_iterator );
+       }
+
+       // Free memory
+       if ( xd->current_gpx_meta_data )
+               free_gpx_meta_data ( xd->current_gpx_meta_data, NULL );
+       g_free ( xd->current_gpx_meta_data );
+       free_gpx_meta_data_list ( xd->list_of_gpx_meta_data );
+       free_gpx_meta_data_list ( selected );
+       g_free ( xd );
+       g_free ( user_pass );
+
+       // Would prefer to keep the update in acquire.c,
+       //  however since we may create the layer - need to do the update here
+       if ( got_something )
+               vik_layer_emit_update ( VIK_LAYER(vtl_last) );
+
+       // ATM The user is only informed if all getting *all* of the traces failed
+       if ( selected )
+               result = got_something;
+       else
+               // Process was cancelled but need to return that it proceeded as expected
+               result = TRUE;
+
+       return result;
+}
+
+static void datasource_osm_my_traces_cleanup ( gpointer data )
+{
+       g_free ( data );
+}
index 7e5b2b3b2a125edb841afb9f23c2b5e63c5bcfe0..f165b7261eb7522dccd3cb39882bf8d5ee760a6c 100644 (file)
@@ -32,6 +32,7 @@ extern VikDataSourceInterface vik_datasource_google_interface;
 #endif
 #ifdef VIK_CONFIG_OPENSTREETMAP
 extern VikDataSourceInterface vik_datasource_osm_interface;
+extern VikDataSourceInterface vik_datasource_osm_my_traces_interface;
 #endif
 #ifdef VIK_CONFIG_GEOCACHES
 extern VikDataSourceInterface vik_datasource_gc_interface;
index 944974b07194f2952f7954720630419208b53a8d..6f29321781b11ac7777c5d501b39fef188fd571d 100644 (file)
@@ -20,6 +20,7 @@ static const char *menu_xml =
 #endif
 #ifdef VIK_CONFIG_OPENSTREETMAP
        "        <menuitem action='AcquireOSM'/>"
+       "        <menuitem action='AcquireMyOSM'/>"
 #endif
 #ifdef VIK_CONFIG_GEOCACHES
        "        <menuitem action='AcquireGC'/>"
index 84a6c28a5449bb23337119c13d0c599cd0a0ec8e..850884c3774320ee974700a3b6efd53501be67a6 100644 (file)
@@ -121,7 +121,7 @@ static const gchar *get_default_user()
   return default_user;
 }
 
-static void set_login(const gchar *user_, const gchar *password_)
+void osm_set_login(const gchar *user_, const gchar *password_)
 {
   /* Allocate mutex */
   if (login_mutex == NULL)
@@ -136,7 +136,7 @@ static void set_login(const gchar *user_, const gchar *password_)
   g_mutex_unlock(login_mutex);
 }
 
-static gchar *get_login()
+gchar *osm_get_login()
 {
   gchar *user_pass = NULL;
   g_mutex_lock(login_mutex);
@@ -182,7 +182,7 @@ static gint osm_traces_upload_file(const char *user,
 
   char *base_url = "http://www.openstreetmap.org/api/0.6/gpx/create";
 
-  gchar *user_pass = get_login();
+  gchar *user_pass = osm_get_login();
 
   gint result = 0; // Default to it worked!
 
@@ -349,6 +349,33 @@ static void osm_traces_upload_thread ( OsmTracesInfo *oti, gpointer threaddata )
   }
 }
 
+/**
+ *
+ */
+void osm_login_widgets (GtkWidget *user_entry, GtkWidget *password_entry)
+{
+  if (!user_entry || !password_entry)
+    return;
+
+  const gchar *default_user = get_default_user();
+  const gchar *pref_user = a_preferences_get(VIKING_OSM_TRACES_PARAMS_NAMESPACE "username")->s;
+  const gchar *pref_password = a_preferences_get(VIKING_OSM_TRACES_PARAMS_NAMESPACE "password")->s;
+
+  if (user != NULL && user[0] != '\0')
+    gtk_entry_set_text(GTK_ENTRY(user_entry), user);
+  else if (pref_user != NULL && pref_user[0] != '\0')
+    gtk_entry_set_text(GTK_ENTRY(user_entry), pref_user);
+  else if (default_user != NULL)
+    gtk_entry_set_text(GTK_ENTRY(user_entry), default_user);
+
+  if (password != NULL && password[0] != '\0')
+    gtk_entry_set_text(GTK_ENTRY(password_entry), password);
+  else if (pref_password != NULL)
+    gtk_entry_set_text(GTK_ENTRY(password_entry), pref_password);
+  /* This is a password -> invisible */
+  gtk_entry_set_visibility(GTK_ENTRY(password_entry), FALSE);
+}
+
 /**
  * Uploading a VikTrwLayer
  *
@@ -366,9 +393,6 @@ static void osm_traces_upload_viktrwlayer ( VikTrwLayer *vtl, VikTrack *trk )
                                                  GTK_RESPONSE_ACCEPT,
                                                  NULL);
 
-  const gchar *default_user = get_default_user();
-  const gchar *pref_user = a_preferences_get(VIKING_OSM_TRACES_PARAMS_NAMESPACE "username")->s;
-  const gchar *pref_password = a_preferences_get(VIKING_OSM_TRACES_PARAMS_NAMESPACE "password")->s;
   const gchar *name = NULL;
   GtkWidget *user_label, *user_entry;
   GtkWidget *password_label, *password_entry;
@@ -380,12 +404,6 @@ static void osm_traces_upload_viktrwlayer ( VikTrwLayer *vtl, VikTrack *trk )
 
   user_label = gtk_label_new(_("Email:"));
   user_entry = gtk_entry_new();
-  if (user != NULL && user[0] != '\0')
-    gtk_entry_set_text(GTK_ENTRY(user_entry), user);
-  else if (pref_user != NULL && pref_user[0] != '\0')
-    gtk_entry_set_text(GTK_ENTRY(user_entry), pref_user);
-  else if (default_user != NULL)
-    gtk_entry_set_text(GTK_ENTRY(user_entry), default_user);
   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia)->vbox), user_label, FALSE, FALSE, 0);
   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia)->vbox), user_entry, FALSE, FALSE, 0);
   gtk_widget_set_tooltip_markup(GTK_WIDGET(user_entry),
@@ -394,18 +412,14 @@ static void osm_traces_upload_viktrwlayer ( VikTrwLayer *vtl, VikTrack *trk )
 
   password_label = gtk_label_new(_("Password:"));
   password_entry = gtk_entry_new();
-  if (password != NULL && password[0] != '\0')
-    gtk_entry_set_text(GTK_ENTRY(password_entry), password);
-  else if (pref_password != NULL)
-    gtk_entry_set_text(GTK_ENTRY(password_entry), pref_password);
-  /* This is a password -> invisible */
-  gtk_entry_set_visibility(GTK_ENTRY(password_entry), FALSE);
   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia)->vbox), password_label, FALSE, FALSE, 0);
   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia)->vbox), password_entry, FALSE, FALSE, 0);
   gtk_widget_set_tooltip_markup(GTK_WIDGET(password_entry),
                         _("The password used to login\n"
                         "<small>Enter the password you use to login into www.openstreetmap.org.</small>"));
 
+  osm_login_widgets ( user_entry, password_entry );
+
   name_label = gtk_label_new(_("File's name:"));
   name_entry = gtk_entry_new();
   if (trk != NULL)
@@ -452,8 +466,8 @@ static void osm_traces_upload_viktrwlayer ( VikTrwLayer *vtl, VikTrack *trk )
     gchar *title = NULL;
 
     /* overwrite authentication info */
-    set_login(gtk_entry_get_text(GTK_ENTRY(user_entry)),
-              gtk_entry_get_text(GTK_ENTRY(password_entry)));
+    osm_set_login(gtk_entry_get_text(GTK_ENTRY(user_entry)),
+                  gtk_entry_get_text(GTK_ENTRY(password_entry)));
 
     /* Storing data for the future thread */
     OsmTracesInfo *info = g_malloc(sizeof(OsmTracesInfo));
index 4f19c46d8f6f33e7d3b8df9a1db917bd1f4ab4b6..2aa142795067339e3175a5587c04b34ab270367b 100644 (file)
@@ -23,6 +23,7 @@
 #define __VIKING_OSM_TRACES_H
 
 #include <glib.h>
+#include <gtk/gtk.h>
 
 G_BEGIN_DECLS
 
@@ -30,6 +31,10 @@ void osm_traces_init();
 void osm_traces_upload_cb(gpointer layer_and_vlp[2], guint file_type);
 void osm_traces_upload_track_cb(gpointer pass_along[8]);
 
+void osm_set_login (const gchar *user_, const gchar *password_);
+gchar *osm_get_login();
+void osm_login_widgets (GtkWidget *user_entry, GtkWidget *password_entry);
+
 G_BEGIN_DECLS
 
 #endif
index b662fbc8656298ca8924a49b69f48887706f15a6..9080b4c1f11d201a59bd981ee4723f9686f8acf0 100644 (file)
@@ -294,6 +294,7 @@ static void trw_layer_acquire_google_cb ( gpointer lav[2] );
 #endif
 #ifdef VIK_CONFIG_OPENSTREETMAP
 static void trw_layer_acquire_osm_cb ( gpointer lav[2] );
+static void trw_layer_acquire_osm_my_traces_cb ( gpointer lav[2] );
 #endif
 #ifdef VIK_CONFIG_GEOCACHES
 static void trw_layer_acquire_geocache_cb ( gpointer lav[2] );
@@ -2975,6 +2976,19 @@ static void trw_layer_acquire_osm_cb ( gpointer lav[2] )
 
   a_acquire ( vw, vlp, vvp, &vik_datasource_osm_interface );
 }
+
+/**
+ * Acquire into this TRW Layer from OSM for 'My' Traces
+ */
+static void trw_layer_acquire_osm_my_traces_cb ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+  VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl));
+  VikViewport *vvp =  vik_window_viewport(vw);
+
+  a_acquire ( vw, vlp, vvp, &vik_datasource_osm_my_traces_interface );
+}
 #endif
 
 #ifdef VIK_CONFIG_GEOCACHES
@@ -3408,6 +3422,11 @@ static void trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer
   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_osm_cb), pass_along );
   gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
   gtk_widget_show ( item );
+
+  item = gtk_menu_item_new_with_mnemonic ( _("From _My OSM Traces...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_osm_my_traces_cb), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
+  gtk_widget_show ( item );
 #endif
 
 #ifdef VIK_CONFIG_GEONAMES
index e34c4e60e7e0620f7927e736265252df29176ae7..57e986079390e504838e91f8740e43209b7d0d58 100644 (file)
@@ -2446,6 +2446,11 @@ static void acquire_from_osm ( GtkAction *a, VikWindow *vw )
 {
   a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_osm_interface );
 }
+
+static void acquire_from_my_osm ( GtkAction *a, VikWindow *vw )
+{
+  a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_osm_my_traces_interface );
+}
 #endif
 
 #ifdef VIK_CONFIG_GEOCACHES
@@ -3126,6 +3131,7 @@ static GtkActionEntry entries[] = {
 #endif
 #ifdef VIK_CONFIG_OPENSTREETMAP
   { "AcquireOSM",   NULL,                 N_("_OSM Traces..."),          NULL,         N_("Get traces from OpenStreetMap"),            (GCallback)acquire_from_osm       },
+  { "AcquireMyOSM", NULL,                 N_("_My OSM Traces..."),       NULL,         N_("Get Your Own Traces from OpenStreetMap"),   (GCallback)acquire_from_my_osm    },
 #endif
 #ifdef VIK_CONFIG_GEOCACHES
   { "AcquireGC",   NULL,                 N_("Geo_caches..."),            NULL,         N_("Get Geocaches from geocaching.com"),            (GCallback)acquire_from_gc       },