]> git.street.me.uk Git - andy/viking.git/commitdiff
SF Features#122: Export Track, Route and Waypoint Lists as text.
authorRob Norris <rw_norris@hotmail.com>
Tue, 24 Feb 2015 23:02:10 +0000 (23:02 +0000)
committerRob Norris <rw_norris@hotmail.com>
Tue, 24 Feb 2015 23:07:51 +0000 (23:07 +0000)
Thus enable multi-select and a new right click option 'Copy Data',
 which copies each field as text separated by a tab.

This can then be pasted into another program - i.e. a spreadsheet application.
[Tested with LibreOffice Calc]

help/C/viking.xml
src/viktrwlayer_tracklist.c
src/viktrwlayer_waypointlist.c

index 9842127332af639d563c838b9168ecb32e506e24..ebfb7360214d1b2b930f27d0c621d363fee25a0a 100644 (file)
@@ -1744,6 +1744,7 @@ Generally it is not useful to sort the Top most layer. Sort is mainly intended f
 <para>
 Selecting this opens a dialog listing all the tracks in a table along side statistics such as track length and maximum speed.
 Each column header is clickable and will reorder the list according to that particular column.
+You can also rearrange the columns via dragging the column header to the new location.
 </para>
 <para>
 This table may be invoked from a variety of different layer levels and will then list only the relevant tracks (and/or routes).
@@ -1776,14 +1777,21 @@ Each entry in the track list can be selected and on mouse right click offers the
 <itemizedlist>
 <listitem><para>View. Move the viewport to the area of the item and highlight it.</para></listitem>
 <listitem><para>Statistics. Opens the Properties dialog on the <xref linkend="track_statistics"/> tab. Note this will close the track list dialog.</para></listitem>
+<listitem><para>Copy Data. Copy the data fields as text.</para></listitem>
 </itemizedlist>
 </para>
+<para>
+If multiple entries are selected the only right click option is <emphasis>Copy Data</emphasis>.
+This copies the individual data fields as plain text separated by tab characters, ideal for pasting into other applications in particular spreadsheet programs.
+Note that the order of the fields copied is the default column ordering (irrespective to how they may have been rearranged).
+</para>
 </section>
 
 <section id="waypoint_list" xreflabel="Waypoint List"><title>Waypoint List</title>
 <para>
 Selecting this opens a dialog listing all the waypoints to give a overview of the waypoint information.
 Each column header is clickable and will reorder the list according to that particular column.
+You can also rearrange the columns via dragging the column header to the new location.
 </para>
 <para>
 This table may be invoked from a variety of different layer levels and will then list only the relevant waypoints.
@@ -1815,8 +1823,14 @@ Each entry in the list can be selected and on mouse right click offers these opt
 <listitem><para>View. Move the viewport to the area of the item and highlight it.</para></listitem>
 <listitem><para>Properties. This will open the properties dialog. Note this will close the waypoint list dialog.</para></listitem>
 <listitem><para>Show Picture. If enabled, this will open the associated image in an external Image Viewer program.</para></listitem>
+<listitem><para>Copy Data. Copy the data fields as text.</para></listitem>
 </itemizedlist>
 </para>
+<para>
+If multiple entries are selected the only right click option is <emphasis>Copy Data</emphasis>.
+This copies the individual data fields as plain text separated by tab characters, ideal for pasting into other applications in particular spreadsheet programs.
+Note that the order of the fields copied is the default column ordering (irrespective to how they may have been rearranged).
+</para>
 </section>
 
 <section id="vis_options" xreflabel="Visibility Options"><title>Visibility Options</title>
index c2412c24c28c7d5da60e373021620705047ded35..b78618a12e5c592d6ad8725fac043b686da904ef 100644 (file)
@@ -207,6 +207,65 @@ static void trw_layer_track_view ( menu_array_values values )
        trw_layer_track_select (values);
 }
 
+typedef struct {
+  gboolean has_layer_names;
+  GString *str;
+} copy_data_t;
+
+static void copy_selection (GtkTreeModel *model,
+                            GtkTreePath *path,
+                            GtkTreeIter *iter,
+                            gpointer data)
+{
+       copy_data_t *cd = (copy_data_t*) data;
+
+       gchar* layername; gtk_tree_model_get ( model, iter, 0, &layername, -1 );
+       gchar* name; gtk_tree_model_get ( model, iter, 1, &name, -1 );
+       gchar* date; gtk_tree_model_get ( model, iter, 2, &date, -1 );
+       gdouble d1; gtk_tree_model_get ( model, iter, 4, &d1, -1 );
+       guint d2; gtk_tree_model_get ( model, iter, 5, &d2, -1 );
+       gdouble d3; gtk_tree_model_get ( model, iter, 6, &d3, -1 );
+       gdouble d4; gtk_tree_model_get ( model, iter, 7, &d4, -1 );
+       gint d5; gtk_tree_model_get ( model, iter, 8, &d5, -1 );
+       gchar sep = '\t'; // Could make this configurable - but simply always make it a tab character for now
+       // NB Even if the columns have been reordered - this copies it out only in the original default order
+       // if col 0 is displayed then also copy the layername
+       if ( cd->has_layer_names )
+               g_string_append_printf ( cd->str, "%s%c%s%c%s%c%.1f%c%d%c%.1f%c%.1f%c%d\n", layername, sep, name, sep, date, sep, d1, sep, d2, sep, d3, sep, d4, sep, d5 );
+       else
+               g_string_append_printf ( cd->str, "%s%c%s%c%.1f%c%d%c%.1f%c%.1f%c%d\n", name, sep, date, sep, d1, sep, d2, sep, d3, sep, d4, sep, d5 );
+       g_free ( layername );
+       g_free ( name );
+       g_free ( date );
+}
+
+static void trw_layer_copy_selected ( GtkWidget *tree_view )
+{
+       GtkTreeSelection *selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW(tree_view) );
+       // NB GTK3 has gtk_tree_view_get_n_columns() but we're GTK2 ATM
+       GList *gl = gtk_tree_view_get_columns ( GTK_TREE_VIEW(tree_view) );
+       guint count = g_list_length ( gl );
+       g_list_free ( gl );
+       copy_data_t cd;
+       cd.has_layer_names = (count > TRK_LIST_COLS-3);
+       // Or use gtk_tree_view_column_get_visible()?
+       cd.str = g_string_new ( NULL );
+       gtk_tree_selection_selected_foreach ( selection, copy_selection, &cd );
+
+       a_clipboard_copy ( VIK_CLIPBOARD_DATA_TEXT, 0, 0, 0, cd.str->str, NULL );
+
+       g_string_free ( cd.str, TRUE );
+}
+
+static void add_copy_menu_item ( GtkMenu *menu, GtkWidget *tree_view )
+{
+       GtkWidget *item = gtk_image_menu_item_new_with_mnemonic ( _("_Copy Data") );
+       gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_COPY, GTK_ICON_SIZE_MENU) );
+       g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_copy_selected), tree_view );
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       gtk_widget_show ( item );
+}
+
 static gboolean add_menu_items ( GtkMenu *menu, VikTrwLayer *vtl, VikTrack *trk, gpointer trk_uuid, VikViewport *vvp, GtkWidget *tree_view, gpointer data )
 {
        static menu_array_values values;
@@ -239,6 +298,21 @@ static gboolean add_menu_items ( GtkMenu *menu, VikTrwLayer *vtl, VikTrack *trk,
        gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
        gtk_widget_show ( item );
 
+       add_copy_menu_item ( menu, tree_view );
+
+       return TRUE;
+}
+
+static gboolean trw_layer_track_menu_popup_multi  ( GtkWidget *tree_view,
+                                                    GdkEventButton *event,
+                                                    gpointer data )
+{
+       GtkWidget *menu = gtk_menu_new();
+
+       add_copy_menu_item ( GTK_MENU(menu), tree_view );
+
+       gtk_menu_popup ( GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() );
+
        return TRUE;
 }
 
@@ -252,7 +326,7 @@ static gboolean trw_layer_track_menu_popup ( GtkWidget *tree_view,
        // This relies on an row being selected as part of the right click
        GtkTreeSelection *selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW(tree_view) );
        if ( gtk_tree_selection_count_selected_rows (selection) != 1 )
-               return FALSE;
+               return trw_layer_track_menu_popup_multi ( tree_view, event, data );
 
        GtkTreePath *path;
        GtkTreeModel *model = gtk_tree_view_get_model ( GTK_TREE_VIEW(tree_view) );
@@ -582,7 +656,7 @@ static void vik_trw_layer_track_list_internal ( GtkWidget *dialog,
                column = my_new_column_text ( _("Max Height\n(Metres)"), renderer, view, column_runner++ );
 
        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_BROWSE ); // GTK_SELECTION_MULTIPLE
+       gtk_tree_selection_set_mode ( gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), GTK_SELECTION_MULTIPLE );
        gtk_tree_view_set_rules_hint ( GTK_TREE_VIEW(view), TRUE );
 
        g_object_unref(store);
index dd8aa8db8a9c673f6104c9ab8572e01576bbdc27..62ef5032771088279cbf0bf0a78206e674d06138 100644 (file)
@@ -219,6 +219,64 @@ static void trw_layer_show_picture ( menu_array_values values )
 }
 
 
+typedef struct {
+  gboolean has_layer_names;
+  GString *str;
+} copy_data_t;
+
+static void copy_selection (GtkTreeModel *model,
+                            GtkTreePath *path,
+                            GtkTreeIter *iter,
+                            gpointer data)
+{
+       copy_data_t *cd = (copy_data_t*) data;
+
+       gchar* layername; gtk_tree_model_get ( model, iter, 0, &layername, -1 );
+       gchar* name; gtk_tree_model_get ( model, iter, 1, &name, -1 );
+       gchar* date; gtk_tree_model_get ( model, iter, 2, &date, -1 );
+       gchar* comment; gtk_tree_model_get ( model, iter, 4, &comment, -1 );
+       if ( comment == NULL )
+               comment = g_strdup ( "" );
+       gint hh; gtk_tree_model_get ( model, iter, 5, &hh, -1 );
+       gchar sep = '\t'; // Could make this configurable - but simply always make it a tab character for now
+       // NB Even if the columns have been reordered - this copies it out only in the original default order
+       // if col 0 is displayed then also copy the layername
+       if ( cd->has_layer_names )
+               g_string_append_printf ( cd->str, "%s%c%s%c%s%c%s%c%d\n", layername, sep, name, sep, date, sep, comment, sep, hh );
+       else
+               g_string_append_printf ( cd->str, "%s%c%s%c%s%c%d\n", name, sep, date, sep, comment, sep, hh );
+       g_free ( layername );
+       g_free ( name );
+       g_free ( date );
+       g_free ( comment );
+}
+
+static void trw_layer_copy_selected ( GtkWidget *tree_view )
+{
+       GtkTreeSelection *selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW(tree_view) );
+       // NB GTK3 has gtk_tree_view_get_n_columns() but we're GTK2 ATM
+       GList *gl = gtk_tree_view_get_columns ( GTK_TREE_VIEW(tree_view) );
+       guint count = g_list_length ( gl );
+       g_list_free ( gl );
+       copy_data_t cd;
+       cd.has_layer_names = (count > WPT_LIST_COLS-3);
+       cd.str = g_string_new ( NULL );
+       gtk_tree_selection_selected_foreach ( selection, copy_selection, &cd );
+
+       a_clipboard_copy ( VIK_CLIPBOARD_DATA_TEXT, 0, 0, 0, cd.str->str, NULL );
+
+       g_string_free ( cd.str, TRUE );
+}
+
+static void add_copy_menu_item ( GtkMenu *menu, GtkWidget *tree_view )
+{
+       GtkWidget *item = gtk_image_menu_item_new_with_mnemonic ( _("_Copy Data") );
+       gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_COPY, GTK_ICON_SIZE_MENU) );
+       g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_copy_selected), tree_view );
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       gtk_widget_show ( item );
+}
+
 static gboolean add_menu_items ( GtkMenu *menu, VikTrwLayer *vtl, VikWaypoint *wpt, gpointer wpt_uuid, VikViewport *vvp, GtkWidget *tree_view, gpointer data )
 {
        static menu_array_values values;
@@ -259,6 +317,21 @@ static gboolean add_menu_items ( GtkMenu *menu, VikTrwLayer *vtl, VikWaypoint *w
        gtk_widget_show ( item );
        gtk_widget_set_sensitive ( item, GPOINTER_TO_INT(wpt->image) );
 
+       add_copy_menu_item ( menu, tree_view );
+
+       return TRUE;
+}
+
+static gboolean trw_layer_waypoint_menu_popup_multi  ( GtkWidget *tree_view,
+                                                       GdkEventButton *event,
+                                                       gpointer data )
+{
+       GtkWidget *menu = gtk_menu_new();
+
+       add_copy_menu_item ( GTK_MENU(menu), tree_view );
+
+       gtk_menu_popup ( GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() );
+
        return TRUE;
 }
 
@@ -272,7 +345,7 @@ static gboolean trw_layer_waypoint_menu_popup ( GtkWidget *tree_view,
        // This relies on an row being selected as part of the right click
        GtkTreeSelection *selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW(tree_view) );
        if ( gtk_tree_selection_count_selected_rows (selection) != 1 )
-               return FALSE;
+               return trw_layer_waypoint_menu_popup_multi ( tree_view, event, data );
 
        GtkTreePath *path;
        GtkTreeModel *model = gtk_tree_view_get_model ( GTK_TREE_VIEW(tree_view) );
@@ -529,7 +602,7 @@ static void vik_trw_layer_waypoint_list_internal ( GtkWidget *dialog,
        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_BROWSE ); // GTK_SELECTION_MULTIPLE
+       gtk_tree_selection_set_mode ( gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), GTK_SELECTION_MULTIPLE );
        gtk_tree_view_set_rules_hint ( GTK_TREE_VIEW(view), TRUE );
 
        g_object_unref(store);