X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/4c85a045ad9f65d3c244ece75754358d0bf46838..9e90c3a511d4ea403d07522fb41d9f44328ecaa0:/src/vikfilelist.c diff --git a/src/vikfilelist.c b/src/vikfilelist.c index 1fc8828c..6bd3529e 100644 --- a/src/vikfilelist.c +++ b/src/vikfilelist.c @@ -2,6 +2,7 @@ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager * * Copyright (C) 2003-2005, Evan Battaglia + * Copyright (C) 2011, Rob Norris * * 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 @@ -19,7 +20,12 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include +#include #include "vikfilelist.h" @@ -28,40 +34,100 @@ struct _VikFileList { GtkWidget *treeview; GtkWidget *file_selector; GtkTreeModel *model; + GtkFileFilter *filter; }; static void file_list_add ( VikFileList *vfl ) { + GSList *files = NULL; + GSList *fiter = NULL; + if ( ! vfl->file_selector ) { GtkWidget *win; g_assert ( (win = gtk_widget_get_toplevel(GTK_WIDGET(vfl))) ); - vfl->file_selector = gtk_file_selection_new ("Choose file(s)"); - gtk_file_selection_set_select_multiple ( GTK_FILE_SELECTION(vfl->file_selector), TRUE ); + vfl->file_selector = gtk_file_chooser_dialog_new (_("Choose file(s)"), + GTK_WINDOW(win), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + gtk_file_chooser_set_select_multiple ( GTK_FILE_CHOOSER(vfl->file_selector), TRUE ); gtk_window_set_transient_for ( GTK_WINDOW(vfl->file_selector), GTK_WINDOW(win) ); gtk_window_set_destroy_with_parent ( GTK_WINDOW(vfl->file_selector), TRUE ); + + if ( vfl->filter ) + gtk_file_chooser_add_filter ( GTK_FILE_CHOOSER(vfl->file_selector), vfl->filter ); } - if ( gtk_dialog_run ( GTK_DIALOG(vfl->file_selector) ) == GTK_RESPONSE_OK ) { - gchar **files = gtk_file_selection_get_selections ( GTK_FILE_SELECTION(vfl->file_selector) ); - gchar **fiter = files; + if ( gtk_dialog_run ( GTK_DIALOG(vfl->file_selector) ) == GTK_RESPONSE_ACCEPT ) { + files = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER(vfl->file_selector) ); + fiter = files; GtkTreeIter iter; - while (*fiter) { + while ( fiter ) { + gchar *file_name = fiter->data; + gtk_list_store_append ( GTK_LIST_STORE(vfl->model), &iter ); - gtk_list_store_set ( GTK_LIST_STORE(vfl->model), &iter, 0, *fiter, -1 ); - fiter++; + gtk_list_store_set ( GTK_LIST_STORE(vfl->model), &iter, 0, file_name, -1 ); + + g_free (file_name); + + fiter = g_slist_next (fiter); } - g_strfreev(files); + g_slist_free (files); } gtk_widget_hide ( vfl->file_selector ); } + +static GtkTreeRowReference** file_list_get_selected_refs (GtkTreeModel *model, + GList *list) +{ + GtkTreeRowReference **arr; + GList *iter; + + arr = g_new (GtkTreeRowReference *, g_list_length (list) + 1); + + gint pos = 0; + for (iter = g_list_first (list); iter != NULL; iter = g_list_next (iter)) { + GtkTreePath *path = (GtkTreePath *)(iter->data); + arr[pos] = gtk_tree_row_reference_new (model, path); + pos++; + } + arr[pos] = NULL; + + return arr; +} + +static void file_list_store_delete_refs (GtkTreeModel *model, + GtkTreeRowReference * const *rrefs) +{ + GtkTreePath *path; + GtkTreeIter iter; + + gint rr; + for ( rr = 0; rrefs[rr] != NULL; rr++ ) { + path = gtk_tree_row_reference_get_path (rrefs[rr]); + gtk_tree_model_get_iter (model, &iter, path); + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + } +} + + static void file_list_del ( VikFileList *vfl ) { GtkTreeSelection *ts = gtk_tree_view_get_selection (GTK_TREE_VIEW(vfl->treeview)); - GtkTreeIter iter; - if ( gtk_tree_selection_get_selected(ts, NULL, &iter) ) - gtk_list_store_remove(GTK_LIST_STORE(vfl->model), &iter); + GList *list = gtk_tree_selection_get_selected_rows ( ts, &(vfl->model) ); + + // For multi delete need to store references to selected rows + GtkTreeRowReference **rrefs = file_list_get_selected_refs ( vfl->model, list ); + // And then delete each one individually as the path will have changed + file_list_store_delete_refs ( vfl->model, rrefs ); + + // Cleanup + g_list_foreach ( list, (GFunc) gtk_tree_path_free, NULL ); + g_list_free ( list ); + g_free (rrefs); } GType vik_file_list_get_type (void) @@ -88,12 +154,18 @@ GType vik_file_list_get_type (void) return vs_type; } -GtkWidget *vik_file_list_new ( const gchar *title ) +/** + * Support just one filter, as that's all that's needed ATM + * Probably need to use a GList of them if more than one is required + */ +GtkWidget *vik_file_list_new ( const gchar *title, GtkFileFilter *filter ) { GtkWidget *add_btn, *del_btn; GtkWidget *hbox, *scrolledwindow; VikFileList *vfl = VIK_FILE_LIST ( g_object_new ( VIK_FILE_LIST_TYPE, NULL ) ); + vfl->filter = filter; + GtkTreeViewColumn *column; vfl->model = GTK_TREE_MODEL ( gtk_list_store_new(1, G_TYPE_STRING) ); @@ -103,10 +175,12 @@ GtkWidget *vik_file_list_new ( const gchar *title ) column = gtk_tree_view_column_new_with_attributes ( title, gtk_cell_renderer_text_new (), "text", 0, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (vfl->treeview), column); + gtk_tree_selection_set_mode ( gtk_tree_view_get_selection (GTK_TREE_VIEW(vfl->treeview)), GTK_SELECTION_MULTIPLE ); + gtk_widget_set_size_request ( vfl->treeview, 200, 100); - add_btn = gtk_button_new_with_label("Add..."); - del_btn = gtk_button_new_with_label("Delete"); + add_btn = gtk_button_new_with_label(_("Add...")); + del_btn = gtk_button_new_with_label(_("Delete")); g_signal_connect_swapped ( G_OBJECT(add_btn), "clicked", G_CALLBACK(file_list_add), vfl ); g_signal_connect_swapped ( G_OBJECT(del_btn), "clicked", G_CALLBACK(file_list_del), vfl ); @@ -134,8 +208,8 @@ static gboolean get_file_name(GtkTreeModel *model, GtkTreePath *path, GtkTreeIte { gchar *str; gtk_tree_model_get ( model, iter, 0, &str, -1 ); - g_debug("get_file_name: %s", str); - (*list) = g_list_append((*list), g_strdup(str)); + g_debug ("%s: %s", __FUNCTION__, str); + (*list) = g_list_append((*list), str); // NB str is already a copy return FALSE; }