]>
Commit | Line | Data |
---|---|---|
ad0a8c2d EB |
1 | /* |
2 | * viking -- GPS Data and Topo Analyzer, Explorer, and Manager | |
3 | * | |
4 | * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net> | |
6eb145f6 | 5 | * Copyright (C) 2011, Rob Norris <rw_norris@hotmail.com> |
ad0a8c2d EB |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 | * | |
21 | */ | |
22 | ||
4c77d5e0 GB |
23 | #ifdef HAVE_CONFIG_H |
24 | #include "config.h" | |
25 | #endif | |
26 | ||
ad0a8c2d | 27 | #include <gtk/gtk.h> |
4c77d5e0 | 28 | #include <glib/gi18n.h> |
ad0a8c2d EB |
29 | |
30 | #include "vikfilelist.h" | |
ad0a8c2d EB |
31 | |
32 | struct _VikFileList { | |
33 | GtkVBox parent; | |
ad0a8c2d | 34 | GtkWidget *treeview; |
4c85a045 | 35 | GtkWidget *file_selector; |
ad0a8c2d | 36 | GtkTreeModel *model; |
8a2df21a | 37 | GtkFileFilter *filter; |
ad0a8c2d EB |
38 | }; |
39 | ||
40 | static void file_list_add ( VikFileList *vfl ) | |
41 | { | |
6e4a49aa MA |
42 | GSList *files = NULL; |
43 | GSList *fiter = NULL; | |
44 | ||
4c85a045 EB |
45 | if ( ! vfl->file_selector ) |
46 | { | |
47 | GtkWidget *win; | |
48 | g_assert ( (win = gtk_widget_get_toplevel(GTK_WIDGET(vfl))) ); | |
6e4a49aa MA |
49 | vfl->file_selector = gtk_file_chooser_dialog_new (_("Choose file(s)"), |
50 | GTK_WINDOW(win), | |
51 | GTK_FILE_CHOOSER_ACTION_OPEN, | |
52 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
53 | GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, | |
54 | NULL); | |
55 | gtk_file_chooser_set_select_multiple ( GTK_FILE_CHOOSER(vfl->file_selector), TRUE ); | |
4c85a045 EB |
56 | gtk_window_set_transient_for ( GTK_WINDOW(vfl->file_selector), GTK_WINDOW(win) ); |
57 | gtk_window_set_destroy_with_parent ( GTK_WINDOW(vfl->file_selector), TRUE ); | |
8a2df21a RN |
58 | |
59 | if ( vfl->filter ) | |
60 | gtk_file_chooser_add_filter ( GTK_FILE_CHOOSER(vfl->file_selector), vfl->filter ); | |
4c85a045 EB |
61 | } |
62 | ||
6e4a49aa MA |
63 | if ( gtk_dialog_run ( GTK_DIALOG(vfl->file_selector) ) == GTK_RESPONSE_ACCEPT ) { |
64 | files = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER(vfl->file_selector) ); | |
65 | fiter = files; | |
4c85a045 | 66 | GtkTreeIter iter; |
6e4a49aa MA |
67 | while ( fiter ) { |
68 | gchar *file_name = fiter->data; | |
69 | ||
4c85a045 | 70 | gtk_list_store_append ( GTK_LIST_STORE(vfl->model), &iter ); |
6e4a49aa MA |
71 | gtk_list_store_set ( GTK_LIST_STORE(vfl->model), &iter, 0, file_name, -1 ); |
72 | ||
73 | g_free (file_name); | |
74 | ||
75 | fiter = g_slist_next (fiter); | |
4c85a045 | 76 | } |
6e4a49aa | 77 | g_slist_free (files); |
4c85a045 EB |
78 | } |
79 | gtk_widget_hide ( vfl->file_selector ); | |
ad0a8c2d EB |
80 | } |
81 | ||
6eb145f6 RN |
82 | |
83 | static GtkTreeRowReference** file_list_get_selected_refs (GtkTreeModel *model, | |
84 | GList *list) | |
85 | { | |
86 | GtkTreeRowReference **arr; | |
87 | GList *iter; | |
88 | ||
89 | arr = g_new (GtkTreeRowReference *, g_list_length (list) + 1); | |
90 | ||
91 | gint pos = 0; | |
92 | for (iter = g_list_first (list); iter != NULL; iter = g_list_next (iter)) { | |
93 | GtkTreePath *path = (GtkTreePath *)(iter->data); | |
94 | arr[pos] = gtk_tree_row_reference_new (model, path); | |
95 | pos++; | |
96 | } | |
97 | arr[pos] = NULL; | |
98 | ||
99 | return arr; | |
100 | } | |
101 | ||
102 | static void file_list_store_delete_refs (GtkTreeModel *model, | |
103 | GtkTreeRowReference * const *rrefs) | |
104 | { | |
105 | GtkTreePath *path; | |
106 | GtkTreeIter iter; | |
107 | ||
108 | gint rr; | |
109 | for ( rr = 0; rrefs[rr] != NULL; rr++ ) { | |
110 | path = gtk_tree_row_reference_get_path (rrefs[rr]); | |
111 | gtk_tree_model_get_iter (model, &iter, path); | |
112 | gtk_list_store_remove (GTK_LIST_STORE (model), &iter); | |
113 | } | |
114 | } | |
115 | ||
116 | ||
ad0a8c2d EB |
117 | static void file_list_del ( VikFileList *vfl ) |
118 | { | |
119 | GtkTreeSelection *ts = gtk_tree_view_get_selection (GTK_TREE_VIEW(vfl->treeview)); | |
6eb145f6 RN |
120 | GList *list = gtk_tree_selection_get_selected_rows ( ts, &(vfl->model) ); |
121 | ||
122 | // For multi delete need to store references to selected rows | |
123 | GtkTreeRowReference **rrefs = file_list_get_selected_refs ( vfl->model, list ); | |
124 | // And then delete each one individually as the path will have changed | |
125 | file_list_store_delete_refs ( vfl->model, rrefs ); | |
126 | ||
127 | // Cleanup | |
128 | g_list_foreach ( list, (GFunc) gtk_tree_path_free, NULL ); | |
129 | g_list_free ( list ); | |
130 | g_free (rrefs); | |
ad0a8c2d EB |
131 | } |
132 | ||
133 | GType vik_file_list_get_type (void) | |
134 | { | |
135 | static GType vs_type = 0; | |
136 | ||
137 | if (!vs_type) | |
138 | { | |
139 | static const GTypeInfo vs_info = | |
140 | { | |
141 | sizeof (VikFileListClass), | |
142 | NULL, /* base_init */ | |
143 | NULL, /* base_finalize */ | |
144 | NULL, /* class init */ | |
145 | NULL, /* class_finalize */ | |
146 | NULL, /* class_data */ | |
147 | sizeof (VikFileList), | |
148 | 0, | |
149 | NULL /* instance init */ | |
150 | }; | |
151 | vs_type = g_type_register_static ( GTK_TYPE_VBOX, "VikFileList", &vs_info, 0 ); | |
152 | } | |
153 | ||
154 | return vs_type; | |
155 | } | |
156 | ||
8a2df21a RN |
157 | /** |
158 | * Support just one filter, as that's all that's needed ATM | |
159 | * Probably need to use a GList of them if more than one is required | |
160 | */ | |
161 | GtkWidget *vik_file_list_new ( const gchar *title, GtkFileFilter *filter ) | |
ad0a8c2d EB |
162 | { |
163 | GtkWidget *add_btn, *del_btn; | |
164 | GtkWidget *hbox, *scrolledwindow; | |
165 | VikFileList *vfl = VIK_FILE_LIST ( g_object_new ( VIK_FILE_LIST_TYPE, NULL ) ); | |
166 | ||
8a2df21a RN |
167 | vfl->filter = filter; |
168 | ||
ad0a8c2d EB |
169 | GtkTreeViewColumn *column; |
170 | ||
171 | vfl->model = GTK_TREE_MODEL ( gtk_list_store_new(1, G_TYPE_STRING) ); | |
172 | ||
173 | vfl->treeview = gtk_tree_view_new ( ); | |
174 | gtk_tree_view_set_model ( GTK_TREE_VIEW(vfl->treeview), vfl->model ); | |
175 | column = gtk_tree_view_column_new_with_attributes ( title, gtk_cell_renderer_text_new (), "text", 0, NULL); | |
176 | gtk_tree_view_append_column (GTK_TREE_VIEW (vfl->treeview), column); | |
177 | ||
6eb145f6 RN |
178 | gtk_tree_selection_set_mode ( gtk_tree_view_get_selection (GTK_TREE_VIEW(vfl->treeview)), GTK_SELECTION_MULTIPLE ); |
179 | ||
ad0a8c2d EB |
180 | gtk_widget_set_size_request ( vfl->treeview, 200, 100); |
181 | ||
4c77d5e0 GB |
182 | add_btn = gtk_button_new_with_label(_("Add...")); |
183 | del_btn = gtk_button_new_with_label(_("Delete")); | |
ad0a8c2d EB |
184 | |
185 | g_signal_connect_swapped ( G_OBJECT(add_btn), "clicked", G_CALLBACK(file_list_add), vfl ); | |
186 | g_signal_connect_swapped ( G_OBJECT(del_btn), "clicked", G_CALLBACK(file_list_del), vfl ); | |
187 | ||
188 | hbox = gtk_hbox_new(FALSE, 2); | |
189 | ||
190 | scrolledwindow = gtk_scrolled_window_new ( NULL, NULL ); | |
191 | gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); | |
192 | gtk_container_add ( GTK_CONTAINER(scrolledwindow), GTK_WIDGET(vfl->treeview) ); | |
193 | ||
194 | gtk_box_pack_start ( GTK_BOX(vfl), scrolledwindow, TRUE, TRUE, 3 ); | |
195 | ||
196 | ||
ad0a8c2d EB |
197 | gtk_box_pack_start ( GTK_BOX(hbox), add_btn, TRUE, TRUE, 3 ); |
198 | gtk_box_pack_start ( GTK_BOX(hbox), del_btn, TRUE, TRUE, 3 ); | |
199 | gtk_box_pack_start ( GTK_BOX(vfl), hbox, FALSE, FALSE, 3 ); | |
200 | gtk_widget_show_all(GTK_WIDGET(vfl)); | |
201 | ||
4c85a045 | 202 | vfl->file_selector = NULL; |
ad0a8c2d EB |
203 | |
204 | return GTK_WIDGET(vfl); | |
205 | } | |
206 | ||
207 | static gboolean get_file_name(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, GList **list) | |
208 | { | |
209 | gchar *str; | |
210 | gtk_tree_model_get ( model, iter, 0, &str, -1 ); | |
4c77d5e0 | 211 | g_debug ("%s: %s", __FUNCTION__, str); |
644eea0e | 212 | (*list) = g_list_append((*list), str); // NB str is already a copy |
ad0a8c2d EB |
213 | return FALSE; |
214 | } | |
215 | ||
216 | GList *vik_file_list_get_files ( VikFileList *vfl ) | |
217 | { | |
218 | GList *list = NULL; | |
219 | gtk_tree_model_foreach (vfl->model, (GtkTreeModelForeachFunc) get_file_name, &list); | |
220 | return list; | |
221 | } | |
222 | ||
223 | void vik_file_list_set_files ( VikFileList *vfl, GList *files ) | |
224 | { | |
225 | while (files) { | |
226 | GtkTreeIter iter; | |
227 | gtk_list_store_append ( GTK_LIST_STORE(vfl->model), &iter ); | |
228 | gtk_list_store_set ( GTK_LIST_STORE(vfl->model), &iter, 0, files->data, -1 ); | |
229 | files = files->next; | |
230 | } | |
231 | } |