summaryrefslogtreecommitdiffstats
path: root/meta/packages/gtk+
diff options
context:
space:
mode:
authorTomas Frydrych <tf@openedhand.com>2007-08-29 17:37:57 +0000
committerTomas Frydrych <tf@openedhand.com>2007-08-29 17:37:57 +0000
commit4a319e98fd0011cd83bd0389c5d006f948ef69f1 (patch)
treede10478364abe269fd8b18844898c1862aca1f7e /meta/packages/gtk+
parentc7b5d7bad1e32d29070aeea7c44a910795595ad2 (diff)
downloadpoky-4a319e98fd0011cd83bd0389c5d006f948ef69f1.tar.gz
modified GtkFileChooserDialog for embedded
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@2596 311d38ba-8fff-0310-9ca6-ca027cbcb966
Diffstat (limited to 'meta/packages/gtk+')
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/filechooser-default.patch6637
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/filechooser-respect-style.patch77
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/filechooser-utils.patch32
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/filechooser.patch25
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/filesystem-volumes.patch198
-rw-r--r--meta/packages/gtk+/gtk+_2.10.14.bb10
6 files changed, 6977 insertions, 2 deletions
diff --git a/meta/packages/gtk+/gtk+-2.10.14/filechooser-default.patch b/meta/packages/gtk+/gtk+-2.10.14/filechooser-default.patch
new file mode 100644
index 0000000000..0495cc9a85
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.10.14/filechooser-default.patch
@@ -0,0 +1,6637 @@
1Index: gtk+-2.10.14/gtk/gtkfilechooserdefault.c
2===================================================================
3--- gtk+-2.10.14.orig/gtk/gtkfilechooserdefault.c 2007-07-16 20:44:17.000000000 +0100
4+++ gtk+-2.10.14/gtk/gtkfilechooserdefault.c 2007-08-29 18:03:50.000000000 +0100
5@@ -33,7 +33,6 @@
6 #include "gtkcombobox.h"
7 #include "gtkentry.h"
8 #include "gtkeventbox.h"
9-#include "gtkexpander.h"
10 #include "gtkfilechooserprivate.h"
11 #include "gtkfilechooserdefault.h"
12 #include "gtkfilechooserembed.h"
13@@ -54,7 +53,6 @@
14 #include "gtkmarshalers.h"
15 #include "gtkmenuitem.h"
16 #include "gtkmessagedialog.h"
17-#include "gtkpathbar.h"
18 #include "gtkprivate.h"
19 #include "gtkradiobutton.h"
20 #include "gtkscrolledwindow.h"
21@@ -88,6 +86,8 @@
22 #include <io.h>
23 #endif
24
25+#define DEFAULT_SPACING 5
26+
27 /* Profiling stuff */
28 #undef PROFILE_FILE_CHOOSER
29 #ifdef PROFILE_FILE_CHOOSER
30@@ -98,6 +98,7 @@
31 #endif
32
33 #define PROFILE_INDENT 4
34+
35 static int profile_indent;
36
37 static void
38@@ -137,8 +138,6 @@
39 #define profile_msg(x, y)
40 #endif
41
42-
43-
44 typedef struct _GtkFileChooserDefaultClass GtkFileChooserDefaultClass;
45
46 #define GTK_FILE_CHOOSER_DEFAULT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_CHOOSER_DEFAULT, GtkFileChooserDefaultClass))
47@@ -146,6 +145,7 @@
48 #define GTK_FILE_CHOOSER_DEFAULT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_CHOOSER_DEFAULT, GtkFileChooserDefaultClass))
49
50 #define MAX_LOADING_TIME 500
51+#define LONG_CLICK_LENGTH 500
52
53 struct _GtkFileChooserDefaultClass
54 {
55@@ -159,27 +159,12 @@
56 UP_FOLDER,
57 DOWN_FOLDER,
58 HOME_FOLDER,
59- DESKTOP_FOLDER,
60- QUICK_BOOKMARK,
61- LOCATION_TOGGLE_POPUP,
62 SHOW_HIDDEN,
63 LAST_SIGNAL
64 };
65
66 static guint signals[LAST_SIGNAL] = { 0 };
67
68-/* Column numbers for the shortcuts tree. Keep these in sync with shortcuts_model_create() */
69-enum {
70- SHORTCUTS_COL_PIXBUF,
71- SHORTCUTS_COL_NAME,
72- SHORTCUTS_COL_DATA,
73- SHORTCUTS_COL_IS_VOLUME,
74- SHORTCUTS_COL_REMOVABLE,
75- SHORTCUTS_COL_PIXBUF_VISIBLE,
76- SHORTCUTS_COL_HANDLE,
77- SHORTCUTS_COL_NUM_COLUMNS
78-};
79-
80 /* Column numbers for the file list */
81 enum {
82 FILE_LIST_COL_NAME,
83@@ -188,62 +173,10 @@
84 FILE_LIST_COL_NUM_COLUMNS
85 };
86
87-/* Identifiers for target types */
88-enum {
89- GTK_TREE_MODEL_ROW,
90- TEXT_URI_LIST
91-};
92-
93-/* Target types for dragging from the shortcuts list */
94-static const GtkTargetEntry shortcuts_source_targets[] = {
95- { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW }
96-};
97-
98-static const int num_shortcuts_source_targets = (sizeof (shortcuts_source_targets)
99- / sizeof (shortcuts_source_targets[0]));
100-
101-/* Target types for dropping into the shortcuts list */
102-static const GtkTargetEntry shortcuts_dest_targets[] = {
103- { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW },
104- { "text/uri-list", 0, TEXT_URI_LIST }
105-};
106-
107-static const int num_shortcuts_dest_targets = (sizeof (shortcuts_dest_targets)
108- / sizeof (shortcuts_dest_targets[0]));
109-
110-/* Target types for DnD from the file list */
111-static const GtkTargetEntry file_list_source_targets[] = {
112- { "text/uri-list", 0, TEXT_URI_LIST }
113-};
114-
115-static const int num_file_list_source_targets = (sizeof (file_list_source_targets)
116- / sizeof (file_list_source_targets[0]));
117-
118-/* Target types for dropping into the file list */
119-static const GtkTargetEntry file_list_dest_targets[] = {
120- { "text/uri-list", 0, TEXT_URI_LIST }
121-};
122-
123-static const int num_file_list_dest_targets = (sizeof (file_list_dest_targets)
124- / sizeof (file_list_dest_targets[0]));
125-
126-
127-/* Interesting places in the shortcuts bar */
128-typedef enum {
129- SHORTCUTS_HOME,
130- SHORTCUTS_DESKTOP,
131- SHORTCUTS_VOLUMES,
132- SHORTCUTS_SHORTCUTS,
133- SHORTCUTS_BOOKMARKS_SEPARATOR,
134- SHORTCUTS_BOOKMARKS,
135- SHORTCUTS_CURRENT_FOLDER_SEPARATOR,
136- SHORTCUTS_CURRENT_FOLDER
137-} ShortcutsIndex;
138-
139 /* Icon size for if we can't get it from the theme */
140-#define FALLBACK_ICON_SIZE 16
141+#define FALLBACK_ICON_SIZE 24
142
143-#define PREVIEW_HBOX_SPACING 12
144+#define LIST_HBOX_SPACING DEFAULT_SPACING
145 #define NUM_LINES 45
146 #define NUM_CHARS 60
147
148@@ -308,7 +241,6 @@
149 const GtkFilePath *path,
150 GError **error);
151 static GSList * gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser);
152-
153 static void gtk_file_chooser_default_get_default_size (GtkFileChooserEmbed *chooser_embed,
154 gint *default_width,
155 gint *default_height);
156@@ -316,50 +248,17 @@
157 static gboolean gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed);
158 static void gtk_file_chooser_default_initial_focus (GtkFileChooserEmbed *chooser_embed);
159
160-static void location_popup_handler (GtkFileChooserDefault *impl,
161- const gchar *path);
162-static void location_popup_on_paste_handler (GtkFileChooserDefault *impl);
163-static void location_toggle_popup_handler (GtkFileChooserDefault *impl);
164 static void up_folder_handler (GtkFileChooserDefault *impl);
165 static void down_folder_handler (GtkFileChooserDefault *impl);
166 static void home_folder_handler (GtkFileChooserDefault *impl);
167-static void desktop_folder_handler (GtkFileChooserDefault *impl);
168-static void quick_bookmark_handler (GtkFileChooserDefault *impl,
169- gint bookmark_index);
170 static void show_hidden_handler (GtkFileChooserDefault *impl);
171 static void update_appearance (GtkFileChooserDefault *impl);
172
173-static void set_current_filter (GtkFileChooserDefault *impl,
174- GtkFileFilter *filter);
175-static void check_preview_change (GtkFileChooserDefault *impl);
176-
177 static void filter_combo_changed (GtkComboBox *combo_box,
178 GtkFileChooserDefault *impl);
179-static void shortcuts_row_activated_cb (GtkTreeView *tree_view,
180- GtkTreePath *path,
181- GtkTreeViewColumn *column,
182- GtkFileChooserDefault *impl);
183-
184-static gboolean shortcuts_key_press_event_cb (GtkWidget *widget,
185- GdkEventKey *event,
186- GtkFileChooserDefault *impl);
187-
188-static gboolean shortcuts_select_func (GtkTreeSelection *selection,
189- GtkTreeModel *model,
190- GtkTreePath *path,
191- gboolean path_currently_selected,
192- gpointer data);
193-static gboolean shortcuts_get_selected (GtkFileChooserDefault *impl,
194- GtkTreeIter *iter);
195-static void shortcuts_activate_iter (GtkFileChooserDefault *impl,
196- GtkTreeIter *iter);
197-static int shortcuts_get_index (GtkFileChooserDefault *impl,
198- ShortcutsIndex where);
199-static int shortcut_find_position (GtkFileChooserDefault *impl,
200- const GtkFilePath *path);
201-
202-static void bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl);
203
204+static void set_current_filter (GtkFileChooserDefault *impl,
205+ GtkFileFilter *filter);
206 static gboolean list_select_func (GtkTreeSelection *selection,
207 GtkTreeModel *model,
208 GtkTreePath *path,
209@@ -378,19 +277,6 @@
210 GtkTreeIter *iter,
211 gpointer user_data);
212
213-static void path_bar_clicked (GtkPathBar *path_bar,
214- GtkFilePath *file_path,
215- GtkFilePath *child_path,
216- gboolean child_is_hidden,
217- GtkFileChooserDefault *impl);
218-
219-static void add_bookmark_button_clicked_cb (GtkButton *button,
220- GtkFileChooserDefault *impl);
221-static void remove_bookmark_button_clicked_cb (GtkButton *button,
222- GtkFileChooserDefault *impl);
223-static void save_folder_combo_changed_cb (GtkComboBox *combo,
224- GtkFileChooserDefault *impl);
225-
226 static void list_icon_data_func (GtkTreeViewColumn *tree_column,
227 GtkCellRenderer *cell,
228 GtkTreeModel *tree_model,
229@@ -422,40 +308,8 @@
230
231 static void location_button_toggled_cb (GtkToggleButton *toggle,
232 GtkFileChooserDefault *impl);
233-static void location_switch_to_path_bar (GtkFileChooserDefault *impl);
234 static void settings_load (GtkFileChooserDefault *impl);
235
236-
237-
238-/* Drag and drop interface declarations */
239-
240-typedef struct {
241- GtkTreeModelFilter parent;
242-
243- GtkFileChooserDefault *impl;
244-} ShortcutsModelFilter;
245-
246-typedef struct {
247- GtkTreeModelFilterClass parent_class;
248-} ShortcutsModelFilterClass;
249-
250-#define SHORTCUTS_MODEL_FILTER_TYPE (_shortcuts_model_filter_get_type ())
251-#define SHORTCUTS_MODEL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHORTCUTS_MODEL_FILTER_TYPE, ShortcutsModelFilter))
252-
253-static void shortcuts_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface);
254-
255-G_DEFINE_TYPE_WITH_CODE (ShortcutsModelFilter,
256- _shortcuts_model_filter,
257- GTK_TYPE_TREE_MODEL_FILTER,
258- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
259- shortcuts_model_filter_drag_source_iface_init))
260-
261-static GtkTreeModel *shortcuts_model_filter_new (GtkFileChooserDefault *impl,
262- GtkTreeModel *child_model,
263- GtkTreePath *root);
264-
265-
266-
267 G_DEFINE_TYPE_WITH_CODE (GtkFileChooserDefault, _gtk_file_chooser_default, GTK_TYPE_VBOX,
268 G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER,
269 gtk_file_chooser_default_iface_init)
270@@ -465,13 +319,9 @@
271 static void
272 _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
273 {
274- static const guint quick_bookmark_keyvals[10] = {
275- GDK_1, GDK_2, GDK_3, GDK_4, GDK_5, GDK_6, GDK_7, GDK_8, GDK_9, GDK_0
276- };
277 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
278 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
279 GtkBindingSet *binding_set;
280- int i;
281
282 gobject_class->finalize = gtk_file_chooser_default_finalize;
283 gobject_class->constructor = gtk_file_chooser_default_constructor;
284@@ -491,7 +341,7 @@
285 _gtk_binding_signal_new (I_("location-popup"),
286 G_OBJECT_CLASS_TYPE (class),
287 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
288- G_CALLBACK (location_popup_handler),
289+ NULL,
290 NULL, NULL,
291 _gtk_marshal_VOID__STRING,
292 G_TYPE_NONE, 1, G_TYPE_STRING);
293@@ -499,15 +349,7 @@
294 _gtk_binding_signal_new ("location-popup-on-paste",
295 G_OBJECT_CLASS_TYPE (class),
296 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
297- G_CALLBACK (location_popup_on_paste_handler),
298- NULL, NULL,
299- _gtk_marshal_VOID__VOID,
300- G_TYPE_NONE, 0);
301- signals[LOCATION_TOGGLE_POPUP] =
302- _gtk_binding_signal_new (I_("location-toggle-popup"),
303- G_OBJECT_CLASS_TYPE (class),
304- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
305- G_CALLBACK (location_toggle_popup_handler),
306+ NULL,
307 NULL, NULL,
308 _gtk_marshal_VOID__VOID,
309 G_TYPE_NONE, 0);
310@@ -535,22 +377,6 @@
311 NULL, NULL,
312 _gtk_marshal_VOID__VOID,
313 G_TYPE_NONE, 0);
314- signals[DESKTOP_FOLDER] =
315- _gtk_binding_signal_new (I_("desktop-folder"),
316- G_OBJECT_CLASS_TYPE (class),
317- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
318- G_CALLBACK (desktop_folder_handler),
319- NULL, NULL,
320- _gtk_marshal_VOID__VOID,
321- G_TYPE_NONE, 0);
322- signals[QUICK_BOOKMARK] =
323- _gtk_binding_signal_new (I_("quick-bookmark"),
324- G_OBJECT_CLASS_TYPE (class),
325- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
326- G_CALLBACK (quick_bookmark_handler),
327- NULL, NULL,
328- _gtk_marshal_VOID__INT,
329- G_TYPE_NONE, 1, G_TYPE_INT);
330 signals[SHOW_HIDDEN] =
331 _gtk_binding_signal_new ("show-hidden",
332 G_OBJECT_CLASS_TYPE (class),
333@@ -618,20 +444,10 @@
334 "home-folder",
335 0);
336 gtk_binding_entry_add_signal (binding_set,
337- GDK_d, GDK_MOD1_MASK,
338- "desktop-folder",
339- 0);
340- gtk_binding_entry_add_signal (binding_set,
341 GDK_h, GDK_CONTROL_MASK,
342 "show-hidden",
343 0);
344
345- for (i = 0; i < 10; i++)
346- gtk_binding_entry_add_signal (binding_set,
347- quick_bookmark_keyvals[i], GDK_MOD1_MASK,
348- "quick-bookmark",
349- 1, G_TYPE_INT, i);
350-
351 _gtk_file_chooser_install_properties (gobject_class);
352
353 gtk_settings_install_property (g_param_spec_string ("gtk-file-chooser-backend",
354@@ -649,7 +465,6 @@
355 iface->select_all = gtk_file_chooser_default_select_all;
356 iface->unselect_all = gtk_file_chooser_default_unselect_all;
357 iface->get_paths = gtk_file_chooser_default_get_paths;
358- iface->get_preview_path = gtk_file_chooser_default_get_preview_path;
359 iface->get_file_system = gtk_file_chooser_default_get_file_system;
360 iface->set_current_folder = gtk_file_chooser_default_set_current_folder;
361 iface->get_current_folder = gtk_file_chooser_default_get_current_folder;
362@@ -657,9 +472,12 @@
363 iface->add_filter = gtk_file_chooser_default_add_filter;
364 iface->remove_filter = gtk_file_chooser_default_remove_filter;
365 iface->list_filters = gtk_file_chooser_default_list_filters;
366+
367+ /* these are only stubs */
368+ iface->get_preview_path = gtk_file_chooser_default_get_preview_path;
369 iface->add_shortcut_folder = gtk_file_chooser_default_add_shortcut_folder;
370 iface->remove_shortcut_folder = gtk_file_chooser_default_remove_shortcut_folder;
371- iface->list_shortcut_folders = gtk_file_chooser_default_list_shortcut_folders;
372+
373 }
374
375 static void
376@@ -679,80 +497,27 @@
377 access ("MARK: *** CREATE FILE CHOOSER", F_OK);
378 #endif
379 impl->local_only = TRUE;
380- impl->preview_widget_active = TRUE;
381- impl->use_preview_label = TRUE;
382 impl->select_multiple = FALSE;
383 impl->show_hidden = FALSE;
384+ impl->show_create_folder = TRUE;
385 impl->icon_size = FALLBACK_ICON_SIZE;
386 impl->load_state = LOAD_EMPTY;
387 impl->reload_state = RELOAD_EMPTY;
388 impl->pending_select_paths = NULL;
389- impl->location_mode = LOCATION_MODE_PATH_BAR;
390+ impl->location_mode = LOCATION_MODE_FILENAME_ENTRY;
391+ impl->path_history = NULL;
392
393- gtk_box_set_spacing (GTK_BOX (impl), 12);
394+ gtk_box_set_spacing (GTK_BOX (impl), DEFAULT_SPACING);
395
396 impl->tooltips = gtk_tooltips_new ();
397 g_object_ref_sink (impl->tooltips);
398
399- profile_end ("end", NULL);
400-}
401-
402-/* Frees the data columns for the specified iter in the shortcuts model*/
403-static void
404-shortcuts_free_row_data (GtkFileChooserDefault *impl,
405- GtkTreeIter *iter)
406-{
407- gpointer col_data;
408- gboolean is_volume;
409- GtkFileSystemHandle *handle;
410-
411- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), iter,
412- SHORTCUTS_COL_DATA, &col_data,
413- SHORTCUTS_COL_IS_VOLUME, &is_volume,
414- SHORTCUTS_COL_HANDLE, &handle,
415- -1);
416-
417- if (handle)
418- gtk_file_system_cancel_operation (handle);
419-
420- if (!col_data)
421- return;
422-
423- if (is_volume)
424- {
425- GtkFileSystemVolume *volume;
426-
427- volume = col_data;
428- gtk_file_system_volume_free (impl->file_system, volume);
429- }
430- else
431- {
432- GtkFilePath *path;
433+ if (!impl->root_folder)
434+ impl->root_folder = g_strdup ("/");
435
436- path = col_data;
437- gtk_file_path_free (path);
438- }
439+ profile_end ("end", NULL);
440 }
441
442-/* Frees all the data columns in the shortcuts model */
443-static void
444-shortcuts_free (GtkFileChooserDefault *impl)
445-{
446- GtkTreeIter iter;
447-
448- if (!impl->shortcuts_model)
449- return;
450-
451- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
452- do
453- {
454- shortcuts_free_row_data (impl, &iter);
455- }
456- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter));
457-
458- g_object_unref (impl->shortcuts_model);
459- impl->shortcuts_model = NULL;
460-}
461
462 static void
463 pending_select_paths_free (GtkFileChooserDefault *impl)
464@@ -771,6 +536,7 @@
465 impl->pending_select_paths = NULL;
466 }
467
468+
469 static void
470 pending_select_paths_add (GtkFileChooserDefault *impl,
471 const GtkFilePath *path)
472@@ -810,15 +576,27 @@
473 }
474
475 static void
476-gtk_file_chooser_default_finalize (GObject *object)
477+path_history_free (GtkFileChooserDefault *impl)
478 {
479- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object);
480 GSList *l;
481
482- if (impl->shortcuts_filter_model)
483- g_object_unref (impl->shortcuts_filter_model);
484+ for (l = impl->path_history; l; l = l->next)
485+ {
486+ GtkFilePath *path;
487+
488+ path = l->data;
489+ gtk_file_path_free (path);
490+ }
491+
492+ g_slist_free (impl->path_history);
493+ impl->path_history = NULL;
494+}
495
496- shortcuts_free (impl);
497+static void
498+gtk_file_chooser_default_finalize (GObject *object)
499+{
500+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object);
501+ GSList *l;
502
503 g_object_unref (impl->file_system);
504
505@@ -842,8 +620,7 @@
506 if (impl->current_folder)
507 gtk_file_path_free (impl->current_folder);
508
509- if (impl->preview_path)
510- gtk_file_path_free (impl->preview_path);
511+ path_history_free (impl);
512
513 load_remove_timer (impl);
514
515@@ -854,12 +631,18 @@
516 if (impl->sort_model)
517 g_object_unref (impl->sort_model);
518
519- g_free (impl->preview_display_name);
520+ if (impl->list_press_path)
521+ {
522+ gtk_tree_path_free (impl->list_press_path);
523+ impl->list_press_path = NULL;
524+ }
525
526 g_free (impl->edited_new_text);
527
528 g_object_unref (impl->tooltips);
529
530+ g_free (impl->root_folder);
531+
532 G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->finalize (object);
533 }
534
535@@ -944,28 +727,6 @@
536 path, error);
537 }
538
539-/* Shows an error dialog about not being able to add a bookmark */
540-static void
541-error_adding_bookmark_dialog (GtkFileChooserDefault *impl,
542- const GtkFilePath *path,
543- GError *error)
544-{
545- error_dialog (impl,
546- _("Could not add a bookmark"),
547- path, error);
548-}
549-
550-/* Shows an error dialog about not being able to remove a bookmark */
551-static void
552-error_removing_bookmark_dialog (GtkFileChooserDefault *impl,
553- const GtkFilePath *path,
554- GError *error)
555-{
556- error_dialog (impl,
557- _("Could not remove bookmark"),
558- path, error);
559-}
560-
561 /* Shows an error dialog about not being able to create a folder */
562 static void
563 error_creating_folder_dialog (GtkFileChooserDefault *impl,
564@@ -1015,2637 +776,387 @@
565
566 /* Changes folders, displaying an error dialog if this fails */
567 static gboolean
568-change_folder_and_display_error (GtkFileChooserDefault *impl,
569- const GtkFilePath *path,
570- gboolean clear_entry)
571+change_folder (GtkFileChooserDefault *impl, const GtkFilePath *path,
572+ gboolean errormsg)
573 {
574 GError *error;
575 gboolean result;
576 GtkFilePath *path_copy;
577+ gchar * file_name;
578
579 g_return_val_if_fail (path != NULL, FALSE);
580
581- profile_start ("start", (char *) path);
582+ path_copy = gtk_file_path_copy (path);
583+ file_name = gtk_file_system_path_to_filename (impl->file_system, path_copy);
584
585- /* We copy the path because of this case:
586- *
587- * list_row_activated()
588- * fetches path from model; path belongs to the model (*)
589- * calls change_folder_and_display_error()
590- * calls _gtk_file_chooser_set_current_folder_path()
591- * changing folders fails, sets model to NULL, thus freeing the path in (*)
592- */
593+ if (!file_name)
594+ {
595+ gtk_file_path_free (path_copy);
596+ return 0;
597+ }
598+
599+ if (impl->root_folder && file_name[0] == '/' && file_name[1] == 0)
600+ {
601+ /* If changing to / and we have root_folder, change into it instead */
602+ gtk_file_path_free (path_copy);
603+ path_copy = gtk_file_system_filename_to_path (impl->file_system,
604+ impl->root_folder);
605+
606+ gtk_widget_set_sensitive (impl->up_button, FALSE);
607+ }
608+ else if (impl->root_folder &&
609+ strcmp (file_name, impl->root_folder) &&
610+ !strncmp (file_name, impl->root_folder, strlen (file_name)))
611+ {
612+ /* refuse to change below the root */
613+ gtk_file_path_free (path_copy);
614+ g_free (file_name);
615+ return 0;
616+ }
617+ else if (!strcmp (file_name, impl->root_folder))
618+ {
619+ gtk_widget_set_sensitive (impl->up_button, FALSE);
620+ }
621+ else if (impl->current_folder && !strcmp (file_name, "/media"))
622+ {
623+ /* Asked to changed into /media -- if we are already in a media
624+ * child folder, we refuse, but if we are in the root, we permit this
625+ */
626+ gchar *name =
627+ gtk_file_system_path_to_filename (impl->file_system,
628+ impl->current_folder);
629+
630+ if (name && !strncmp (name, "/media", 6))
631+ {
632+ g_free (name);
633+ gtk_file_path_free (path_copy);
634+ g_free (file_name);
635+ return 0;
636+ }
637+
638+ gtk_widget_set_sensitive (impl->up_button, TRUE);
639+ }
640+ else if (!strncmp (file_name, "/media/", 7))
641+ {
642+ /* Changing into a media child -- if it is an immediate child, disable
643+ * the Up button
644+ */
645+ gchar * p = file_name + 7;
646+ gchar * q = strchr (p, '/');
647+ if (!q)
648+ gtk_widget_set_sensitive (impl->up_button, FALSE);
649+ else
650+ gtk_widget_set_sensitive (impl->up_button, TRUE);
651+ }
652+ else
653+ {
654+ gtk_widget_set_sensitive (impl->up_button, TRUE);
655+ }
656
657- path_copy = gtk_file_path_copy (path);
658
659 error = NULL;
660- result = gtk_file_chooser_default_update_current_folder (GTK_FILE_CHOOSER (impl), path_copy, TRUE, clear_entry, &error);
661+ result = _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (impl), path_copy, &error);
662
663- if (!result)
664+ if (errormsg && !result)
665 error_changing_folder_dialog (impl, path_copy, error);
666
667 gtk_file_path_free (path_copy);
668-
669- profile_end ("end", (char *) path);
670+ g_free (file_name);
671
672 return result;
673 }
674
675-static void
676-update_preview_widget_visibility (GtkFileChooserDefault *impl)
677+static gboolean
678+change_folder_and_display_error (GtkFileChooserDefault *impl,
679+ const GtkFilePath *path)
680 {
681- if (impl->use_preview_label)
682- {
683- if (!impl->preview_label)
684- {
685- impl->preview_label = gtk_label_new (impl->preview_display_name);
686- gtk_box_pack_start (GTK_BOX (impl->preview_box), impl->preview_label, FALSE, FALSE, 0);
687- gtk_box_reorder_child (GTK_BOX (impl->preview_box), impl->preview_label, 0);
688- gtk_label_set_ellipsize (GTK_LABEL (impl->preview_label), PANGO_ELLIPSIZE_MIDDLE);
689- gtk_widget_show (impl->preview_label);
690- }
691- }
692+ return change_folder (impl, path, TRUE);
693+}
694+
695+
696+/* FIXME: GtkFileSystem needs a function to split a remote path
697+ * into hostname and path components, or maybe just have a
698+ * gtk_file_system_path_get_display_name().
699+ *
700+ * This function is also used in gtkfilechooserbutton.c
701+ */
702+gchar *
703+_gtk_file_chooser_label_for_uri (const gchar *uri)
704+{
705+ const gchar *path, *start, *end, *p;
706+ gchar *host, *label;
707+
708+ start = strstr (uri, "://");
709+ start += 3;
710+ path = strchr (start, '/');
711+
712+ if (path)
713+ end = path;
714 else
715 {
716- if (impl->preview_label)
717- {
718- gtk_widget_destroy (impl->preview_label);
719- impl->preview_label = NULL;
720- }
721+ end = uri + strlen (uri);
722+ path = "/";
723 }
724
725- if (impl->preview_widget_active && impl->preview_widget)
726- gtk_widget_show (impl->preview_box);
727- else
728- gtk_widget_hide (impl->preview_box);
729+ /* strip username */
730+ p = strchr (start, '@');
731+ if (p && p < end)
732+ {
733+ start = p + 1;
734+ }
735
736- g_signal_emit_by_name (impl, "default-size-changed");
737-}
738+ p = strchr (start, ':');
739+ if (p && p < end)
740+ end = p;
741
742-static void
743-set_preview_widget (GtkFileChooserDefault *impl,
744- GtkWidget *preview_widget)
745-{
746- if (preview_widget == impl->preview_widget)
747- return;
748+ host = g_strndup (start, end - start);
749
750- if (impl->preview_widget)
751- gtk_container_remove (GTK_CONTAINER (impl->preview_box),
752- impl->preview_widget);
753+ /* Translators: the first string is a path and the second string
754+ * is a hostname. Nautilus and the panel contain the same string
755+ * to translate.
756+ */
757+ label = g_strdup_printf (_("%1$s on %2$s"), path, host);
758
759- impl->preview_widget = preview_widget;
760- if (impl->preview_widget)
761- {
762- gtk_widget_show (impl->preview_widget);
763- gtk_box_pack_start (GTK_BOX (impl->preview_box), impl->preview_widget, TRUE, TRUE, 0);
764- gtk_box_reorder_child (GTK_BOX (impl->preview_box),
765- impl->preview_widget,
766- (impl->use_preview_label && impl->preview_label) ? 1 : 0);
767- }
768+ g_free (host);
769
770- update_preview_widget_visibility (impl);
771+ return label;
772 }
773
774-/* Re-reads all the icons for the shortcuts, used when the theme changes */
775-struct ReloadIconsData
776-{
777- GtkFileChooserDefault *impl;
778- GtkTreeRowReference *row_ref;
779-};
780
781+/* Callback used when the "New Folder" button is clicked */
782 static void
783-shortcuts_reload_icons_get_info_cb (GtkFileSystemHandle *handle,
784- const GtkFileInfo *info,
785- const GError *error,
786- gpointer user_data)
787+new_folder_button_clicked (GtkButton *button,
788+ GtkFileChooserDefault *impl)
789 {
790- GdkPixbuf *pixbuf;
791 GtkTreeIter iter;
792 GtkTreePath *path;
793- gboolean cancelled = handle->cancelled;
794- struct ReloadIconsData *data = user_data;
795-
796- if (!g_slist_find (data->impl->reload_icon_handles, handle))
797- goto out;
798-
799- data->impl->reload_icon_handles = g_slist_remove (data->impl->reload_icon_handles, handle);
800
801- if (cancelled || error)
802- goto out;
803+ if (!impl->browse_files_model)
804+ return; /* FIXME: this sucks. Disable the New Folder button or something. */
805
806- pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->impl),
807- data->impl->icon_size, NULL);
808+ /* Prevent button from being clicked twice */
809+ gtk_widget_set_sensitive (impl->browse_new_folder_button, FALSE);
810
811- path = gtk_tree_row_reference_get_path (data->row_ref);
812- gtk_tree_model_get_iter (GTK_TREE_MODEL (data->impl->shortcuts_model), &iter, path);
813- gtk_list_store_set (data->impl->shortcuts_model, &iter,
814- SHORTCUTS_COL_PIXBUF, pixbuf,
815- -1);
816- gtk_tree_path_free (path);
817+ _gtk_file_system_model_add_editable (impl->browse_files_model, &iter);
818
819- if (pixbuf)
820- g_object_unref (pixbuf);
821+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->browse_files_model), &iter);
822+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->browse_files_tree_view),
823+ path, impl->list_name_column,
824+ FALSE, 0.0, 0.0);
825
826-out:
827- gtk_tree_row_reference_free (data->row_ref);
828- g_object_unref (data->impl);
829- g_free (data);
830+ g_object_set (impl->list_name_renderer, "editable", TRUE, NULL);
831+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view),
832+ path,
833+ impl->list_name_column,
834+ TRUE);
835
836- g_object_unref (handle);
837+ gtk_tree_path_free (path);
838 }
839
840 static void
841-shortcuts_reload_icons (GtkFileChooserDefault *impl)
842+edited_idle_create_folder_cb (GtkFileSystemHandle *handle,
843+ const GtkFilePath *path,
844+ const GError *error,
845+ gpointer data)
846 {
847- GSList *l;
848- GtkTreeIter iter;
849-
850- profile_start ("start", NULL);
851+ gboolean cancelled = handle->cancelled;
852+ GtkFileChooserDefault *impl = data;
853
854- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
855+ if (!g_slist_find (impl->pending_handles, handle))
856 goto out;
857
858- for (l = impl->reload_icon_handles; l; l = l->next)
859- {
860- GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (l->data);
861- gtk_file_system_cancel_operation (handle);
862- }
863- g_slist_free (impl->reload_icon_handles);
864- impl->reload_icon_handles = NULL;
865-
866- do
867- {
868- gpointer data;
869- gboolean is_volume;
870- gboolean pixbuf_visible;
871- GdkPixbuf *pixbuf;
872+ impl->pending_handles = g_slist_remove (impl->pending_handles, handle);
873
874- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
875- SHORTCUTS_COL_DATA, &data,
876- SHORTCUTS_COL_IS_VOLUME, &is_volume,
877- SHORTCUTS_COL_PIXBUF_VISIBLE, &pixbuf_visible,
878- -1);
879+ if (cancelled)
880+ goto out;
881
882- if (pixbuf_visible && data)
883- {
884- if (is_volume)
885- {
886- GtkFileSystemVolume *volume;
887+ if (!error)
888+ change_folder_and_display_error (impl, path);
889+ else
890+ error_creating_folder_dialog (impl, path, g_error_copy (error));
891
892- volume = data;
893- pixbuf = gtk_file_system_volume_render_icon (impl->file_system, volume, GTK_WIDGET (impl),
894- impl->icon_size, NULL);
895-
896- gtk_list_store_set (impl->shortcuts_model, &iter,
897- SHORTCUTS_COL_PIXBUF, pixbuf,
898- -1);
899+ out:
900+ g_object_unref (impl);
901+ g_object_unref (handle);
902+}
903
904- if (pixbuf)
905- g_object_unref (pixbuf);
906- }
907- else if (gtk_file_system_path_is_local (impl->file_system, (GtkFilePath *)data))
908- {
909- const GtkFilePath *path;
910- struct ReloadIconsData *info;
911- GtkTreePath *tree_path;
912- GtkFileSystemHandle *handle;
913-
914- path = data;
915-
916- info = g_new0 (struct ReloadIconsData, 1);
917- info->impl = g_object_ref (impl);
918- tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
919- info->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->shortcuts_model), tree_path);
920- gtk_tree_path_free (tree_path);
921-
922- handle = gtk_file_system_get_info (impl->file_system, path,
923- GTK_FILE_INFO_ICON,
924- shortcuts_reload_icons_get_info_cb,
925- info);
926- impl->reload_icon_handles = g_slist_append (impl->reload_icon_handles, handle);
927- }
928- else
929- {
930- GtkIconTheme *icon_theme;
931-
932- /* Don't call get_info for remote paths to avoid latency and
933- * auth dialogs.
934- * If we switch to a better bookmarks file format (XBEL), we
935- * should use mime info to get a better icon.
936- */
937- icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
938- pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-directory",
939- impl->icon_size, 0, NULL);
940-
941- gtk_list_store_set (impl->shortcuts_model, &iter,
942- SHORTCUTS_COL_PIXBUF, pixbuf,
943- -1);
944-
945- if (pixbuf)
946- g_object_unref (pixbuf);
947- }
948- }
949- }
950- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model),&iter));
951-
952- out:
953-
954- profile_end ("end", NULL);
955-}
956-
957-static void
958-shortcuts_find_folder (GtkFileChooserDefault *impl,
959- GtkFilePath *folder)
960-{
961- GtkTreeSelection *selection;
962- int pos;
963- GtkTreePath *path;
964-
965- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
966-
967- g_assert (folder != NULL);
968- pos = shortcut_find_position (impl, folder);
969- if (pos == -1)
970- {
971- gtk_tree_selection_unselect_all (selection);
972- return;
973- }
974-
975- path = gtk_tree_path_new_from_indices (pos, -1);
976- gtk_tree_selection_select_path (selection, path);
977- gtk_tree_path_free (path);
978-}
979-
980-/* If a shortcut corresponds to the current folder, selects it */
981-static void
982-shortcuts_find_current_folder (GtkFileChooserDefault *impl)
983-{
984- shortcuts_find_folder (impl, impl->current_folder);
985-}
986-
987-/* Removes the specified number of rows from the shortcuts list */
988-static void
989-shortcuts_remove_rows (GtkFileChooserDefault *impl,
990- int start_row,
991- int n_rows)
992-{
993- GtkTreePath *path;
994-
995- path = gtk_tree_path_new_from_indices (start_row, -1);
996-
997- for (; n_rows; n_rows--)
998- {
999- GtkTreeIter iter;
1000-
1001- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->shortcuts_model), &iter, path))
1002- g_assert_not_reached ();
1003-
1004- shortcuts_free_row_data (impl, &iter);
1005- gtk_list_store_remove (impl->shortcuts_model, &iter);
1006- }
1007-
1008- gtk_tree_path_free (path);
1009-}
1010-
1011-static void
1012-shortcuts_update_count (GtkFileChooserDefault *impl,
1013- ShortcutsIndex type,
1014- gint value)
1015-{
1016- switch (type)
1017- {
1018- case SHORTCUTS_HOME:
1019- if (value < 0)
1020- impl->has_home = FALSE;
1021- else
1022- impl->has_home = TRUE;
1023- break;
1024-
1025- case SHORTCUTS_DESKTOP:
1026- if (value < 0)
1027- impl->has_desktop = FALSE;
1028- else
1029- impl->has_desktop = TRUE;
1030- break;
1031-
1032- case SHORTCUTS_VOLUMES:
1033- impl->num_volumes += value;
1034- break;
1035-
1036- case SHORTCUTS_SHORTCUTS:
1037- impl->num_shortcuts += value;
1038- break;
1039-
1040- case SHORTCUTS_BOOKMARKS:
1041- impl->num_bookmarks += value;
1042- break;
1043-
1044- case SHORTCUTS_CURRENT_FOLDER:
1045- if (value < 0)
1046- impl->shortcuts_current_folder_active = FALSE;
1047- else
1048- impl->shortcuts_current_folder_active = TRUE;
1049- break;
1050-
1051- default:
1052- /* nothing */
1053- break;
1054- }
1055-}
1056-
1057-struct ShortcutsInsertRequest
1058-{
1059- GtkFileChooserDefault *impl;
1060- GtkFilePath *parent_path;
1061- GtkFilePath *path;
1062- int pos;
1063- char *label_copy;
1064- GtkTreeRowReference *row_ref;
1065- ShortcutsIndex type;
1066- gboolean name_only;
1067- gboolean removable;
1068-};
1069-
1070-static void
1071-get_file_info_finished (GtkFileSystemHandle *handle,
1072- const GtkFileInfo *info,
1073- const GError *error,
1074- gpointer data)
1075-{
1076- gint pos = -1;
1077- gboolean cancelled = handle->cancelled;
1078- gboolean is_volume = FALSE;
1079- GdkPixbuf *pixbuf;
1080- GtkTreePath *path;
1081- GtkTreeIter iter;
1082- GtkFileSystemHandle *model_handle;
1083- struct ShortcutsInsertRequest *request = data;
1084-
1085- path = gtk_tree_row_reference_get_path (request->row_ref);
1086- if (!path)
1087- /* Handle doesn't exist anymore in the model */
1088- goto out;
1089-
1090- pos = gtk_tree_path_get_indices (path)[0];
1091- gtk_tree_model_get_iter (GTK_TREE_MODEL (request->impl->shortcuts_model),
1092- &iter, path);
1093- gtk_tree_path_free (path);
1094-
1095- /* validate handle, else goto out */
1096- gtk_tree_model_get (GTK_TREE_MODEL (request->impl->shortcuts_model), &iter,
1097- SHORTCUTS_COL_HANDLE, &model_handle,
1098- -1);
1099- if (handle != model_handle)
1100- goto out;
1101-
1102- /* set the handle to NULL in the model (we unref later on) */
1103- gtk_list_store_set (request->impl->shortcuts_model, &iter,
1104- SHORTCUTS_COL_HANDLE, NULL,
1105- -1);
1106-
1107- if (cancelled)
1108- goto out;
1109-
1110- if (!info)
1111- {
1112- gtk_list_store_remove (request->impl->shortcuts_model, &iter);
1113- shortcuts_update_count (request->impl, request->type, -1);
1114-
1115- if (request->type == SHORTCUTS_HOME)
1116- {
1117- const char *home = g_get_home_dir ();
1118- GtkFilePath *home_path;
1119-
1120- home_path = gtk_file_system_filename_to_path (request->impl->file_system, home);
1121- error_getting_info_dialog (request->impl, home_path, g_error_copy (error));
1122- gtk_file_path_free (home_path);
1123- }
1124- else if (request->type == SHORTCUTS_CURRENT_FOLDER)
1125- {
1126- /* Remove the current folder separator */
1127- gint separator_pos = shortcuts_get_index (request->impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
1128- shortcuts_remove_rows (request->impl, separator_pos, 1);
1129- }
1130-
1131- goto out;
1132- }
1133-
1134- if (!request->label_copy)
1135- request->label_copy = g_strdup (gtk_file_info_get_display_name (info));
1136- pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (request->impl),
1137- request->impl->icon_size, NULL);
1138-
1139- gtk_list_store_set (request->impl->shortcuts_model, &iter,
1140- SHORTCUTS_COL_PIXBUF, pixbuf,
1141- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
1142- SHORTCUTS_COL_NAME, request->label_copy,
1143- SHORTCUTS_COL_IS_VOLUME, is_volume,
1144- SHORTCUTS_COL_REMOVABLE, request->removable,
1145- -1);
1146-
1147- if (request->impl->shortcuts_filter_model)
1148- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (request->impl->shortcuts_filter_model));
1149-
1150- if (request->type == SHORTCUTS_CURRENT_FOLDER
1151- && request->impl->save_folder_combo != NULL)
1152- {
1153- /* The current folder is updated via _activate_iter(), don't
1154- * have save_folder_combo_changed_cb() call _activate_iter()
1155- * again.
1156- */
1157- g_signal_handlers_block_by_func (request->impl->save_folder_combo,
1158- G_CALLBACK (save_folder_combo_changed_cb),
1159- request->impl);
1160- gtk_combo_box_set_active (GTK_COMBO_BOX (request->impl->save_folder_combo), pos);
1161- g_signal_handlers_unblock_by_func (request->impl->save_folder_combo,
1162- G_CALLBACK (save_folder_combo_changed_cb),
1163- request->impl);
1164- }
1165-
1166- if (pixbuf)
1167- g_object_unref (pixbuf);
1168-
1169-out:
1170- g_object_unref (request->impl);
1171- gtk_file_path_free (request->parent_path);
1172- gtk_file_path_free (request->path);
1173- gtk_tree_row_reference_free (request->row_ref);
1174- g_free (request->label_copy);
1175- g_free (request);
1176-
1177- g_object_unref (handle);
1178-}
1179-
1180-/* FIXME: GtkFileSystem needs a function to split a remote path
1181- * into hostname and path components, or maybe just have a
1182- * gtk_file_system_path_get_display_name().
1183- *
1184- * This function is also used in gtkfilechooserbutton.c
1185- */
1186-gchar *
1187-_gtk_file_chooser_label_for_uri (const gchar *uri)
1188-{
1189- const gchar *path, *start, *end, *p;
1190- gchar *host, *label;
1191-
1192- start = strstr (uri, "://");
1193- start += 3;
1194- path = strchr (start, '/');
1195-
1196- if (path)
1197- end = path;
1198- else
1199- {
1200- end = uri + strlen (uri);
1201- path = "/";
1202- }
1203-
1204- /* strip username */
1205- p = strchr (start, '@');
1206- if (p && p < end)
1207- {
1208- start = p + 1;
1209- }
1210-
1211- p = strchr (start, ':');
1212- if (p && p < end)
1213- end = p;
1214-
1215- host = g_strndup (start, end - start);
1216-
1217- /* Translators: the first string is a path and the second string
1218- * is a hostname. Nautilus and the panel contain the same string
1219- * to translate.
1220- */
1221- label = g_strdup_printf (_("%1$s on %2$s"), path, host);
1222-
1223- g_free (host);
1224-
1225- return label;
1226-}
1227-
1228-/* Inserts a path in the shortcuts tree, making a copy of it; alternatively,
1229- * inserts a volume. A position of -1 indicates the end of the tree.
1230- */
1231-static void
1232-shortcuts_insert_path (GtkFileChooserDefault *impl,
1233- int pos,
1234- gboolean is_volume,
1235- GtkFileSystemVolume *volume,
1236- const GtkFilePath *path,
1237- const char *label,
1238- gboolean removable,
1239- ShortcutsIndex type)
1240-{
1241- char *label_copy;
1242- GdkPixbuf *pixbuf = NULL;
1243- gpointer data = NULL;
1244- GtkTreeIter iter;
1245- GtkIconTheme *icon_theme;
1246-
1247- profile_start ("start", is_volume ? "volume" : (char *) path);
1248-
1249- if (is_volume)
1250- {
1251- data = volume;
1252- label_copy = gtk_file_system_volume_get_display_name (impl->file_system, volume);
1253- pixbuf = gtk_file_system_volume_render_icon (impl->file_system, volume, GTK_WIDGET (impl),
1254- impl->icon_size, NULL);
1255- }
1256- else if (gtk_file_system_path_is_local (impl->file_system, path))
1257- {
1258- struct ShortcutsInsertRequest *request;
1259- GtkFileSystemHandle *handle;
1260- GtkTreePath *p;
1261-
1262- request = g_new0 (struct ShortcutsInsertRequest, 1);
1263- request->impl = g_object_ref (impl);
1264- request->path = gtk_file_path_copy (path);
1265- request->name_only = TRUE;
1266- request->removable = removable;
1267- request->pos = pos;
1268- request->type = type;
1269- if (label)
1270- request->label_copy = g_strdup (label);
1271-
1272- if (pos == -1)
1273- gtk_list_store_append (impl->shortcuts_model, &iter);
1274- else
1275- gtk_list_store_insert (impl->shortcuts_model, &iter, pos);
1276-
1277- p = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
1278- request->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->shortcuts_model), p);
1279- gtk_tree_path_free (p);
1280-
1281- handle = gtk_file_system_get_info (request->impl->file_system, request->path,
1282- GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_IS_HIDDEN | GTK_FILE_INFO_ICON,
1283- get_file_info_finished, request);
1284-
1285- gtk_list_store_set (impl->shortcuts_model, &iter,
1286- SHORTCUTS_COL_DATA, gtk_file_path_copy (path),
1287- SHORTCUTS_COL_IS_VOLUME, is_volume,
1288- SHORTCUTS_COL_HANDLE, handle,
1289- -1);
1290-
1291- shortcuts_update_count (impl, type, 1);
1292-
1293- return;
1294- }
1295- else
1296- {
1297- /* Don't call get_info for remote paths to avoid latency and
1298- * auth dialogs.
1299- */
1300- data = gtk_file_path_copy (path);
1301- if (label)
1302- label_copy = g_strdup (label);
1303- else
1304- {
1305- gchar *uri;
1306-
1307- uri = gtk_file_system_path_to_uri (impl->file_system, path);
1308-
1309- label_copy = _gtk_file_chooser_label_for_uri (uri);
1310-
1311- g_free (uri);
1312- }
1313-
1314- /* If we switch to a better bookmarks file format (XBEL), we
1315- * should use mime info to get a better icon.
1316- */
1317- icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
1318- pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-directory",
1319- impl->icon_size, 0, NULL);
1320- }
1321-
1322- if (pos == -1)
1323- gtk_list_store_append (impl->shortcuts_model, &iter);
1324- else
1325- gtk_list_store_insert (impl->shortcuts_model, &iter, pos);
1326-
1327- shortcuts_update_count (impl, type, 1);
1328-
1329- gtk_list_store_set (impl->shortcuts_model, &iter,
1330- SHORTCUTS_COL_PIXBUF, pixbuf,
1331- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
1332- SHORTCUTS_COL_NAME, label_copy,
1333- SHORTCUTS_COL_DATA, data,
1334- SHORTCUTS_COL_IS_VOLUME, is_volume,
1335- SHORTCUTS_COL_REMOVABLE, removable,
1336- SHORTCUTS_COL_HANDLE, NULL,
1337- -1);
1338-
1339- if (impl->shortcuts_filter_model)
1340- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model));
1341-
1342- if (type == SHORTCUTS_CURRENT_FOLDER && impl->save_folder_combo != NULL)
1343- {
1344- /* The current folder is updated via _activate_iter(), don't
1345- * have save_folder_combo_changed_cb() call _activate_iter()
1346- * again.
1347- */
1348- gint combo_pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER);
1349- g_signal_handlers_block_by_func (impl->save_folder_combo,
1350- G_CALLBACK (save_folder_combo_changed_cb),
1351- impl);
1352- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), combo_pos);
1353- g_signal_handlers_unblock_by_func (impl->save_folder_combo,
1354- G_CALLBACK (save_folder_combo_changed_cb),
1355- impl);
1356- }
1357-
1358- g_free (label_copy);
1359-
1360- if (pixbuf)
1361- g_object_unref (pixbuf);
1362-
1363- profile_end ("end", NULL);
1364-}
1365-
1366-/* Appends an item for the user's home directory to the shortcuts model */
1367-static void
1368-shortcuts_append_home (GtkFileChooserDefault *impl)
1369-{
1370- const char *home;
1371- GtkFilePath *home_path;
1372-
1373- profile_start ("start", NULL);
1374-
1375- home = g_get_home_dir ();
1376- if (home == NULL)
1377- {
1378- profile_end ("end - no home directory!?", NULL);
1379- return;
1380- }
1381-
1382- home_path = gtk_file_system_filename_to_path (impl->file_system, home);
1383-
1384- shortcuts_insert_path (impl, -1, FALSE, NULL, home_path, NULL, FALSE, SHORTCUTS_HOME);
1385-
1386- gtk_file_path_free (home_path);
1387-
1388- profile_end ("end", NULL);
1389-}
1390-
1391-/* Appends the ~/Desktop directory to the shortcuts model */
1392-static void
1393-shortcuts_append_desktop (GtkFileChooserDefault *impl)
1394-{
1395- char *name;
1396- const char *home;
1397- GtkFilePath *path;
1398-
1399- profile_start ("start", NULL);
1400-
1401-#ifdef G_OS_WIN32
1402- name = _gtk_file_system_win32_get_desktop ();
1403-#else
1404- home = g_get_home_dir ();
1405- if (home == NULL)
1406- {
1407- profile_end ("end - no home directory!?", NULL);
1408- return;
1409- }
1410-
1411- name = g_build_filename (home, "Desktop", NULL);
1412-#endif
1413-
1414- path = gtk_file_system_filename_to_path (impl->file_system, name);
1415- g_free (name);
1416-
1417- shortcuts_insert_path (impl, -1, FALSE, NULL, path, _("Desktop"), FALSE, SHORTCUTS_DESKTOP);
1418- /* We do not actually pop up an error dialog if there is no desktop directory
1419- * because some people may really not want to have one.
1420- */
1421-
1422- gtk_file_path_free (path);
1423-
1424- profile_end ("end", NULL);
1425-}
1426-
1427-/* Appends a list of GtkFilePath to the shortcuts model; returns how many were inserted */
1428-static int
1429-shortcuts_append_paths (GtkFileChooserDefault *impl,
1430- GSList *paths)
1431-{
1432- int start_row;
1433- int num_inserted;
1434- gchar *label;
1435-
1436- profile_start ("start", NULL);
1437-
1438- /* As there is no separator now, we want to start there.
1439- */
1440- start_row = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR);
1441- num_inserted = 0;
1442-
1443- for (; paths; paths = paths->next)
1444- {
1445- GtkFilePath *path;
1446-
1447- path = paths->data;
1448-
1449- if (impl->local_only &&
1450- !gtk_file_system_path_is_local (impl->file_system, path))
1451- continue;
1452-
1453- label = gtk_file_system_get_bookmark_label (impl->file_system, path);
1454-
1455- /* NULL GError, but we don't really want to show error boxes here */
1456- shortcuts_insert_path (impl, start_row + num_inserted, FALSE, NULL, path, label, TRUE, SHORTCUTS_BOOKMARKS);
1457- num_inserted++;
1458-
1459- g_free (label);
1460- }
1461-
1462- profile_end ("end", NULL);
1463-
1464- return num_inserted;
1465-}
1466-
1467-/* Returns the index for the corresponding item in the shortcuts bar */
1468-static int
1469-shortcuts_get_index (GtkFileChooserDefault *impl,
1470- ShortcutsIndex where)
1471-{
1472- int n;
1473-
1474- n = 0;
1475-
1476- if (where == SHORTCUTS_HOME)
1477- goto out;
1478-
1479- n += impl->has_home ? 1 : 0;
1480-
1481- if (where == SHORTCUTS_DESKTOP)
1482- goto out;
1483-
1484- n += impl->has_desktop ? 1 : 0;
1485-
1486- if (where == SHORTCUTS_VOLUMES)
1487- goto out;
1488-
1489- n += impl->num_volumes;
1490-
1491- if (where == SHORTCUTS_SHORTCUTS)
1492- goto out;
1493-
1494- n += impl->num_shortcuts;
1495-
1496- if (where == SHORTCUTS_BOOKMARKS_SEPARATOR)
1497- goto out;
1498-
1499- /* If there are no bookmarks there won't be a separator */
1500- n += (impl->num_bookmarks > 0) ? 1 : 0;
1501-
1502- if (where == SHORTCUTS_BOOKMARKS)
1503- goto out;
1504-
1505- n += impl->num_bookmarks;
1506-
1507- if (where == SHORTCUTS_CURRENT_FOLDER_SEPARATOR)
1508- goto out;
1509-
1510- n += 1;
1511-
1512- if (where == SHORTCUTS_CURRENT_FOLDER)
1513- goto out;
1514-
1515- g_assert_not_reached ();
1516-
1517- out:
1518-
1519- return n;
1520-}
1521-
1522-/* Adds all the file system volumes to the shortcuts model */
1523-static void
1524-shortcuts_add_volumes (GtkFileChooserDefault *impl)
1525-{
1526- int start_row;
1527- GSList *list, *l;
1528- int n;
1529- gboolean old_changing_folders;
1530-
1531- profile_start ("start", NULL);
1532-
1533-
1534- old_changing_folders = impl->changing_folder;
1535- impl->changing_folder = TRUE;
1536-
1537- start_row = shortcuts_get_index (impl, SHORTCUTS_VOLUMES);
1538- shortcuts_remove_rows (impl, start_row, impl->num_volumes);
1539- impl->num_volumes = 0;
1540-
1541- list = gtk_file_system_list_volumes (impl->file_system);
1542-
1543- n = 0;
1544-
1545- for (l = list; l; l = l->next)
1546- {
1547- GtkFileSystemVolume *volume;
1548-
1549- volume = l->data;
1550-
1551- if (impl->local_only)
1552- {
1553- if (gtk_file_system_volume_get_is_mounted (impl->file_system, volume))
1554- {
1555- GtkFilePath *base_path;
1556-
1557- base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
1558- if (base_path != NULL)
1559- {
1560- gboolean is_local = gtk_file_system_path_is_local (impl->file_system, base_path);
1561- gtk_file_path_free (base_path);
1562-
1563- if (!is_local)
1564- {
1565- gtk_file_system_volume_free (impl->file_system, volume);
1566- continue;
1567- }
1568- }
1569- }
1570- }
1571-
1572- shortcuts_insert_path (impl, start_row + n, TRUE, volume, NULL, NULL, FALSE, SHORTCUTS_VOLUMES);
1573- n++;
1574- }
1575-
1576- impl->num_volumes = n;
1577- g_slist_free (list);
1578-
1579- if (impl->shortcuts_filter_model)
1580- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model));
1581-
1582- impl->changing_folder = old_changing_folders;
1583-
1584- profile_end ("end", NULL);
1585-}
1586-
1587-/* Inserts a separator node in the shortcuts list */
1588-static void
1589-shortcuts_insert_separator (GtkFileChooserDefault *impl,
1590- ShortcutsIndex where)
1591-{
1592- GtkTreeIter iter;
1593-
1594- g_assert (where == SHORTCUTS_BOOKMARKS_SEPARATOR || where == SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
1595-
1596- gtk_list_store_insert (impl->shortcuts_model, &iter,
1597- shortcuts_get_index (impl, where));
1598- gtk_list_store_set (impl->shortcuts_model, &iter,
1599- SHORTCUTS_COL_PIXBUF, NULL,
1600- SHORTCUTS_COL_PIXBUF_VISIBLE, FALSE,
1601- SHORTCUTS_COL_NAME, NULL,
1602- SHORTCUTS_COL_DATA, NULL,
1603- -1);
1604-}
1605-
1606-/* Updates the list of bookmarks */
1607-static void
1608-shortcuts_add_bookmarks (GtkFileChooserDefault *impl)
1609-{
1610- GSList *bookmarks;
1611- gboolean old_changing_folders;
1612- GtkTreeIter iter;
1613- GtkFilePath *list_selected = NULL;
1614- GtkFilePath *combo_selected = NULL;
1615- gboolean is_volume;
1616- gpointer col_data;
1617-
1618- profile_start ("start", NULL);
1619-
1620- old_changing_folders = impl->changing_folder;
1621- impl->changing_folder = TRUE;
1622-
1623- if (shortcuts_get_selected (impl, &iter))
1624- {
1625- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model),
1626- &iter,
1627- SHORTCUTS_COL_DATA, &col_data,
1628- SHORTCUTS_COL_IS_VOLUME, &is_volume,
1629- -1);
1630-
1631- if (col_data && !is_volume)
1632- list_selected = gtk_file_path_copy (col_data);
1633- }
1634-
1635- if (impl->save_folder_combo &&
1636- gtk_combo_box_get_active_iter (GTK_COMBO_BOX (impl->save_folder_combo),
1637- &iter))
1638- {
1639- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model),
1640- &iter,
1641- SHORTCUTS_COL_DATA, &col_data,
1642- SHORTCUTS_COL_IS_VOLUME, &is_volume,
1643- -1);
1644-
1645- if (col_data && !is_volume)
1646- combo_selected = gtk_file_path_copy (col_data);
1647- }
1648-
1649- if (impl->num_bookmarks > 0)
1650- shortcuts_remove_rows (impl,
1651- shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR),
1652- impl->num_bookmarks + 1);
1653-
1654- impl->num_bookmarks = 0;
1655-
1656- bookmarks = gtk_file_system_list_bookmarks (impl->file_system);
1657- shortcuts_append_paths (impl, bookmarks);
1658- gtk_file_paths_free (bookmarks);
1659-
1660- if (impl->num_bookmarks > 0)
1661- shortcuts_insert_separator (impl, SHORTCUTS_BOOKMARKS_SEPARATOR);
1662-
1663- if (impl->shortcuts_filter_model)
1664- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model));
1665-
1666- if (list_selected)
1667- {
1668- shortcuts_find_folder (impl, list_selected);
1669- gtk_file_path_free (list_selected);
1670- }
1671-
1672- if (combo_selected)
1673- {
1674- gint pos;
1675-
1676- pos = shortcut_find_position (impl, combo_selected);
1677- if (pos != -1)
1678- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo),
1679- pos);
1680- gtk_file_path_free (combo_selected);
1681- }
1682-
1683- impl->changing_folder = old_changing_folders;
1684-
1685- profile_end ("end", NULL);
1686-}
1687-
1688-/* Appends a separator and a row to the shortcuts list for the current folder */
1689-static void
1690-shortcuts_add_current_folder (GtkFileChooserDefault *impl)
1691-{
1692- int pos;
1693- gboolean success;
1694-
1695- g_assert (!impl->shortcuts_current_folder_active);
1696-
1697- success = TRUE;
1698-
1699- g_assert (impl->current_folder != NULL);
1700-
1701- pos = shortcut_find_position (impl, impl->current_folder);
1702- if (pos == -1)
1703- {
1704- GtkFileSystemVolume *volume;
1705- GtkFilePath *base_path;
1706-
1707- /* Separator */
1708-
1709- shortcuts_insert_separator (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
1710-
1711- /* Item */
1712-
1713- pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER);
1714-
1715- volume = gtk_file_system_get_volume_for_path (impl->file_system, impl->current_folder);
1716- if (volume)
1717- base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
1718- else
1719- base_path = NULL;
1720-
1721- if (base_path &&
1722- strcmp (gtk_file_path_get_string (base_path), gtk_file_path_get_string (impl->current_folder)) == 0)
1723- {
1724- shortcuts_insert_path (impl, pos, TRUE, volume, NULL, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
1725- }
1726- else
1727- {
1728- shortcuts_insert_path (impl, pos, FALSE, NULL, impl->current_folder, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
1729- if (volume)
1730- gtk_file_system_volume_free (impl->file_system, volume);
1731- }
1732-
1733- if (base_path)
1734- gtk_file_path_free (base_path);
1735- }
1736- else if (impl->save_folder_combo != NULL)
1737- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), pos);
1738-}
1739-
1740-/* Updates the current folder row in the shortcuts model */
1741-static void
1742-shortcuts_update_current_folder (GtkFileChooserDefault *impl)
1743-{
1744- int pos;
1745-
1746- pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
1747-
1748- if (impl->shortcuts_current_folder_active)
1749- {
1750- shortcuts_remove_rows (impl, pos, 2);
1751- impl->shortcuts_current_folder_active = FALSE;
1752- }
1753-
1754- shortcuts_add_current_folder (impl);
1755-}
1756-
1757-/* Filter function used for the shortcuts filter model */
1758-static gboolean
1759-shortcuts_filter_cb (GtkTreeModel *model,
1760- GtkTreeIter *iter,
1761- gpointer data)
1762-{
1763- GtkFileChooserDefault *impl;
1764- GtkTreePath *path;
1765- int pos;
1766-
1767- impl = GTK_FILE_CHOOSER_DEFAULT (data);
1768-
1769- path = gtk_tree_model_get_path (model, iter);
1770- if (!path)
1771- return FALSE;
1772-
1773- pos = *gtk_tree_path_get_indices (path);
1774- gtk_tree_path_free (path);
1775-
1776- return (pos < shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR));
1777-}
1778-
1779-/* Creates the list model for shortcuts */
1780-static void
1781-shortcuts_model_create (GtkFileChooserDefault *impl)
1782-{
1783- /* Keep this order in sync with the SHORCUTS_COL_* enum values */
1784- impl->shortcuts_model = gtk_list_store_new (SHORTCUTS_COL_NUM_COLUMNS,
1785- GDK_TYPE_PIXBUF, /* pixbuf */
1786- G_TYPE_STRING, /* name */
1787- G_TYPE_POINTER, /* path or volume */
1788- G_TYPE_BOOLEAN, /* is the previous column a volume? */
1789- G_TYPE_BOOLEAN, /* removable */
1790- G_TYPE_BOOLEAN, /* pixbuf cell visibility */
1791- G_TYPE_POINTER); /* GtkFileSystemHandle */
1792-
1793- if (impl->file_system)
1794- {
1795- shortcuts_append_home (impl);
1796- shortcuts_append_desktop (impl);
1797- shortcuts_add_volumes (impl);
1798- }
1799-
1800- impl->shortcuts_filter_model = shortcuts_model_filter_new (impl,
1801- GTK_TREE_MODEL (impl->shortcuts_model),
1802- NULL);
1803-
1804- gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model),
1805- shortcuts_filter_cb,
1806- impl,
1807- NULL);
1808-}
1809-
1810-/* Callback used when the "New Folder" button is clicked */
1811-static void
1812-new_folder_button_clicked (GtkButton *button,
1813- GtkFileChooserDefault *impl)
1814-{
1815- GtkTreeIter iter;
1816- GtkTreePath *path;
1817-
1818- if (!impl->browse_files_model)
1819- return; /* FIXME: this sucks. Disable the New Folder button or something. */
1820-
1821- /* Prevent button from being clicked twice */
1822- gtk_widget_set_sensitive (impl->browse_new_folder_button, FALSE);
1823-
1824- _gtk_file_system_model_add_editable (impl->browse_files_model, &iter);
1825-
1826- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->browse_files_model), &iter);
1827- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->browse_files_tree_view),
1828- path, impl->list_name_column,
1829- FALSE, 0.0, 0.0);
1830-
1831- g_object_set (impl->list_name_renderer, "editable", TRUE, NULL);
1832- gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view),
1833- path,
1834- impl->list_name_column,
1835- TRUE);
1836-
1837- gtk_tree_path_free (path);
1838-}
1839-
1840-static void
1841-edited_idle_create_folder_cb (GtkFileSystemHandle *handle,
1842- const GtkFilePath *path,
1843- const GError *error,
1844- gpointer data)
1845-{
1846- gboolean cancelled = handle->cancelled;
1847- GtkFileChooserDefault *impl = data;
1848-
1849- if (!g_slist_find (impl->pending_handles, handle))
1850- goto out;
1851-
1852- impl->pending_handles = g_slist_remove (impl->pending_handles, handle);
1853-
1854- if (cancelled)
1855- goto out;
1856-
1857- if (!error)
1858- change_folder_and_display_error (impl, path, FALSE);
1859- else
1860- error_creating_folder_dialog (impl, path, g_error_copy (error));
1861-
1862- out:
1863- g_object_unref (impl);
1864- g_object_unref (handle);
1865-}
1866-
1867-/* Idle handler for creating a new folder after editing its name cell, or for
1868- * canceling the editing.
1869- */
1870-static gboolean
1871-edited_idle_cb (GtkFileChooserDefault *impl)
1872-{
1873- GDK_THREADS_ENTER ();
1874-
1875- g_source_destroy (impl->edited_idle);
1876- impl->edited_idle = NULL;
1877-
1878- _gtk_file_system_model_remove_editable (impl->browse_files_model);
1879- g_object_set (impl->list_name_renderer, "editable", FALSE, NULL);
1880-
1881- gtk_widget_set_sensitive (impl->browse_new_folder_button, TRUE);
1882-
1883- if (impl->edited_new_text) /* not cancelled? */
1884- {
1885- GError *error;
1886- GtkFilePath *file_path;
1887-
1888- error = NULL;
1889- file_path = gtk_file_system_make_path (impl->file_system,
1890- impl->current_folder,
1891- impl->edited_new_text,
1892- &error);
1893- if (file_path)
1894- {
1895- GtkFileSystemHandle *handle;
1896-
1897- handle = gtk_file_system_create_folder (impl->file_system, file_path,
1898- edited_idle_create_folder_cb,
1899- g_object_ref (impl));
1900- impl->pending_handles = g_slist_append (impl->pending_handles, handle);
1901-
1902- gtk_file_path_free (file_path);
1903- }
1904- else
1905- error_creating_folder_dialog (impl, file_path, error);
1906-
1907- g_free (impl->edited_new_text);
1908- impl->edited_new_text = NULL;
1909- }
1910-
1911- GDK_THREADS_LEAVE ();
1912-
1913- return FALSE;
1914-}
1915-
1916-static void
1917-queue_edited_idle (GtkFileChooserDefault *impl,
1918- const gchar *new_text)
1919-{
1920- /* We create the folder in an idle handler so that we don't modify the tree
1921- * just now.
1922- */
1923-
1924- if (!impl->edited_idle)
1925- {
1926- impl->edited_idle = g_idle_source_new ();
1927- g_source_set_closure (impl->edited_idle,
1928- g_cclosure_new_object (G_CALLBACK (edited_idle_cb),
1929- G_OBJECT (impl)));
1930- g_source_attach (impl->edited_idle, NULL);
1931- }
1932-
1933- g_free (impl->edited_new_text);
1934- impl->edited_new_text = g_strdup (new_text);
1935-}
1936-
1937-/* Callback used from the text cell renderer when the new folder is named */
1938-static void
1939-renderer_edited_cb (GtkCellRendererText *cell_renderer_text,
1940- const gchar *path,
1941- const gchar *new_text,
1942- GtkFileChooserDefault *impl)
1943-{
1944- /* work around bug #154921 */
1945- g_object_set (cell_renderer_text,
1946- "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
1947- queue_edited_idle (impl, new_text);
1948-}
1949-
1950-/* Callback used from the text cell renderer when the new folder edition gets
1951- * canceled.
1952- */
1953-static void
1954-renderer_editing_canceled_cb (GtkCellRendererText *cell_renderer_text,
1955- GtkFileChooserDefault *impl)
1956-{
1957- /* work around bug #154921 */
1958- g_object_set (cell_renderer_text,
1959- "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
1960- queue_edited_idle (impl, NULL);
1961-}
1962-
1963-/* Creates the widgets for the filter combo box */
1964-static GtkWidget *
1965-filter_create (GtkFileChooserDefault *impl)
1966-{
1967- impl->filter_combo = gtk_combo_box_new_text ();
1968- gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (impl->filter_combo), FALSE);
1969-
1970- g_signal_connect (impl->filter_combo, "changed",
1971- G_CALLBACK (filter_combo_changed), impl);
1972-
1973- return impl->filter_combo;
1974-}
1975-
1976-static GtkWidget *
1977-button_new (GtkFileChooserDefault *impl,
1978- const char *text,
1979- const char *stock_id,
1980- gboolean sensitive,
1981- gboolean show,
1982- GCallback callback)
1983-{
1984- GtkWidget *button;
1985- GtkWidget *image;
1986-
1987- button = gtk_button_new_with_mnemonic (text);
1988- image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
1989- gtk_button_set_image (GTK_BUTTON (button), image);
1990-
1991- gtk_widget_set_sensitive (button, sensitive);
1992- g_signal_connect (button, "clicked", callback, impl);
1993-
1994- if (show)
1995- gtk_widget_show (button);
1996-
1997- return button;
1998-}
1999-
2000-/* Looks for a path among the shortcuts; returns its index or -1 if it doesn't exist */
2001-static int
2002-shortcut_find_position (GtkFileChooserDefault *impl,
2003- const GtkFilePath *path)
2004-{
2005- GtkTreeIter iter;
2006- int i;
2007- int current_folder_separator_idx;
2008-
2009- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
2010- return -1;
2011-
2012- current_folder_separator_idx = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
2013-
2014-#if 0
2015- /* FIXME: is this still needed? */
2016- if (current_folder_separator_idx >= impl->shortcuts_model->length)
2017- return -1;
2018-#endif
2019-
2020- for (i = 0; i < current_folder_separator_idx; i++)
2021- {
2022- gpointer col_data;
2023- gboolean is_volume;
2024-
2025- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2026- SHORTCUTS_COL_DATA, &col_data,
2027- SHORTCUTS_COL_IS_VOLUME, &is_volume,
2028- -1);
2029-
2030- if (col_data)
2031- {
2032- if (is_volume)
2033- {
2034- GtkFileSystemVolume *volume;
2035- GtkFilePath *base_path;
2036- gboolean exists;
2037-
2038- volume = col_data;
2039- base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
2040-
2041- exists = base_path && strcmp (gtk_file_path_get_string (path),
2042- gtk_file_path_get_string (base_path)) == 0;
2043- g_free (base_path);
2044-
2045- if (exists)
2046- return i;
2047- }
2048- else
2049- {
2050- GtkFilePath *model_path;
2051-
2052- model_path = col_data;
2053-
2054- if (model_path && gtk_file_path_compare (model_path, path) == 0)
2055- return i;
2056- }
2057- }
2058-
2059- if (i < current_folder_separator_idx - 1)
2060- {
2061- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
2062- g_assert_not_reached ();
2063- }
2064- }
2065-
2066- return -1;
2067-}
2068-
2069-/* Tries to add a bookmark from a path name */
2070-static gboolean
2071-shortcuts_add_bookmark_from_path (GtkFileChooserDefault *impl,
2072- const GtkFilePath *path,
2073- int pos)
2074-{
2075- GError *error;
2076-
2077- g_return_val_if_fail (path != NULL, FALSE);
2078-
2079- if (shortcut_find_position (impl, path) != -1)
2080- return FALSE;
2081-
2082- error = NULL;
2083- if (!gtk_file_system_insert_bookmark (impl->file_system, path, pos, &error))
2084- {
2085- error_adding_bookmark_dialog (impl, path, error);
2086- return FALSE;
2087- }
2088-
2089- return TRUE;
2090-}
2091-
2092-static void
2093-add_bookmark_foreach_cb (GtkTreeModel *model,
2094- GtkTreePath *path,
2095- GtkTreeIter *iter,
2096- gpointer data)
2097-{
2098- GtkFileChooserDefault *impl;
2099- GtkFileSystemModel *fs_model;
2100- GtkTreeIter child_iter;
2101- const GtkFilePath *file_path;
2102-
2103- impl = (GtkFileChooserDefault *) data;
2104-
2105- fs_model = impl->browse_files_model;
2106- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, iter);
2107-
2108- file_path = _gtk_file_system_model_get_path (fs_model, &child_iter);
2109- shortcuts_add_bookmark_from_path (impl, file_path, -1);
2110-}
2111-
2112-/* Adds a bookmark from the currently selected item in the file list */
2113-static void
2114-bookmarks_add_selected_folder (GtkFileChooserDefault *impl)
2115-{
2116- GtkTreeSelection *selection;
2117-
2118- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
2119-
2120- if (gtk_tree_selection_count_selected_rows (selection) == 0)
2121- shortcuts_add_bookmark_from_path (impl, impl->current_folder, -1);
2122- else
2123- gtk_tree_selection_selected_foreach (selection,
2124- add_bookmark_foreach_cb,
2125- impl);
2126-}
2127-
2128-/* Callback used when the "Add bookmark" button is clicked */
2129-static void
2130-add_bookmark_button_clicked_cb (GtkButton *button,
2131- GtkFileChooserDefault *impl)
2132-{
2133- bookmarks_add_selected_folder (impl);
2134-}
2135-
2136-/* Returns TRUE plus an iter in the shortcuts_model if a row is selected;
2137- * returns FALSE if no shortcut is selected.
2138- */
2139-static gboolean
2140-shortcuts_get_selected (GtkFileChooserDefault *impl,
2141- GtkTreeIter *iter)
2142-{
2143- GtkTreeSelection *selection;
2144- GtkTreeIter parent_iter;
2145-
2146- if (!impl->browse_shortcuts_tree_view)
2147- return FALSE;
2148-
2149- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
2150-
2151- if (!gtk_tree_selection_get_selected (selection, NULL, &parent_iter))
2152- return FALSE;
2153-
2154- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model),
2155- iter,
2156- &parent_iter);
2157- return TRUE;
2158-}
2159-
2160-/* Removes the selected bookmarks */
2161-static void
2162-remove_selected_bookmarks (GtkFileChooserDefault *impl)
2163-{
2164- GtkTreeIter iter;
2165- gpointer col_data;
2166- GtkFilePath *path;
2167- gboolean removable;
2168- GError *error;
2169-
2170- if (!shortcuts_get_selected (impl, &iter))
2171- return;
2172-
2173- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2174- SHORTCUTS_COL_DATA, &col_data,
2175- SHORTCUTS_COL_REMOVABLE, &removable,
2176- -1);
2177- g_assert (col_data != NULL);
2178-
2179- if (!removable)
2180- return;
2181-
2182- path = col_data;
2183-
2184- error = NULL;
2185- if (!gtk_file_system_remove_bookmark (impl->file_system, path, &error))
2186- error_removing_bookmark_dialog (impl, path, error);
2187-}
2188-
2189-/* Callback used when the "Remove bookmark" button is clicked */
2190-static void
2191-remove_bookmark_button_clicked_cb (GtkButton *button,
2192- GtkFileChooserDefault *impl)
2193-{
2194- remove_selected_bookmarks (impl);
2195-}
2196-
2197-struct selection_check_closure {
2198- GtkFileChooserDefault *impl;
2199- int num_selected;
2200- gboolean all_files;
2201- gboolean all_folders;
2202-};
2203-
2204-/* Used from gtk_tree_selection_selected_foreach() */
2205-static void
2206-selection_check_foreach_cb (GtkTreeModel *model,
2207- GtkTreePath *path,
2208- GtkTreeIter *iter,
2209- gpointer data)
2210-{
2211- struct selection_check_closure *closure;
2212- GtkTreeIter child_iter;
2213- const GtkFileInfo *info;
2214- gboolean is_folder;
2215-
2216- closure = data;
2217- closure->num_selected++;
2218-
2219- gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter);
2220-
2221- info = _gtk_file_system_model_get_info (closure->impl->browse_files_model, &child_iter);
2222- is_folder = info ? gtk_file_info_get_is_folder (info) : FALSE;
2223-
2224- closure->all_folders = closure->all_folders && is_folder;
2225- closure->all_files = closure->all_files && !is_folder;
2226-}
2227-
2228-/* Checks whether the selected items in the file list are all files or all folders */
2229-static void
2230-selection_check (GtkFileChooserDefault *impl,
2231- gint *num_selected,
2232- gboolean *all_files,
2233- gboolean *all_folders)
2234-{
2235- struct selection_check_closure closure;
2236- GtkTreeSelection *selection;
2237-
2238- closure.impl = impl;
2239- closure.num_selected = 0;
2240- closure.all_files = TRUE;
2241- closure.all_folders = TRUE;
2242-
2243- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
2244- gtk_tree_selection_selected_foreach (selection,
2245- selection_check_foreach_cb,
2246- &closure);
2247-
2248- g_assert (closure.num_selected == 0 || !(closure.all_files && closure.all_folders));
2249-
2250- if (num_selected)
2251- *num_selected = closure.num_selected;
2252-
2253- if (all_files)
2254- *all_files = closure.all_files;
2255-
2256- if (all_folders)
2257- *all_folders = closure.all_folders;
2258-}
2259-
2260-struct get_selected_path_closure {
2261- GtkFileChooserDefault *impl;
2262- const GtkFilePath *path;
2263-};
2264-
2265-static void
2266-get_selected_path_foreach_cb (GtkTreeModel *model,
2267- GtkTreePath *path,
2268- GtkTreeIter *iter,
2269- gpointer data)
2270-{
2271- struct get_selected_path_closure *closure;
2272- GtkTreeIter child_iter;
2273-
2274- closure = data;
2275-
2276- gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter);
2277- closure->path = _gtk_file_system_model_get_path (closure->impl->browse_files_model, &child_iter);
2278-}
2279-
2280-/* Returns a selected path from the file list */
2281-static const GtkFilePath *
2282-get_selected_path (GtkFileChooserDefault *impl)
2283-{
2284- struct get_selected_path_closure closure;
2285- GtkTreeSelection *selection;
2286-
2287- closure.impl = impl;
2288- closure.path = NULL;
2289-
2290- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
2291- gtk_tree_selection_selected_foreach (selection,
2292- get_selected_path_foreach_cb,
2293- &closure);
2294-
2295- return closure.path;
2296-}
2297-
2298-typedef struct {
2299- GtkFileChooserDefault *impl;
2300- gchar *tip;
2301-} UpdateTooltipData;
2302-
2303-static void
2304-update_tooltip (GtkTreeModel *model,
2305- GtkTreePath *path,
2306- GtkTreeIter *iter,
2307- gpointer data)
2308-{
2309- UpdateTooltipData *udata = data;
2310- GtkTreeIter child_iter;
2311- const GtkFileInfo *info;
2312-
2313- if (udata->tip == NULL)
2314- {
2315- gtk_tree_model_sort_convert_iter_to_child_iter (udata->impl->sort_model,
2316- &child_iter,
2317- iter);
2318-
2319- info = _gtk_file_system_model_get_info (udata->impl->browse_files_model, &child_iter);
2320- udata->tip = g_strdup_printf (_("Add the folder '%s' to the bookmarks"),
2321- gtk_file_info_get_display_name (info));
2322- }
2323-}
2324-
2325-
2326-/* Sensitize the "add bookmark" button if all the selected items are folders, or
2327- * if there are no selected items *and* the current folder is not in the
2328- * bookmarks list. De-sensitize the button otherwise.
2329- */
2330-static void
2331-bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl)
2332-{
2333- gint num_selected;
2334- gboolean all_folders;
2335- gboolean active;
2336- gchar *tip;
2337-
2338- selection_check (impl, &num_selected, NULL, &all_folders);
2339-
2340- if (num_selected == 0)
2341- active = (impl->current_folder != NULL) && (shortcut_find_position (impl, impl->current_folder) == -1);
2342- else if (num_selected == 1)
2343- {
2344- const GtkFilePath *path;
2345-
2346- path = get_selected_path (impl);
2347- active = all_folders && (shortcut_find_position (impl, path) == -1);
2348- }
2349- else
2350- active = all_folders;
2351-
2352- gtk_widget_set_sensitive (impl->browse_shortcuts_add_button, active);
2353-
2354- if (impl->browse_files_popup_menu_add_shortcut_item)
2355- gtk_widget_set_sensitive (impl->browse_files_popup_menu_add_shortcut_item,
2356- (num_selected == 0) ? FALSE : active);
2357-
2358- if (active)
2359- {
2360- if (num_selected == 0)
2361- tip = g_strdup_printf (_("Add the current folder to the bookmarks"));
2362- else if (num_selected > 1)
2363- tip = g_strdup_printf (_("Add the selected folders to the bookmarks"));
2364- else
2365- {
2366- GtkTreeSelection *selection;
2367- UpdateTooltipData data;
2368-
2369- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
2370- data.impl = impl;
2371- data.tip = NULL;
2372- gtk_tree_selection_selected_foreach (selection, update_tooltip, &data);
2373- tip = data.tip;
2374-
2375- }
2376- gtk_tooltips_set_tip (impl->tooltips, impl->browse_shortcuts_add_button, tip, NULL);
2377- g_free (tip);
2378- }
2379-}
2380-
2381-/* Sets the sensitivity of the "remove bookmark" button depending on whether a
2382- * bookmark row is selected in the shortcuts tree.
2383- */
2384-static void
2385-bookmarks_check_remove_sensitivity (GtkFileChooserDefault *impl)
2386-{
2387- GtkTreeIter iter;
2388- gboolean removable = FALSE;
2389- gchar *name = NULL;
2390-
2391- if (shortcuts_get_selected (impl, &iter))
2392- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2393- SHORTCUTS_COL_REMOVABLE, &removable,
2394- SHORTCUTS_COL_NAME, &name,
2395- -1);
2396-
2397- gtk_widget_set_sensitive (impl->browse_shortcuts_remove_button, removable);
2398-
2399- if (removable)
2400- {
2401- gchar *tip;
2402-
2403- tip = g_strdup_printf (_("Remove the bookmark '%s'"), name);
2404- gtk_tooltips_set_tip (impl->tooltips, impl->browse_shortcuts_remove_button,
2405- tip, NULL);
2406- g_free (tip);
2407- }
2408-
2409- g_free (name);
2410-}
2411-
2412-static void
2413-shortcuts_check_popup_sensitivity (GtkFileChooserDefault *impl)
2414-{
2415- GtkTreeIter iter;
2416- gboolean removable = FALSE;
2417-
2418- if (impl->browse_shortcuts_popup_menu == NULL)
2419- return;
2420-
2421- if (shortcuts_get_selected (impl, &iter))
2422- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2423- SHORTCUTS_COL_REMOVABLE, &removable,
2424- -1);
2425-
2426- gtk_widget_set_sensitive (impl->browse_shortcuts_popup_menu_remove_item, removable);
2427- gtk_widget_set_sensitive (impl->browse_shortcuts_popup_menu_rename_item, removable);
2428-}
2429-
2430-/* GtkWidget::drag-begin handler for the shortcuts list. */
2431-static void
2432-shortcuts_drag_begin_cb (GtkWidget *widget,
2433- GdkDragContext *context,
2434- GtkFileChooserDefault *impl)
2435-{
2436-#if 0
2437- impl->shortcuts_drag_context = g_object_ref (context);
2438-#endif
2439-}
2440-
2441-#if 0
2442-/* Removes the idle handler for outside drags */
2443-static void
2444-shortcuts_cancel_drag_outside_idle (GtkFileChooserDefault *impl)
2445-{
2446- if (!impl->shortcuts_drag_outside_idle)
2447- return;
2448-
2449- g_source_destroy (impl->shortcuts_drag_outside_idle);
2450- impl->shortcuts_drag_outside_idle = NULL;
2451-}
2452-#endif
2453-
2454-/* GtkWidget::drag-end handler for the shortcuts list. */
2455-static void
2456-shortcuts_drag_end_cb (GtkWidget *widget,
2457- GdkDragContext *context,
2458- GtkFileChooserDefault *impl)
2459-{
2460-#if 0
2461- g_object_unref (impl->shortcuts_drag_context);
2462-
2463- shortcuts_cancel_drag_outside_idle (impl);
2464-
2465- if (!impl->shortcuts_drag_outside)
2466- return;
2467-
2468- gtk_button_clicked (GTK_BUTTON (impl->browse_shortcuts_remove_button));
2469-
2470- impl->shortcuts_drag_outside = FALSE;
2471-#endif
2472-}
2473-
2474-/* GtkWidget::drag-data-delete handler for the shortcuts list. */
2475-static void
2476-shortcuts_drag_data_delete_cb (GtkWidget *widget,
2477- GdkDragContext *context,
2478- GtkFileChooserDefault *impl)
2479-{
2480- g_signal_stop_emission_by_name (widget, "drag_data_delete");
2481-}
2482-
2483-#if 0
2484-/* Creates a suitable drag cursor to indicate that the selected bookmark will be
2485- * deleted or not.
2486- */
2487-static void
2488-shortcuts_drag_set_delete_cursor (GtkFileChooserDefault *impl,
2489- gboolean delete)
2490-{
2491- GtkTreeView *tree_view;
2492- GtkTreeIter iter;
2493- GtkTreePath *path;
2494- GdkPixmap *row_pixmap;
2495- GdkBitmap *mask;
2496- int row_pixmap_y;
2497- int cell_y;
2498-
2499- tree_view = GTK_TREE_VIEW (impl->browse_shortcuts_tree_view);
2500-
2501- /* Find the selected path and get its drag pixmap */
2502-
2503- if (!shortcuts_get_selected (impl, &iter))
2504- g_assert_not_reached ();
2505-
2506- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
2507-
2508- row_pixmap = gtk_tree_view_create_row_drag_icon (tree_view, path);
2509- gtk_tree_path_free (path);
2510-
2511- mask = NULL;
2512- row_pixmap_y = 0;
2513-
2514- if (delete)
2515- {
2516- GdkPixbuf *pixbuf;
2517-
2518- pixbuf = gtk_widget_render_icon (impl->browse_shortcuts_tree_view,
2519- GTK_STOCK_DELETE,
2520- GTK_ICON_SIZE_DND,
2521- NULL);
2522- if (pixbuf)
2523- {
2524- GdkPixmap *composite;
2525- int row_pixmap_width, row_pixmap_height;
2526- int pixbuf_width, pixbuf_height;
2527- int composite_width, composite_height;
2528- int pixbuf_x, pixbuf_y;
2529- GdkGC *gc, *mask_gc;
2530- GdkColor color;
2531- GdkBitmap *pixbuf_mask;
2532-
2533- /* Create pixmap and mask for composite image */
2534-
2535- gdk_drawable_get_size (row_pixmap, &row_pixmap_width, &row_pixmap_height);
2536- pixbuf_width = gdk_pixbuf_get_width (pixbuf);
2537- pixbuf_height = gdk_pixbuf_get_height (pixbuf);
2538-
2539- composite_width = MAX (row_pixmap_width, pixbuf_width);
2540- composite_height = MAX (row_pixmap_height, pixbuf_height);
2541-
2542- row_pixmap_y = (composite_height - row_pixmap_height) / 2;
2543-
2544- if (gtk_widget_get_direction (impl->browse_shortcuts_tree_view) == GTK_TEXT_DIR_RTL)
2545- pixbuf_x = 0;
2546- else
2547- pixbuf_x = composite_width - pixbuf_width;
2548-
2549- pixbuf_y = (composite_height - pixbuf_height) / 2;
2550-
2551- composite = gdk_pixmap_new (row_pixmap, composite_width, composite_height, -1);
2552- gc = gdk_gc_new (composite);
2553-
2554- mask = gdk_pixmap_new (row_pixmap, composite_width, composite_height, 1);
2555- mask_gc = gdk_gc_new (mask);
2556- color.pixel = 0;
2557- gdk_gc_set_foreground (mask_gc, &color);
2558- gdk_draw_rectangle (mask, mask_gc, TRUE, 0, 0, composite_width, composite_height);
2559-
2560- color.red = 0xffff;
2561- color.green = 0xffff;
2562- color.blue = 0xffff;
2563- gdk_gc_set_rgb_fg_color (gc, &color);
2564- gdk_draw_rectangle (composite, gc, TRUE, 0, 0, composite_width, composite_height);
2565-
2566- /* Composite the row pixmap and the pixbuf */
2567-
2568- gdk_pixbuf_render_pixmap_and_mask_for_colormap
2569- (pixbuf,
2570- gtk_widget_get_colormap (impl->browse_shortcuts_tree_view),
2571- NULL, &pixbuf_mask, 128);
2572- gdk_draw_drawable (mask, mask_gc, pixbuf_mask,
2573- 0, 0,
2574- pixbuf_x, pixbuf_y,
2575- pixbuf_width, pixbuf_height);
2576- g_object_unref (pixbuf_mask);
2577-
2578- gdk_draw_drawable (composite, gc, row_pixmap,
2579- 0, 0,
2580- 0, row_pixmap_y,
2581- row_pixmap_width, row_pixmap_height);
2582- color.pixel = 1;
2583- gdk_gc_set_foreground (mask_gc, &color);
2584- gdk_draw_rectangle (mask, mask_gc, TRUE, 0, row_pixmap_y, row_pixmap_width, row_pixmap_height);
2585-
2586- gdk_draw_pixbuf (composite, gc, pixbuf,
2587- 0, 0,
2588- pixbuf_x, pixbuf_y,
2589- pixbuf_width, pixbuf_height,
2590- GDK_RGB_DITHER_MAX,
2591- 0, 0);
2592-
2593- g_object_unref (pixbuf);
2594- g_object_unref (row_pixmap);
2595-
2596- row_pixmap = composite;
2597- }
2598- }
2599-
2600- /* The hotspot offsets here are copied from gtk_tree_view_drag_begin(), ugh */
2601-
2602- gtk_tree_view_get_path_at_pos (tree_view,
2603- tree_view->priv->press_start_x,
2604- tree_view->priv->press_start_y,
2605- NULL,
2606- NULL,
2607- NULL,
2608- &cell_y);
2609-
2610- gtk_drag_set_icon_pixmap (impl->shortcuts_drag_context,
2611- gdk_drawable_get_colormap (row_pixmap),
2612- row_pixmap,
2613- mask,
2614- tree_view->priv->press_start_x + 1,
2615- row_pixmap_y + cell_y + 1);
2616-
2617- g_object_unref (row_pixmap);
2618- if (mask)
2619- g_object_unref (mask);
2620-}
2621-
2622-/* We set the delete cursor and the shortcuts_drag_outside flag in an idle
2623- * handler so that we can tell apart the drag_leave event that comes right
2624- * before a drag_drop, from a normal drag_leave. We don't want to set the
2625- * cursor nor the flag in the latter case.
2626- */
2627-static gboolean
2628-shortcuts_drag_outside_idle_cb (GtkFileChooserDefault *impl)
2629-{
2630- GDK_THREADS_ENTER ();
2631-
2632- shortcuts_drag_set_delete_cursor (impl, TRUE);
2633- impl->shortcuts_drag_outside = TRUE;
2634-
2635- shortcuts_cancel_drag_outside_idle (impl);
2636-
2637- GDK_THREADS_LEAVE ();
2638-
2639- return FALSE;
2640-}
2641-#endif
2642-
2643-/* GtkWidget::drag-leave handler for the shortcuts list. We unhighlight the
2644- * drop position.
2645- */
2646-static void
2647-shortcuts_drag_leave_cb (GtkWidget *widget,
2648- GdkDragContext *context,
2649- guint time_,
2650- GtkFileChooserDefault *impl)
2651-{
2652-#if 0
2653- if (gtk_drag_get_source_widget (context) == widget && !impl->shortcuts_drag_outside_idle)
2654- {
2655- impl->shortcuts_drag_outside_idle = g_idle_source_new ();
2656- g_source_set_closure (impl->shortcuts_drag_outside_idle,
2657- g_cclosure_new_object (G_CALLBACK (shortcuts_drag_outside_idle_cb),
2658- G_OBJECT (impl)));
2659- g_source_attach (impl->shortcuts_drag_outside_idle, NULL);
2660- }
2661-#endif
2662-
2663- gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
2664- NULL,
2665- GTK_TREE_VIEW_DROP_BEFORE);
2666-
2667- g_signal_stop_emission_by_name (widget, "drag_leave");
2668-}
2669-
2670-/* Computes the appropriate row and position for dropping */
2671-static void
2672-shortcuts_compute_drop_position (GtkFileChooserDefault *impl,
2673- int x,
2674- int y,
2675- GtkTreePath **path,
2676- GtkTreeViewDropPosition *pos)
2677-{
2678- GtkTreeView *tree_view;
2679- GtkTreeViewColumn *column;
2680- int cell_y;
2681- GdkRectangle cell;
2682- int row;
2683- int bookmarks_index;
2684-
2685- tree_view = GTK_TREE_VIEW (impl->browse_shortcuts_tree_view);
2686-
2687- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS);
2688-
2689- if (!gtk_tree_view_get_path_at_pos (tree_view,
2690- x,
2691- y - TREE_VIEW_HEADER_HEIGHT (tree_view),
2692- path,
2693- &column,
2694- NULL,
2695- &cell_y))
2696- {
2697- row = bookmarks_index + impl->num_bookmarks - 1;
2698- *path = gtk_tree_path_new_from_indices (row, -1);
2699- *pos = GTK_TREE_VIEW_DROP_AFTER;
2700- return;
2701- }
2702-
2703- row = *gtk_tree_path_get_indices (*path);
2704- gtk_tree_view_get_background_area (tree_view, *path, column, &cell);
2705- gtk_tree_path_free (*path);
2706-
2707- if (row < bookmarks_index)
2708- {
2709- row = bookmarks_index;
2710- *pos = GTK_TREE_VIEW_DROP_BEFORE;
2711- }
2712- else if (row > bookmarks_index + impl->num_bookmarks - 1)
2713- {
2714- row = bookmarks_index + impl->num_bookmarks - 1;
2715- *pos = GTK_TREE_VIEW_DROP_AFTER;
2716- }
2717- else
2718- {
2719- if (cell_y < cell.height / 2)
2720- *pos = GTK_TREE_VIEW_DROP_BEFORE;
2721- else
2722- *pos = GTK_TREE_VIEW_DROP_AFTER;
2723- }
2724-
2725- *path = gtk_tree_path_new_from_indices (row, -1);
2726-}
2727-
2728-/* GtkWidget::drag-motion handler for the shortcuts list. We basically
2729- * implement the destination side of DnD by hand, due to limitations in
2730- * GtkTreeView's DnD API.
2731+/* Idle handler for creating a new folder after editing its name cell, or for
2732+ * canceling the editing.
2733 */
2734 static gboolean
2735-shortcuts_drag_motion_cb (GtkWidget *widget,
2736- GdkDragContext *context,
2737- gint x,
2738- gint y,
2739- guint time_,
2740- GtkFileChooserDefault *impl)
2741-{
2742- GtkTreePath *path;
2743- GtkTreeViewDropPosition pos;
2744- GdkDragAction action;
2745-
2746-#if 0
2747- if (gtk_drag_get_source_widget (context) == widget)
2748- {
2749- shortcuts_cancel_drag_outside_idle (impl);
2750-
2751- if (impl->shortcuts_drag_outside)
2752- {
2753- shortcuts_drag_set_delete_cursor (impl, FALSE);
2754- impl->shortcuts_drag_outside = FALSE;
2755- }
2756- }
2757-#endif
2758-
2759- if (context->suggested_action == GDK_ACTION_COPY || (context->actions & GDK_ACTION_COPY) != 0)
2760- action = GDK_ACTION_COPY;
2761- else if (context->suggested_action == GDK_ACTION_MOVE || (context->actions & GDK_ACTION_MOVE) != 0)
2762- action = GDK_ACTION_MOVE;
2763- else
2764- {
2765- action = 0;
2766- goto out;
2767- }
2768-
2769- shortcuts_compute_drop_position (impl, x, y, &path, &pos);
2770- gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), path, pos);
2771- gtk_tree_path_free (path);
2772-
2773- out:
2774-
2775- g_signal_stop_emission_by_name (widget, "drag_motion");
2776-
2777- if (action != 0)
2778- {
2779- gdk_drag_status (context, action, time_);
2780- return TRUE;
2781- }
2782- else
2783- return FALSE;
2784-}
2785-
2786-/* GtkWidget::drag-drop handler for the shortcuts list. */
2787-static gboolean
2788-shortcuts_drag_drop_cb (GtkWidget *widget,
2789- GdkDragContext *context,
2790- gint x,
2791- gint y,
2792- guint time_,
2793- GtkFileChooserDefault *impl)
2794+edited_idle_cb (GtkFileChooserDefault *impl)
2795 {
2796-#if 0
2797- shortcuts_cancel_drag_outside_idle (impl);
2798-#endif
2799+ GDK_THREADS_ENTER ();
2800
2801- g_signal_stop_emission_by_name (widget, "drag_drop");
2802- return TRUE;
2803-}
2804+ g_source_destroy (impl->edited_idle);
2805+ impl->edited_idle = NULL;
2806
2807-/* Parses a "text/uri-list" string and inserts its URIs as bookmarks */
2808-static void
2809-shortcuts_drop_uris (GtkFileChooserDefault *impl,
2810- const char *data,
2811- int position)
2812-{
2813- gchar **uris;
2814- gint i;
2815+ _gtk_file_system_model_remove_editable (impl->browse_files_model);
2816+ g_object_set (impl->list_name_renderer, "editable", FALSE, NULL);
2817
2818- uris = g_uri_list_extract_uris (data);
2819+ gtk_widget_set_sensitive (impl->browse_new_folder_button, TRUE);
2820
2821- for (i = 0; uris[i]; i++)
2822+ if (impl->edited_new_text) /* not cancelled? */
2823 {
2824- char *uri;
2825- GtkFilePath *path;
2826-
2827- uri = uris[i];
2828- path = gtk_file_system_uri_to_path (impl->file_system, uri);
2829+ GError *error;
2830+ GtkFilePath *file_path;
2831
2832- if (path)
2833+ error = NULL;
2834+ file_path = gtk_file_system_make_path (impl->file_system,
2835+ impl->current_folder,
2836+ impl->edited_new_text,
2837+ &error);
2838+ if (file_path)
2839 {
2840- if (shortcuts_add_bookmark_from_path (impl, path, position))
2841- position++;
2842+ GtkFileSystemHandle *handle;
2843
2844- gtk_file_path_free (path);
2845- }
2846- else
2847- {
2848- GError *error;
2849+ handle = gtk_file_system_create_folder (impl->file_system, file_path,
2850+ edited_idle_create_folder_cb,
2851+ g_object_ref (impl));
2852+ impl->pending_handles = g_slist_append (impl->pending_handles, handle);
2853
2854- g_set_error (&error,
2855- GTK_FILE_CHOOSER_ERROR,
2856- GTK_FILE_CHOOSER_ERROR_BAD_FILENAME,
2857- _("Could not add a bookmark for '%s' "
2858- "because it is an invalid path name."),
2859- uri);
2860- error_adding_bookmark_dialog (impl, path, error);
2861+ gtk_file_path_free (file_path);
2862 }
2863- }
2864-
2865- g_strfreev (uris);
2866-}
2867-
2868-/* Reorders the selected bookmark to the specified position */
2869-static void
2870-shortcuts_reorder (GtkFileChooserDefault *impl,
2871- int new_position)
2872-{
2873- GtkTreeIter iter;
2874- gpointer col_data;
2875- gboolean is_volume;
2876- GtkTreePath *path;
2877- int old_position;
2878- int bookmarks_index;
2879- const GtkFilePath *file_path;
2880- GtkFilePath *file_path_copy;
2881- GError *error;
2882- gchar *name;
2883-
2884- /* Get the selected path */
2885-
2886- if (!shortcuts_get_selected (impl, &iter))
2887- g_assert_not_reached ();
2888-
2889- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
2890- old_position = *gtk_tree_path_get_indices (path);
2891- gtk_tree_path_free (path);
2892-
2893- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS);
2894- old_position -= bookmarks_index;
2895- g_assert (old_position >= 0 && old_position < impl->num_bookmarks);
2896-
2897- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2898- SHORTCUTS_COL_NAME, &name,
2899- SHORTCUTS_COL_DATA, &col_data,
2900- SHORTCUTS_COL_IS_VOLUME, &is_volume,
2901- -1);
2902- g_assert (col_data != NULL);
2903- g_assert (!is_volume);
2904-
2905- file_path = col_data;
2906- file_path_copy = gtk_file_path_copy (file_path); /* removal below will free file_path, so we need a copy */
2907-
2908- /* Remove the path from the old position and insert it in the new one */
2909-
2910- if (new_position > old_position)
2911- new_position--;
2912-
2913- if (old_position == new_position)
2914- goto out;
2915+ else
2916+ error_creating_folder_dialog (impl, file_path, error);
2917
2918- error = NULL;
2919- if (gtk_file_system_remove_bookmark (impl->file_system, file_path_copy, &error))
2920- {
2921- shortcuts_add_bookmark_from_path (impl, file_path_copy, new_position);
2922- gtk_file_system_set_bookmark_label (impl->file_system, file_path_copy, name);
2923+ g_free (impl->edited_new_text);
2924+ impl->edited_new_text = NULL;
2925 }
2926- else
2927- error_adding_bookmark_dialog (impl, file_path_copy, error);
2928-
2929- out:
2930-
2931- gtk_file_path_free (file_path_copy);
2932-}
2933-
2934-/* Callback used when we get the drag data for the bookmarks list. We add the
2935- * received URIs as bookmarks if they are folders.
2936- */
2937-static void
2938-shortcuts_drag_data_received_cb (GtkWidget *widget,
2939- GdkDragContext *context,
2940- gint x,
2941- gint y,
2942- GtkSelectionData *selection_data,
2943- guint info,
2944- guint time_,
2945- gpointer data)
2946-{
2947- GtkFileChooserDefault *impl;
2948- GtkTreePath *tree_path;
2949- GtkTreeViewDropPosition tree_pos;
2950- int position;
2951- int bookmarks_index;
2952-
2953- impl = GTK_FILE_CHOOSER_DEFAULT (data);
2954-
2955- /* Compute position */
2956-
2957- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS);
2958-
2959- shortcuts_compute_drop_position (impl, x, y, &tree_path, &tree_pos);
2960- position = *gtk_tree_path_get_indices (tree_path);
2961- gtk_tree_path_free (tree_path);
2962-
2963- if (tree_pos == GTK_TREE_VIEW_DROP_AFTER)
2964- position++;
2965-
2966- g_assert (position >= bookmarks_index);
2967- position -= bookmarks_index;
2968-
2969- if (selection_data->target == gdk_atom_intern_static_string ("text/uri-list"))
2970- shortcuts_drop_uris (impl, (const char *) selection_data->data, position);
2971- else if (selection_data->target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
2972- shortcuts_reorder (impl, position);
2973-
2974- g_signal_stop_emission_by_name (widget, "drag_data_received");
2975-}
2976-
2977-/* Callback used when the selection in the shortcuts tree changes */
2978-static void
2979-shortcuts_selection_changed_cb (GtkTreeSelection *selection,
2980- GtkFileChooserDefault *impl)
2981-{
2982- bookmarks_check_remove_sensitivity (impl);
2983- shortcuts_check_popup_sensitivity (impl);
2984-}
2985-
2986-static gboolean
2987-shortcuts_row_separator_func (GtkTreeModel *model,
2988- GtkTreeIter *iter,
2989- gpointer data)
2990-{
2991- gint column = GPOINTER_TO_INT (data);
2992- gchar *text;
2993-
2994- gtk_tree_model_get (model, iter, column, &text, -1);
2995-
2996- if (!text)
2997- return TRUE;
2998-
2999- g_free (text);
3000-
3001- return FALSE;
3002-}
3003
3004-/* Since GtkTreeView has a keybinding attached to '/', we need to catch
3005- * keypresses before the TreeView gets them.
3006- */
3007-static gboolean
3008-tree_view_keybinding_cb (GtkWidget *tree_view,
3009- GdkEventKey *event,
3010- GtkFileChooserDefault *impl)
3011-{
3012- if ((event->keyval == GDK_slash
3013- || event->keyval == GDK_KP_Divide
3014-#ifdef G_OS_UNIX
3015- || event->keyval == GDK_asciitilde
3016-#endif
3017- ) && ! (event->state & (~GDK_SHIFT_MASK & gtk_accelerator_get_default_mod_mask ())))
3018- {
3019- location_popup_handler (impl, event->string);
3020- return TRUE;
3021- }
3022+ GDK_THREADS_LEAVE ();
3023
3024 return FALSE;
3025 }
3026
3027-/* Callback used when the file list's popup menu is detached */
3028-static void
3029-shortcuts_popup_menu_detach_cb (GtkWidget *attach_widget,
3030- GtkMenu *menu)
3031-{
3032- GtkFileChooserDefault *impl;
3033-
3034- impl = g_object_get_data (G_OBJECT (attach_widget), "GtkFileChooserDefault");
3035- g_assert (GTK_IS_FILE_CHOOSER_DEFAULT (impl));
3036-
3037- impl->browse_shortcuts_popup_menu = NULL;
3038- impl->browse_shortcuts_popup_menu_remove_item = NULL;
3039- impl->browse_shortcuts_popup_menu_rename_item = NULL;
3040-}
3041-
3042-static void
3043-remove_shortcut_cb (GtkMenuItem *item,
3044- GtkFileChooserDefault *impl)
3045-{
3046- remove_selected_bookmarks (impl);
3047-}
3048-
3049-/* Rename the selected bookmark */
3050-static void
3051-rename_selected_bookmark (GtkFileChooserDefault *impl)
3052-{
3053- GtkTreeIter iter;
3054- GtkTreePath *path;
3055- GtkTreeViewColumn *column;
3056- GtkCellRenderer *cell;
3057- GList *renderers;
3058-
3059- if (shortcuts_get_selected (impl, &iter))
3060- {
3061- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
3062- column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), 0);
3063- renderers = gtk_tree_view_column_get_cell_renderers (column);
3064- cell = g_list_nth_data (renderers, 1);
3065- g_list_free (renderers);
3066- g_object_set (cell, "editable", TRUE, NULL);
3067- gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
3068- path, column, cell, TRUE);
3069- gtk_tree_path_free (path);
3070- }
3071-}
3072-
3073-static void
3074-rename_shortcut_cb (GtkMenuItem *item,
3075- GtkFileChooserDefault *impl)
3076-{
3077- rename_selected_bookmark (impl);
3078-}
3079-
3080-/* Constructs the popup menu for the file list if needed */
3081-static void
3082-shortcuts_build_popup_menu (GtkFileChooserDefault *impl)
3083-{
3084- GtkWidget *item;
3085-
3086- if (impl->browse_shortcuts_popup_menu)
3087- return;
3088-
3089- impl->browse_shortcuts_popup_menu = gtk_menu_new ();
3090- gtk_menu_attach_to_widget (GTK_MENU (impl->browse_shortcuts_popup_menu),
3091- impl->browse_shortcuts_tree_view,
3092- shortcuts_popup_menu_detach_cb);
3093-
3094- item = gtk_image_menu_item_new_with_label (_("Remove"));
3095- impl->browse_shortcuts_popup_menu_remove_item = item;
3096- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
3097- gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
3098- g_signal_connect (item, "activate",
3099- G_CALLBACK (remove_shortcut_cb), impl);
3100- gtk_widget_show (item);
3101- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu), item);
3102-
3103- item = gtk_menu_item_new_with_label (_("Rename..."));
3104- impl->browse_shortcuts_popup_menu_rename_item = item;
3105- g_signal_connect (item, "activate",
3106- G_CALLBACK (rename_shortcut_cb), impl);
3107- gtk_widget_show (item);
3108- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu), item);
3109-
3110- shortcuts_check_popup_sensitivity (impl);
3111-}
3112-
3113 static void
3114-shortcuts_update_popup_menu (GtkFileChooserDefault *impl)
3115+queue_edited_idle (GtkFileChooserDefault *impl,
3116+ const gchar *new_text)
3117 {
3118- shortcuts_build_popup_menu (impl);
3119-}
3120-
3121-static void
3122-popup_position_func (GtkMenu *menu,
3123- gint *x,
3124- gint *y,
3125- gboolean *push_in,
3126- gpointer user_data);
3127+ /* We create the folder in an idle handler so that we don't modify the tree
3128+ * just now.
3129+ */
3130
3131-static void
3132-shortcuts_popup_menu (GtkFileChooserDefault *impl,
3133- GdkEventButton *event)
3134-{
3135- shortcuts_update_popup_menu (impl);
3136- if (event)
3137- gtk_menu_popup (GTK_MENU (impl->browse_shortcuts_popup_menu),
3138- NULL, NULL, NULL, NULL,
3139- event->button, event->time);
3140- else
3141+ if (!impl->edited_idle)
3142 {
3143- gtk_menu_popup (GTK_MENU (impl->browse_shortcuts_popup_menu),
3144- NULL, NULL,
3145- popup_position_func, impl->browse_shortcuts_tree_view,
3146- 0, GDK_CURRENT_TIME);
3147- gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu),
3148- FALSE);
3149+ impl->edited_idle = g_idle_source_new ();
3150+ g_source_set_closure (impl->edited_idle,
3151+ g_cclosure_new_object (G_CALLBACK (edited_idle_cb),
3152+ G_OBJECT (impl)));
3153+ g_source_attach (impl->edited_idle, NULL);
3154 }
3155-}
3156-
3157-/* Callback used for the GtkWidget::popup-menu signal of the shortcuts list */
3158-static gboolean
3159-shortcuts_popup_menu_cb (GtkWidget *widget,
3160- GtkFileChooserDefault *impl)
3161-{
3162- shortcuts_popup_menu (impl, NULL);
3163- return TRUE;
3164-}
3165-
3166-/* Callback used when a button is pressed on the shortcuts list.
3167- * We trap button 3 to bring up a popup menu.
3168- */
3169-static gboolean
3170-shortcuts_button_press_event_cb (GtkWidget *widget,
3171- GdkEventButton *event,
3172- GtkFileChooserDefault *impl)
3173-{
3174- static gboolean in_press = FALSE;
3175- gboolean handled;
3176-
3177- if (in_press)
3178- return FALSE;
3179-
3180- if (event->button != 3)
3181- return FALSE;
3182-
3183- in_press = TRUE;
3184- handled = gtk_widget_event (impl->browse_shortcuts_tree_view, (GdkEvent *) event);
3185- in_press = FALSE;
3186
3187- if (!handled)
3188- return FALSE;
3189-
3190- shortcuts_popup_menu (impl, event);
3191- return TRUE;
3192+ g_free (impl->edited_new_text);
3193+ impl->edited_new_text = g_strdup (new_text);
3194 }
3195
3196+/* Callback used from the text cell renderer when the new folder is named */
3197 static void
3198-shortcuts_edited (GtkCellRenderer *cell,
3199- gchar *path_string,
3200- gchar *new_text,
3201- GtkFileChooserDefault *impl)
3202-{
3203- GtkTreePath *path;
3204- GtkTreeIter iter;
3205- GtkFilePath *shortcut;
3206-
3207- g_object_set (cell, "editable", FALSE, NULL);
3208-
3209- path = gtk_tree_path_new_from_string (path_string);
3210- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->shortcuts_model), &iter, path))
3211- g_assert_not_reached ();
3212-
3213- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
3214- SHORTCUTS_COL_DATA, &shortcut,
3215- -1);
3216- gtk_tree_path_free (path);
3217-
3218- gtk_file_system_set_bookmark_label (impl->file_system, shortcut, new_text);
3219+renderer_edited_cb (GtkCellRendererText *cell_renderer_text,
3220+ const gchar *path,
3221+ const gchar *new_text,
3222+ GtkFileChooserDefault *impl)
3223+{
3224+ /* work around bug #154921 */
3225+ g_object_set (cell_renderer_text,
3226+ "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
3227+ queue_edited_idle (impl, new_text);
3228 }
3229
3230+/* Callback used from the text cell renderer when the new folder edition gets
3231+ * canceled.
3232+ */
3233 static void
3234-shortcuts_editing_canceled (GtkCellRenderer *cell,
3235- GtkFileChooserDefault *impl)
3236+renderer_editing_canceled_cb (GtkCellRendererText *cell_renderer_text,
3237+ GtkFileChooserDefault *impl)
3238 {
3239- g_object_set (cell, "editable", FALSE, NULL);
3240+ /* work around bug #154921 */
3241+ g_object_set (cell_renderer_text,
3242+ "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
3243+ queue_edited_idle (impl, NULL);
3244 }
3245
3246-/* Creates the widgets for the shortcuts and bookmarks tree */
3247+/* Creates the widgets for the filter combo box */
3248 static GtkWidget *
3249-shortcuts_list_create (GtkFileChooserDefault *impl)
3250+filter_create (GtkFileChooserDefault *impl)
3251 {
3252- GtkWidget *swin;
3253- GtkTreeSelection *selection;
3254- GtkTreeViewColumn *column;
3255- GtkCellRenderer *renderer;
3256-
3257- /* Scrolled window */
3258-
3259- swin = gtk_scrolled_window_new (NULL, NULL);
3260- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
3261- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3262- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin),
3263- GTK_SHADOW_IN);
3264- gtk_widget_show (swin);
3265-
3266- /* Tree */
3267-
3268- impl->browse_shortcuts_tree_view = gtk_tree_view_new ();
3269-#ifdef PROFILE_FILE_CHOOSER
3270- g_object_set_data (G_OBJECT (impl->browse_shortcuts_tree_view), "fmq-name", "shortcuts");
3271-#endif
3272- g_signal_connect (impl->browse_shortcuts_tree_view, "key_press_event",
3273- G_CALLBACK (tree_view_keybinding_cb), impl);
3274- g_signal_connect (impl->browse_shortcuts_tree_view, "popup_menu",
3275- G_CALLBACK (shortcuts_popup_menu_cb), impl);
3276- g_signal_connect (impl->browse_shortcuts_tree_view, "button_press_event",
3277- G_CALLBACK (shortcuts_button_press_event_cb), impl);
3278- /* Accessible object name for the file chooser's shortcuts pane */
3279- atk_object_set_name (gtk_widget_get_accessible (impl->browse_shortcuts_tree_view), _("Places"));
3280-
3281- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), impl->shortcuts_filter_model);
3282-
3283- gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
3284- GDK_BUTTON1_MASK,
3285- shortcuts_source_targets,
3286- num_shortcuts_source_targets,
3287- GDK_ACTION_MOVE);
3288-
3289- gtk_drag_dest_set (impl->browse_shortcuts_tree_view,
3290- GTK_DEST_DEFAULT_ALL,
3291- shortcuts_dest_targets,
3292- num_shortcuts_dest_targets,
3293- GDK_ACTION_COPY | GDK_ACTION_MOVE);
3294-
3295- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
3296- gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
3297- gtk_tree_selection_set_select_function (selection,
3298- shortcuts_select_func,
3299- impl, NULL);
3300-
3301- g_signal_connect (selection, "changed",
3302- G_CALLBACK (shortcuts_selection_changed_cb), impl);
3303-
3304- g_signal_connect (impl->browse_shortcuts_tree_view, "row_activated",
3305- G_CALLBACK (shortcuts_row_activated_cb), impl);
3306-
3307- g_signal_connect (impl->browse_shortcuts_tree_view, "key_press_event",
3308- G_CALLBACK (shortcuts_key_press_event_cb), impl);
3309+ impl->filter_combo = gtk_combo_box_new_text ();
3310+ gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (impl->filter_combo), FALSE);
3311
3312- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_begin",
3313- G_CALLBACK (shortcuts_drag_begin_cb), impl);
3314- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_end",
3315- G_CALLBACK (shortcuts_drag_end_cb), impl);
3316- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_data_delete",
3317- G_CALLBACK (shortcuts_drag_data_delete_cb), impl);
3318-
3319- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_leave",
3320- G_CALLBACK (shortcuts_drag_leave_cb), impl);
3321- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_motion",
3322- G_CALLBACK (shortcuts_drag_motion_cb), impl);
3323- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_drop",
3324- G_CALLBACK (shortcuts_drag_drop_cb), impl);
3325- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_data_received",
3326- G_CALLBACK (shortcuts_drag_data_received_cb), impl);
3327+ g_signal_connect (impl->filter_combo, "changed",
3328+ G_CALLBACK (filter_combo_changed), impl);
3329
3330- gtk_container_add (GTK_CONTAINER (swin), impl->browse_shortcuts_tree_view);
3331- gtk_widget_show (impl->browse_shortcuts_tree_view);
3332+ return impl->filter_combo;
3333+}
3334
3335- /* Column */
3336+struct selection_check_closure {
3337+ GtkFileChooserDefault *impl;
3338+ int num_selected;
3339+ gboolean all_files;
3340+ gboolean all_folders;
3341+};
3342
3343- column = gtk_tree_view_column_new ();
3344- /* Column header for the file chooser's shortcuts pane */
3345- gtk_tree_view_column_set_title (column, _("_Places"));
3346+/* Used from gtk_tree_selection_selected_foreach() */
3347+static void
3348+selection_check_foreach_cb (GtkTreeModel *model,
3349+ GtkTreePath *path,
3350+ GtkTreeIter *iter,
3351+ gpointer data)
3352+{
3353+ struct selection_check_closure *closure;
3354+ GtkTreeIter child_iter;
3355+ const GtkFileInfo *info;
3356+ gboolean is_folder;
3357
3358- renderer = gtk_cell_renderer_pixbuf_new ();
3359- gtk_tree_view_column_pack_start (column, renderer, FALSE);
3360- gtk_tree_view_column_set_attributes (column, renderer,
3361- "pixbuf", SHORTCUTS_COL_PIXBUF,
3362- "visible", SHORTCUTS_COL_PIXBUF_VISIBLE,
3363- NULL);
3364+ closure = data;
3365+ closure->num_selected++;
3366
3367- renderer = gtk_cell_renderer_text_new ();
3368- g_signal_connect (renderer, "edited",
3369- G_CALLBACK (shortcuts_edited), impl);
3370- g_signal_connect (renderer, "editing-canceled",
3371- G_CALLBACK (shortcuts_editing_canceled), impl);
3372- gtk_tree_view_column_pack_start (column, renderer, TRUE);
3373- gtk_tree_view_column_set_attributes (column, renderer,
3374- "text", SHORTCUTS_COL_NAME,
3375- NULL);
3376-
3377- gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
3378- shortcuts_row_separator_func,
3379- GINT_TO_POINTER (SHORTCUTS_COL_NAME),
3380- NULL);
3381+ gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter);
3382
3383- gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), column);
3384+ info = _gtk_file_system_model_get_info (closure->impl->browse_files_model, &child_iter);
3385+ is_folder = info ? gtk_file_info_get_is_folder (info) : FALSE;
3386
3387- return swin;
3388+ closure->all_folders = closure->all_folders && is_folder;
3389+ closure->all_files = closure->all_files && !is_folder;
3390 }
3391
3392-/* Creates the widgets for the shortcuts/bookmarks pane */
3393-static GtkWidget *
3394-shortcuts_pane_create (GtkFileChooserDefault *impl,
3395- GtkSizeGroup *size_group)
3396+/* Checks whether the selected items in the file list are all files or all folders */
3397+static void
3398+selection_check (GtkFileChooserDefault *impl,
3399+ gint *num_selected,
3400+ gboolean *all_files,
3401+ gboolean *all_folders)
3402 {
3403- GtkWidget *vbox;
3404- GtkWidget *hbox;
3405- GtkWidget *widget;
3406-
3407- vbox = gtk_vbox_new (FALSE, 6);
3408- gtk_widget_show (vbox);
3409-
3410- /* Shortcuts tree */
3411+ struct selection_check_closure closure;
3412+ GtkTreeSelection *selection;
3413
3414- widget = shortcuts_list_create (impl);
3415- gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
3416+ closure.impl = impl;
3417+ closure.num_selected = 0;
3418+ closure.all_files = TRUE;
3419+ closure.all_folders = TRUE;
3420
3421- /* Box for buttons */
3422+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
3423+ gtk_tree_selection_selected_foreach (selection,
3424+ selection_check_foreach_cb,
3425+ &closure);
3426
3427- hbox = gtk_hbox_new (TRUE, 6);
3428- gtk_size_group_add_widget (size_group, hbox);
3429- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
3430- gtk_widget_show (hbox);
3431+ g_assert (closure.num_selected == 0 || !(closure.all_files && closure.all_folders));
3432
3433- /* Add bookmark button */
3434+ if (num_selected)
3435+ *num_selected = closure.num_selected;
3436
3437- impl->browse_shortcuts_add_button = button_new (impl,
3438- _("_Add"),
3439- GTK_STOCK_ADD,
3440- FALSE,
3441- TRUE,
3442- G_CALLBACK (add_bookmark_button_clicked_cb));
3443- gtk_box_pack_start (GTK_BOX (hbox), impl->browse_shortcuts_add_button, TRUE, TRUE, 0);
3444- gtk_tooltips_set_tip (impl->tooltips, impl->browse_shortcuts_add_button,
3445- _("Add the selected folder to the Bookmarks"), NULL);
3446-
3447- /* Remove bookmark button */
3448-
3449- impl->browse_shortcuts_remove_button = button_new (impl,
3450- _("_Remove"),
3451- GTK_STOCK_REMOVE,
3452- FALSE,
3453- TRUE,
3454- G_CALLBACK (remove_bookmark_button_clicked_cb));
3455- gtk_box_pack_start (GTK_BOX (hbox), impl->browse_shortcuts_remove_button, TRUE, TRUE, 0);
3456- gtk_tooltips_set_tip (impl->tooltips, impl->browse_shortcuts_remove_button,
3457- _("Remove the selected bookmark"), NULL);
3458+ if (all_files)
3459+ *all_files = closure.all_files;
3460
3461- return vbox;
3462+ if (all_folders)
3463+ *all_folders = closure.all_folders;
3464 }
3465
3466+struct get_selected_path_closure {
3467+ GtkFileChooserDefault *impl;
3468+ const GtkFilePath *path;
3469+};
3470+
3471 /* Handles key press events on the file list, so that we can trap Enter to
3472 * activate the default button on our own. Also, checks to see if '/' has been
3473 * pressed. See comment by tree_view_keybinding_cb() for more details.
3474@@ -3662,17 +1173,6 @@
3475
3476 modifiers = gtk_accelerator_get_default_mod_mask ();
3477
3478- if ((event->keyval == GDK_slash
3479- || event->keyval == GDK_KP_Divide
3480-#ifdef G_OS_UNIX
3481- || event->keyval == GDK_asciitilde
3482-#endif
3483- ) && ! (event->state & (~GDK_SHIFT_MASK & modifiers)))
3484- {
3485- location_popup_handler (impl, event->string);
3486- return TRUE;
3487- }
3488-
3489 if ((event->keyval == GDK_Return
3490 || event->keyval == GDK_ISO_Enter
3491 || event->keyval == GDK_KP_Enter
3492@@ -3692,372 +1192,71 @@
3493 gtk_window_activate_default (window);
3494 return TRUE;
3495 }
3496- }
3497-
3498- return FALSE;
3499-}
3500-
3501-/* Callback used when the file list's popup menu is detached */
3502-static void
3503-popup_menu_detach_cb (GtkWidget *attach_widget,
3504- GtkMenu *menu)
3505-{
3506- GtkFileChooserDefault *impl;
3507-
3508- impl = g_object_get_data (G_OBJECT (attach_widget), "GtkFileChooserDefault");
3509- g_assert (GTK_IS_FILE_CHOOSER_DEFAULT (impl));
3510-
3511- impl->browse_files_popup_menu = NULL;
3512- impl->browse_files_popup_menu_add_shortcut_item = NULL;
3513- impl->browse_files_popup_menu_hidden_files_item = NULL;
3514-}
3515-
3516-/* Callback used when the "Add to Bookmarks" menu item is activated */
3517-static void
3518-add_to_shortcuts_cb (GtkMenuItem *item,
3519- GtkFileChooserDefault *impl)
3520-{
3521- bookmarks_add_selected_folder (impl);
3522-}
3523-
3524-/* Callback used when the "Show Hidden Files" menu item is toggled */
3525-static void
3526-show_hidden_toggled_cb (GtkCheckMenuItem *item,
3527- GtkFileChooserDefault *impl)
3528-{
3529- g_object_set (impl,
3530- "show-hidden", gtk_check_menu_item_get_active (item),
3531- NULL);
3532-}
3533-
3534-/* Shows an error dialog about not being able to select a dragged file */
3535-static void
3536-error_selecting_dragged_file_dialog (GtkFileChooserDefault *impl,
3537- const GtkFilePath *path,
3538- GError *error)
3539-{
3540- error_dialog (impl,
3541- _("Could not select file"),
3542- path, error);
3543-}
3544-
3545-static void
3546-file_list_drag_data_select_uris (GtkFileChooserDefault *impl,
3547- gchar **uris)
3548-{
3549- int i;
3550- char *uri;
3551- GtkFileChooser *chooser = GTK_FILE_CHOOSER (impl);
3552-
3553- for (i = 1; uris[i]; i++)
3554- {
3555- GtkFilePath *path;
3556-
3557- uri = uris[i];
3558- path = gtk_file_system_uri_to_path (impl->file_system, uri);
3559-
3560- if (path)
3561- {
3562- GError *error = NULL;
3563-
3564- gtk_file_chooser_default_select_path (chooser, path, &error);
3565- if (error)
3566- error_selecting_dragged_file_dialog (impl, path, error);
3567-
3568- gtk_file_path_free (path);
3569- }
3570- }
3571-}
3572-
3573-struct FileListDragData
3574-{
3575- GtkFileChooserDefault *impl;
3576- gchar **uris;
3577- GtkFilePath *path;
3578-};
3579-
3580-static void
3581-file_list_drag_data_received_get_info_cb (GtkFileSystemHandle *handle,
3582- const GtkFileInfo *info,
3583- const GError *error,
3584- gpointer user_data)
3585-{
3586- gboolean cancelled = handle->cancelled;
3587- struct FileListDragData *data = user_data;
3588- GtkFileChooser *chooser = GTK_FILE_CHOOSER (data->impl);
3589-
3590- if (handle != data->impl->file_list_drag_data_received_handle)
3591- goto out;
3592-
3593- data->impl->file_list_drag_data_received_handle = NULL;
3594-
3595- if (cancelled || error)
3596- goto out;
3597-
3598- if ((data->impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
3599- data->impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) &&
3600- data->uris[1] == 0 && !error &&
3601- gtk_file_info_get_is_folder (info))
3602- change_folder_and_display_error (data->impl, data->path, FALSE);
3603- else
3604- {
3605- GError *error = NULL;
3606-
3607- gtk_file_chooser_default_unselect_all (chooser);
3608- gtk_file_chooser_default_select_path (chooser, data->path, &error);
3609- if (error)
3610- error_selecting_dragged_file_dialog (data->impl, data->path, error);
3611- else
3612- browse_files_center_selected_row (data->impl);
3613- }
3614-
3615- if (data->impl->select_multiple)
3616- file_list_drag_data_select_uris (data->impl, data->uris);
3617-
3618-out:
3619- g_object_unref (data->impl);
3620- g_strfreev (data->uris);
3621- gtk_file_path_free (data->path);
3622- g_free (data);
3623-
3624- g_object_unref (handle);
3625-}
3626-
3627-static void
3628-file_list_drag_data_received_cb (GtkWidget *widget,
3629- GdkDragContext *context,
3630- gint x,
3631- gint y,
3632- GtkSelectionData *selection_data,
3633- guint info,
3634- guint time_,
3635- gpointer data)
3636-{
3637- GtkFileChooserDefault *impl;
3638- GtkFileChooser *chooser;
3639- gchar **uris;
3640- char *uri;
3641- GtkFilePath *path;
3642- GError *error = NULL;
3643-
3644- impl = GTK_FILE_CHOOSER_DEFAULT (data);
3645- chooser = GTK_FILE_CHOOSER (data);
3646-
3647- /* Parse the text/uri-list string, navigate to the first one */
3648- uris = g_uri_list_extract_uris ((const char *) selection_data->data);
3649- if (uris[0])
3650- {
3651- uri = uris[0];
3652- path = gtk_file_system_uri_to_path (impl->file_system, uri);
3653-
3654- if (path)
3655- {
3656- struct FileListDragData *data;
3657-
3658- data = g_new0 (struct FileListDragData, 1);
3659- data->impl = g_object_ref (impl);
3660- data->uris = uris;
3661- data->path = path;
3662-
3663- if (impl->file_list_drag_data_received_handle)
3664- gtk_file_system_cancel_operation (impl->file_list_drag_data_received_handle);
3665-
3666- impl->file_list_drag_data_received_handle =
3667- gtk_file_system_get_info (impl->file_system, path,
3668- GTK_FILE_INFO_IS_FOLDER,
3669- file_list_drag_data_received_get_info_cb,
3670- data);
3671- goto out;
3672- }
3673- else
3674- {
3675- g_set_error (&error,
3676- GTK_FILE_CHOOSER_ERROR,
3677- GTK_FILE_CHOOSER_ERROR_BAD_FILENAME,
3678- _("Could not select file '%s' "
3679- "because it is an invalid path name."),
3680- uri);
3681- error_selecting_dragged_file_dialog (impl, NULL, error);
3682- }
3683-
3684- if (impl->select_multiple)
3685- file_list_drag_data_select_uris (impl, uris);
3686- }
3687-
3688- g_strfreev (uris);
3689-
3690-out:
3691- g_signal_stop_emission_by_name (widget, "drag_data_received");
3692-}
3693-
3694-/* Don't do anything with the drag_drop signal */
3695-static gboolean
3696-file_list_drag_drop_cb (GtkWidget *widget,
3697- GdkDragContext *context,
3698- gint x,
3699- gint y,
3700- guint time_,
3701- GtkFileChooserDefault *impl)
3702-{
3703- g_signal_stop_emission_by_name (widget, "drag_drop");
3704- return TRUE;
3705-}
3706-
3707-/* Disable the normal tree drag motion handler, it makes it look like you're
3708- dropping the dragged item onto a tree item */
3709-static gboolean
3710-file_list_drag_motion_cb (GtkWidget *widget,
3711- GdkDragContext *context,
3712- gint x,
3713- gint y,
3714- guint time_,
3715- GtkFileChooserDefault *impl)
3716-{
3717- g_signal_stop_emission_by_name (widget, "drag_motion");
3718- return TRUE;
3719-}
3720-
3721-/* Constructs the popup menu for the file list if needed */
3722-static void
3723-file_list_build_popup_menu (GtkFileChooserDefault *impl)
3724-{
3725- GtkWidget *item;
3726-
3727- if (impl->browse_files_popup_menu)
3728- return;
3729-
3730- impl->browse_files_popup_menu = gtk_menu_new ();
3731- gtk_menu_attach_to_widget (GTK_MENU (impl->browse_files_popup_menu),
3732- impl->browse_files_tree_view,
3733- popup_menu_detach_cb);
3734-
3735- item = gtk_image_menu_item_new_with_mnemonic (_("_Add to Bookmarks"));
3736- impl->browse_files_popup_menu_add_shortcut_item = item;
3737- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
3738- gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
3739- gtk_widget_set_sensitive (item, FALSE);
3740- g_signal_connect (item, "activate",
3741- G_CALLBACK (add_to_shortcuts_cb), impl);
3742- gtk_widget_show (item);
3743- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
3744-
3745- item = gtk_separator_menu_item_new ();
3746- gtk_widget_show (item);
3747- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
3748-
3749- item = gtk_check_menu_item_new_with_mnemonic (_("Show _Hidden Files"));
3750- impl->browse_files_popup_menu_hidden_files_item = item;
3751- g_signal_connect (item, "toggled",
3752- G_CALLBACK (show_hidden_toggled_cb), impl);
3753- gtk_widget_show (item);
3754- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
3755-}
3756-
3757-/* Updates the popup menu for the file list, creating it if necessary */
3758-static void
3759-file_list_update_popup_menu (GtkFileChooserDefault *impl)
3760-{
3761- file_list_build_popup_menu (impl);
3762-
3763- /* The sensitivity of the Add to Bookmarks item is set in
3764- * bookmarks_check_add_sensitivity()
3765- */
3766-
3767- g_signal_handlers_block_by_func (impl->browse_files_popup_menu_hidden_files_item,
3768- G_CALLBACK (show_hidden_toggled_cb), impl);
3769- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_hidden_files_item),
3770- impl->show_hidden);
3771- g_signal_handlers_unblock_by_func (impl->browse_files_popup_menu_hidden_files_item,
3772- G_CALLBACK (show_hidden_toggled_cb), impl);
3773-}
3774-
3775-static void
3776-popup_position_func (GtkMenu *menu,
3777- gint *x,
3778- gint *y,
3779- gboolean *push_in,
3780- gpointer user_data)
3781-{
3782- GtkWidget *widget = GTK_WIDGET (user_data);
3783- GdkScreen *screen = gtk_widget_get_screen (widget);
3784- GtkRequisition req;
3785- gint monitor_num;
3786- GdkRectangle monitor;
3787-
3788- g_return_if_fail (GTK_WIDGET_REALIZED (widget));
3789-
3790- gdk_window_get_origin (widget->window, x, y);
3791-
3792- gtk_widget_size_request (GTK_WIDGET (menu), &req);
3793-
3794- *x += (widget->allocation.width - req.width) / 2;
3795- *y += (widget->allocation.height - req.height) / 2;
3796-
3797- monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y);
3798- gtk_menu_set_monitor (menu, monitor_num);
3799- gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
3800-
3801- *x = CLAMP (*x, monitor.x, monitor.x + MAX (0, monitor.width - req.width));
3802- *y = CLAMP (*y, monitor.y, monitor.y + MAX (0, monitor.height - req.height));
3803+ }
3804
3805- *push_in = FALSE;
3806+ return FALSE;
3807 }
3808
3809-static void
3810-file_list_popup_menu (GtkFileChooserDefault *impl,
3811- GdkEventButton *event)
3812+static gboolean
3813+list_button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)
3814 {
3815- file_list_update_popup_menu (impl);
3816- if (event)
3817- gtk_menu_popup (GTK_MENU (impl->browse_files_popup_menu),
3818- NULL, NULL, NULL, NULL,
3819- event->button, event->time);
3820- else
3821+ GtkTreeView * tree = GTK_TREE_VIEW (widget);
3822+ GtkFileChooserDefault *impl = data;
3823+ GtkTreePath *path;
3824+
3825+ if (event->type != GDK_BUTTON_PRESS ||
3826+ !gtk_tree_view_get_path_at_pos (tree, (gint)event->x, (gint)event->y,
3827+ &path, NULL, NULL, NULL))
3828 {
3829- gtk_menu_popup (GTK_MENU (impl->browse_files_popup_menu),
3830- NULL, NULL,
3831- popup_position_func, impl->browse_files_tree_view,
3832- 0, GDK_CURRENT_TIME);
3833- gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->browse_files_popup_menu),
3834- FALSE);
3835+ return FALSE;
3836 }
3837
3838-}
3839+ impl->list_press_time = event->time;
3840+ impl->list_press_path = path;
3841
3842-/* Callback used for the GtkWidget::popup-menu signal of the file list */
3843-static gboolean
3844-list_popup_menu_cb (GtkWidget *widget,
3845- GtkFileChooserDefault *impl)
3846-{
3847- file_list_popup_menu (impl, NULL);
3848- return TRUE;
3849+ return FALSE;
3850 }
3851
3852-/* Callback used when a button is pressed on the file list. We trap button 3 to
3853- * bring up a popup menu.
3854- */
3855 static gboolean
3856-list_button_press_event_cb (GtkWidget *widget,
3857- GdkEventButton *event,
3858- GtkFileChooserDefault *impl)
3859+list_button_release (GtkWidget *widget, GdkEventButton *event, gpointer data)
3860 {
3861- static gboolean in_press = FALSE;
3862- gboolean handled;
3863+ GtkTreeView * tree = GTK_TREE_VIEW (widget);
3864+ GtkFileChooserDefault *impl = data;
3865+ GtkTreePath *path = NULL;
3866+ gboolean retval = FALSE;
3867
3868- if (in_press)
3869- return FALSE;
3870+ if (!impl->list_press_time ||
3871+ !impl->list_press_path ||
3872+ event->type != GDK_BUTTON_RELEASE ||
3873+ !gtk_tree_view_get_path_at_pos (tree, (gint)event->x, (gint)event->y,
3874+ &path, NULL, NULL, NULL))
3875+ {
3876+ goto done;
3877+ }
3878
3879- if (event->button != 3)
3880- return FALSE;
3881+ if (event->time - impl->list_press_time > LONG_CLICK_LENGTH &&
3882+ !gtk_tree_path_compare (impl->list_press_path, path))
3883+ {
3884+ retval = TRUE;
3885+ list_row_activated (tree, path, NULL, impl);
3886+ }
3887+
3888+ done:
3889+ if (path)
3890+ gtk_tree_path_free (path);
3891
3892- in_press = TRUE;
3893- handled = gtk_widget_event (impl->browse_files_tree_view, (GdkEvent *) event);
3894- in_press = FALSE;
3895+ impl->list_press_time = 0;
3896
3897- file_list_popup_menu (impl, event);
3898- return TRUE;
3899+ if (impl->list_press_path)
3900+ {
3901+ gtk_tree_path_free (impl->list_press_path);
3902+ impl->list_press_path = NULL;
3903+ }
3904+
3905+ return FALSE;
3906 }
3907
3908+
3909 /* Creates the widgets for the file list */
3910 static GtkWidget *
3911 create_file_list (GtkFileChooserDefault *impl)
3912@@ -4087,37 +1286,19 @@
3913 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (impl->browse_files_tree_view), TRUE);
3914 gtk_container_add (GTK_CONTAINER (swin), impl->browse_files_tree_view);
3915
3916- gtk_drag_dest_set (impl->browse_files_tree_view,
3917- GTK_DEST_DEFAULT_ALL,
3918- file_list_dest_targets,
3919- num_file_list_dest_targets,
3920- GDK_ACTION_COPY | GDK_ACTION_MOVE);
3921-
3922 g_signal_connect (impl->browse_files_tree_view, "row_activated",
3923 G_CALLBACK (list_row_activated), impl);
3924 g_signal_connect (impl->browse_files_tree_view, "key_press_event",
3925 G_CALLBACK (trap_activate_cb), impl);
3926- g_signal_connect (impl->browse_files_tree_view, "popup_menu",
3927- G_CALLBACK (list_popup_menu_cb), impl);
3928 g_signal_connect (impl->browse_files_tree_view, "button_press_event",
3929- G_CALLBACK (list_button_press_event_cb), impl);
3930-
3931- g_signal_connect (impl->browse_files_tree_view, "drag_data_received",
3932- G_CALLBACK (file_list_drag_data_received_cb), impl);
3933- g_signal_connect (impl->browse_files_tree_view, "drag_drop",
3934- G_CALLBACK (file_list_drag_drop_cb), impl);
3935- g_signal_connect (impl->browse_files_tree_view, "drag_motion",
3936- G_CALLBACK (file_list_drag_motion_cb), impl);
3937+ G_CALLBACK (list_button_press), impl);
3938+ g_signal_connect (impl->browse_files_tree_view, "button_release_event",
3939+ G_CALLBACK (list_button_release), impl);
3940
3941 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
3942 gtk_tree_selection_set_select_function (selection,
3943 list_select_func,
3944 impl, NULL);
3945- gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (impl->browse_files_tree_view),
3946- GDK_BUTTON1_MASK,
3947- file_list_source_targets,
3948- num_file_list_source_targets,
3949- GDK_ACTION_COPY);
3950
3951 g_signal_connect (selection, "changed",
3952 G_CALLBACK (list_selection_changed), impl);
3953@@ -4178,230 +1359,206 @@
3954 return swin;
3955 }
3956
3957-static GtkWidget *
3958-create_path_bar (GtkFileChooserDefault *impl)
3959-{
3960- GtkWidget *path_bar;
3961-
3962- path_bar = g_object_new (GTK_TYPE_PATH_BAR, NULL);
3963- _gtk_path_bar_set_file_system (GTK_PATH_BAR (path_bar), impl->file_system);
3964-
3965- return path_bar;
3966-}
3967-
3968 static void
3969-set_filter_tooltip (GtkWidget *widget,
3970- gpointer data)
3971+up_button_clicked_cb (GtkButton *button, gpointer data)
3972 {
3973- GtkTooltips *tooltips = (GtkTooltips *)data;
3974-
3975- if (GTK_IS_BUTTON (widget))
3976- gtk_tooltips_set_tip (tooltips, widget,
3977- _("Select which types of files are shown"),
3978- NULL);
3979+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
3980+ up_folder_handler (impl);
3981 }
3982
3983 static void
3984-realize_filter_combo (GtkWidget *combo,
3985- gpointer data)
3986+volume_button_clicked_cb (GtkButton *button, gpointer data)
3987 {
3988- GtkFileChooserDefault *impl = (GtkFileChooserDefault *)data;
3989+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
3990+ GtkFilePath * path = g_object_get_data (G_OBJECT (button), "file-path");
3991
3992- gtk_container_forall (GTK_CONTAINER (combo),
3993- set_filter_tooltip,
3994- impl->tooltips);
3995+ change_folder_and_display_error (impl, path);
3996 }
3997
3998-/* Creates the widgets for the files/folders pane */
3999 static GtkWidget *
4000-file_pane_create (GtkFileChooserDefault *impl,
4001- GtkSizeGroup *size_group)
4002+create_bar (GtkFileChooserDefault *impl)
4003 {
4004- GtkWidget *vbox;
4005- GtkWidget *hbox;
4006- GtkWidget *widget;
4007+ GSList *list, *l;
4008+ int n;
4009+ GtkWidget *bar = gtk_hbox_new (FALSE, DEFAULT_SPACING);
4010+ GtkWidget *img;
4011
4012- vbox = gtk_vbox_new (FALSE, 6);
4013- gtk_widget_show (vbox);
4014+ /* first the Up button */
4015+ img = gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON);
4016+ gtk_widget_show (img);
4017+
4018+ impl->up_button = gtk_button_new ();
4019+ gtk_container_add (GTK_CONTAINER (impl->up_button), img);
4020+ gtk_widget_show (impl->up_button);
4021+ gtk_widget_set_sensitive (impl->up_button, FALSE);
4022+ gtk_button_set_focus_on_click (GTK_BUTTON (impl->up_button), FALSE);
4023+
4024+ g_signal_connect (impl->up_button, "clicked",
4025+ G_CALLBACK (up_button_clicked_cb), impl);
4026+ gtk_box_pack_start (GTK_BOX(bar), impl->up_button, FALSE, FALSE, 0);
4027+
4028+ impl->num_volumes = 0;
4029+ list = gtk_file_system_list_volumes (impl->file_system);
4030
4031- /* Box for lists and preview */
4032+ n = 0;
4033
4034- hbox = gtk_hbox_new (FALSE, PREVIEW_HBOX_SPACING);
4035- gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
4036- gtk_widget_show (hbox);
4037+ for (l = list; l; l = l->next, n++)
4038+ {
4039+ GtkFileSystemVolume *volume;
4040+ GdkPixbuf *pixbuf;
4041+ GtkWidget *button;
4042+ GtkWidget *image;
4043+ GtkFilePath *base_path;
4044+ gchar * file_name = NULL;
4045
4046- /* File list */
4047+ volume = l->data;
4048+ base_path =
4049+ gtk_file_system_volume_get_base_path (impl->file_system, volume);
4050
4051- widget = create_file_list (impl);
4052- gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
4053+ if (impl->local_only)
4054+ {
4055+ gboolean is_local =
4056+ gtk_file_system_path_is_local (impl->file_system, base_path);
4057+
4058+ if (!is_local)
4059+ {
4060+ gtk_file_path_free (base_path);
4061+ gtk_file_system_volume_free (impl->file_system, volume);
4062+ continue;
4063+ }
4064+ }
4065
4066- /* Preview */
4067+#if 0
4068+ label_copy =
4069+ gtk_file_system_volume_get_display_name (impl->file_system, volume);
4070+#endif
4071+ pixbuf =
4072+ gtk_file_system_volume_render_icon (impl->file_system, volume,
4073+ GTK_WIDGET (impl),
4074+ impl->icon_size, NULL);
4075
4076- impl->preview_box = gtk_vbox_new (FALSE, 12);
4077- gtk_box_pack_start (GTK_BOX (hbox), impl->preview_box, FALSE, FALSE, 0);
4078- /* Don't show preview box initially */
4079+ button = gtk_button_new ();
4080+ image = gtk_image_new_from_pixbuf (pixbuf);
4081+ g_object_unref (G_OBJECT (pixbuf));
4082+ gtk_container_add (GTK_CONTAINER (button), image);
4083+ gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
4084+
4085+ file_name =
4086+ gtk_file_system_path_to_filename (impl->file_system, base_path);
4087+
4088+ if (file_name && impl->root_folder &&
4089+ strcmp (file_name, impl->root_folder) &&
4090+ !strncmp (file_name, impl->root_folder, strlen (file_name)))
4091+ {
4092+ /* The base path is below the root folder; we replace it with
4093+ * the root folder
4094+ */
4095+ gtk_file_path_free (base_path);
4096+ base_path = gtk_file_system_filename_to_path (impl->file_system,
4097+ impl->root_folder);
4098+ }
4099
4100- /* Filter combo */
4101+ g_free (file_name);
4102+ gtk_widget_show_all (button);
4103
4104- impl->filter_combo_hbox = gtk_hbox_new (FALSE, 12);
4105+ g_object_set_data (G_OBJECT (button), "file-path", base_path);
4106
4107- widget = filter_create (impl);
4108+ g_signal_connect (button, "clicked",
4109+ G_CALLBACK (volume_button_clicked_cb), impl);
4110
4111- g_signal_connect (widget, "realize",
4112- G_CALLBACK (realize_filter_combo), impl);
4113+ gtk_box_pack_start (GTK_BOX(bar), button, FALSE, FALSE, 0);
4114+ }
4115
4116- gtk_widget_show (widget);
4117- gtk_box_pack_end (GTK_BOX (impl->filter_combo_hbox), widget, FALSE, FALSE, 0);
4118+ impl->num_volumes = n;
4119+ g_slist_free (list);
4120
4121- gtk_size_group_add_widget (size_group, impl->filter_combo_hbox);
4122- gtk_box_pack_end (GTK_BOX (vbox), impl->filter_combo_hbox, FALSE, FALSE, 0);
4123+ gtk_widget_show (bar);
4124
4125- return vbox;
4126+ return bar;
4127 }
4128
4129-/* Callback used when the "Browse for more folders" expander is toggled */
4130-static void
4131-expander_changed_cb (GtkExpander *expander,
4132- GParamSpec *pspec,
4133- GtkFileChooserDefault *impl)
4134+/* Creates the widgets for the files/folders pane */
4135+static GtkWidget *
4136+file_pane_create (GtkFileChooserDefault *impl)
4137 {
4138- impl->expand_folders = gtk_expander_get_expanded(GTK_EXPANDER (impl->save_expander));
4139- update_appearance (impl);
4140-}
4141+ GtkWidget *vbox;
4142+ GtkWidget *hbox;
4143+ GtkWidget *widget;
4144+ vbox = gtk_vbox_new (FALSE, DEFAULT_SPACING);
4145+ gtk_widget_show (vbox);
4146
4147-/* Callback used when the selection changes in the save folder combo box */
4148-static void
4149-save_folder_combo_changed_cb (GtkComboBox *combo,
4150- GtkFileChooserDefault *impl)
4151-{
4152- GtkTreeIter iter;
4153+ /* The volume bar and 'Create Folder' button */
4154+ hbox = gtk_hbox_new (FALSE, DEFAULT_SPACING);
4155+ gtk_widget_show (hbox);
4156+ impl->bar = create_bar (impl);
4157+ gtk_widget_show_all (impl->bar);
4158+ gtk_box_pack_start (GTK_BOX (hbox), impl->bar, TRUE, TRUE, 0);
4159
4160- if (impl->changing_folder)
4161- return;
4162+ /* Create Folder */
4163+ widget = gtk_image_new_from_icon_name ("folder-new", GTK_ICON_SIZE_BUTTON);
4164+ gtk_widget_show (widget);
4165+ impl->browse_new_folder_button = gtk_button_new ();
4166+ gtk_container_add (GTK_CONTAINER (impl->browse_new_folder_button), widget);
4167+ gtk_button_set_focus_on_click (GTK_BUTTON (impl->browse_new_folder_button),
4168+ FALSE);
4169
4170- if (gtk_combo_box_get_active_iter (combo, &iter))
4171- shortcuts_activate_iter (impl, &iter);
4172-}
4173+ g_signal_connect (impl->browse_new_folder_button, "clicked",
4174+ G_CALLBACK (new_folder_button_clicked), impl);
4175+ gtk_box_pack_end (GTK_BOX (hbox), impl->browse_new_folder_button, FALSE, FALSE, 0);
4176
4177-/* Creates the combo box with the save folders */
4178-static GtkWidget *
4179-save_folder_combo_create (GtkFileChooserDefault *impl)
4180-{
4181- GtkWidget *combo;
4182- GtkCellRenderer *cell;
4183+ widget = filter_create (impl);
4184+ gtk_widget_hide (widget);
4185+ gtk_box_pack_end (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
4186+
4187+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
4188+
4189+ /* Box for lists */
4190+ hbox = gtk_hbox_new (FALSE, LIST_HBOX_SPACING);
4191+ gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
4192+ gtk_widget_show (hbox);
4193
4194- combo = g_object_new (GTK_TYPE_COMBO_BOX,
4195- "model", impl->shortcuts_model,
4196- "focus-on-click", FALSE,
4197- NULL);
4198- gtk_widget_show (combo);
4199-
4200- cell = gtk_cell_renderer_pixbuf_new ();
4201- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, FALSE);
4202- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
4203- "pixbuf", SHORTCUTS_COL_PIXBUF,
4204- "visible", SHORTCUTS_COL_PIXBUF_VISIBLE,
4205- "sensitive", SHORTCUTS_COL_PIXBUF_VISIBLE,
4206- NULL);
4207-
4208- cell = gtk_cell_renderer_text_new ();
4209- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
4210- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
4211- "text", SHORTCUTS_COL_NAME,
4212- "sensitive", SHORTCUTS_COL_PIXBUF_VISIBLE,
4213- NULL);
4214-
4215- gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo),
4216- shortcuts_row_separator_func,
4217- GINT_TO_POINTER (SHORTCUTS_COL_NAME),
4218- NULL);
4219+ /* File list */
4220
4221- g_signal_connect (combo, "changed",
4222- G_CALLBACK (save_folder_combo_changed_cb), impl);
4223+ widget = create_file_list (impl);
4224+ gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
4225
4226- return combo;
4227+ return vbox;
4228 }
4229
4230 /* Creates the widgets specific to Save mode */
4231-static void
4232+static GtkWidget *
4233 save_widgets_create (GtkFileChooserDefault *impl)
4234 {
4235 GtkWidget *vbox;
4236- GtkWidget *table;
4237+ GtkWidget *hbox;
4238 GtkWidget *widget;
4239- GtkWidget *alignment;
4240
4241- if (impl->save_widgets != NULL)
4242- return;
4243-
4244- location_switch_to_path_bar (impl);
4245-
4246- vbox = gtk_vbox_new (FALSE, 12);
4247-
4248- table = gtk_table_new (2, 2, FALSE);
4249- gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
4250- gtk_widget_show (table);
4251- gtk_table_set_row_spacings (GTK_TABLE (table), 12);
4252- gtk_table_set_col_spacings (GTK_TABLE (table), 12);
4253+ vbox = gtk_vbox_new (FALSE, 0);
4254+ hbox = gtk_hbox_new (FALSE, DEFAULT_SPACING);
4255
4256- /* Label */
4257-
4258- widget = gtk_label_new_with_mnemonic (_("_Name:"));
4259+ widget = gtk_label_new (_("Name:"));
4260 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
4261- gtk_table_attach (GTK_TABLE (table), widget,
4262- 0, 1, 0, 1,
4263- GTK_FILL, GTK_FILL,
4264- 0, 0);
4265+ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
4266 gtk_widget_show (widget);
4267
4268- /* Location entry */
4269-
4270 impl->location_entry = _gtk_file_chooser_entry_new (TRUE);
4271 _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
4272 impl->file_system);
4273- gtk_entry_set_width_chars (GTK_ENTRY (impl->location_entry), 45);
4274+/* gtk_entry_set_width_chars (GTK_ENTRY (impl->location_entry), 45); */
4275 gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE);
4276- gtk_table_attach (GTK_TABLE (table), impl->location_entry,
4277- 1, 2, 0, 1,
4278- GTK_EXPAND | GTK_FILL, 0,
4279- 0, 0);
4280+ gtk_box_pack_start (GTK_BOX (hbox), impl->location_entry,
4281+ TRUE, TRUE, 0);
4282+
4283 gtk_widget_show (impl->location_entry);
4284- gtk_label_set_mnemonic_widget (GTK_LABEL (widget), impl->location_entry);
4285
4286- /* Folder combo */
4287- impl->save_folder_label = gtk_label_new (NULL);
4288- gtk_misc_set_alignment (GTK_MISC (impl->save_folder_label), 0.0, 0.5);
4289- gtk_table_attach (GTK_TABLE (table), impl->save_folder_label,
4290- 0, 1, 1, 2,
4291- GTK_FILL, GTK_FILL,
4292- 0, 0);
4293- gtk_widget_show (impl->save_folder_label);
4294-
4295- impl->save_folder_combo = save_folder_combo_create (impl);
4296- gtk_table_attach (GTK_TABLE (table), impl->save_folder_combo,
4297- 1, 2, 1, 2,
4298- GTK_EXPAND | GTK_FILL, GTK_FILL,
4299- 0, 0);
4300- gtk_label_set_mnemonic_widget (GTK_LABEL (impl->save_folder_label), impl->save_folder_combo);
4301-
4302- /* Expander */
4303- alignment = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
4304- gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
4305-
4306- impl->save_expander = gtk_expander_new_with_mnemonic (_("_Browse for other folders"));
4307- gtk_container_add (GTK_CONTAINER (alignment), impl->save_expander);
4308- g_signal_connect (impl->save_expander, "notify::expanded",
4309- G_CALLBACK (expander_changed_cb),
4310- impl);
4311- gtk_widget_show_all (alignment);
4312+ gtk_widget_show (hbox);
4313+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
4314
4315- impl->save_widgets = vbox;
4316- gtk_box_pack_start (GTK_BOX (impl), impl->save_widgets, FALSE, FALSE, 0);
4317- gtk_box_reorder_child (GTK_BOX (impl), impl->save_widgets, 0);
4318- gtk_widget_show (impl->save_widgets);
4319+ return vbox;
4320 }
4321
4322 /* Destroys the widgets specific to Save mode */
4323+/* ??? */
4324 static void
4325 save_widgets_destroy (GtkFileChooserDefault *impl)
4326 {
4327@@ -4411,293 +1568,17 @@
4328 gtk_widget_destroy (impl->save_widgets);
4329 impl->save_widgets = NULL;
4330 impl->location_entry = NULL;
4331- impl->save_folder_label = NULL;
4332- impl->save_folder_combo = NULL;
4333- impl->save_expander = NULL;
4334-}
4335-
4336-/* Turns on the path bar widget. Can be called even if we are already in that
4337- * mode.
4338- */
4339-static void
4340-location_switch_to_path_bar (GtkFileChooserDefault *impl)
4341-{
4342- if (impl->location_entry)
4343- {
4344- gtk_widget_destroy (impl->location_entry);
4345- impl->location_entry = NULL;
4346- }
4347-
4348- gtk_widget_hide (impl->location_entry_box);
4349-}
4350-
4351-/* Sets the full path of the current folder as the text in the location entry. */
4352-static void
4353-location_entry_set_initial_text (GtkFileChooserDefault *impl)
4354-{
4355- char *text;
4356-
4357- if (!impl->current_folder)
4358- return;
4359-
4360- if (gtk_file_system_path_is_local (impl->file_system, impl->current_folder))
4361- {
4362- char *filename;
4363-
4364- filename = gtk_file_system_path_to_filename (impl->file_system, impl->current_folder);
4365- if (filename)
4366- {
4367- text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
4368- g_free (filename);
4369- }
4370- else
4371- text = NULL;
4372- }
4373- else
4374- text = gtk_file_system_path_to_uri (impl->file_system, impl->current_folder);
4375-
4376- if (text)
4377- {
4378- gboolean need_slash;
4379- int len;
4380-
4381- len = strlen (text);
4382- need_slash = (text[len - 1] != G_DIR_SEPARATOR);
4383-
4384- if (need_slash)
4385- {
4386- char *slash_text;
4387-
4388- slash_text = g_new (char, len + 2);
4389- strcpy (slash_text, text);
4390- slash_text[len] = G_DIR_SEPARATOR;
4391- slash_text[len + 1] = 0;
4392-
4393- g_free (text);
4394- text = slash_text;
4395- }
4396-
4397- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), text);
4398- g_free (text);
4399- }
4400-}
4401-
4402-/* Turns on the location entry. Can be called even if we are already in that
4403- * mode.
4404- */
4405-static void
4406-location_switch_to_filename_entry (GtkFileChooserDefault *impl)
4407-{
4408- if (impl->location_entry)
4409- gtk_widget_destroy (impl->location_entry);
4410-
4411- /* Box */
4412-
4413- gtk_widget_show (impl->location_entry_box);
4414-
4415- /* Entry */
4416-
4417- impl->location_entry = _gtk_file_chooser_entry_new (TRUE);
4418- _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
4419- impl->file_system);
4420- gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE);
4421- _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
4422-
4423- gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_entry, TRUE, TRUE, 0);
4424- gtk_label_set_mnemonic_widget (GTK_LABEL (impl->location_label), impl->location_entry);
4425-
4426- /* Configure the entry */
4427-
4428- _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->current_folder);
4429-
4430- /* Done */
4431-
4432- gtk_widget_show (impl->location_entry);
4433- gtk_widget_grab_focus (impl->location_entry);
4434-}
4435-
4436-/* Sets a new location mode. set_buttons determines whether the toggle button
4437- * for the mode will also be changed.
4438- */
4439-static void
4440-location_mode_set (GtkFileChooserDefault *impl,
4441- LocationMode new_mode,
4442- gboolean set_button)
4443-{
4444- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
4445- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
4446- {
4447- GtkWindow *toplevel;
4448- GtkWidget *current_focus;
4449- gboolean button_active;
4450- gboolean switch_to_file_list;
4451-
4452- switch (new_mode)
4453- {
4454- case LOCATION_MODE_PATH_BAR:
4455- button_active = FALSE;
4456-
4457- /* The location_entry will disappear when we switch to path bar mode. So,
4458- * we'll focus the file list in that case, to avoid having a window with
4459- * no focused widget.
4460- */
4461- toplevel = get_toplevel (GTK_WIDGET (impl));
4462- switch_to_file_list = FALSE;
4463- if (toplevel)
4464- {
4465- current_focus = gtk_window_get_focus (toplevel);
4466- if (!current_focus || current_focus == impl->location_entry)
4467- switch_to_file_list = TRUE;
4468- }
4469-
4470- location_switch_to_path_bar (impl);
4471-
4472- if (switch_to_file_list)
4473- gtk_widget_grab_focus (impl->browse_files_tree_view);
4474-
4475- break;
4476-
4477- case LOCATION_MODE_FILENAME_ENTRY:
4478- button_active = TRUE;
4479- location_switch_to_filename_entry (impl);
4480- break;
4481-
4482- default:
4483- g_assert_not_reached ();
4484- return;
4485- }
4486-
4487- if (set_button)
4488- {
4489- g_signal_handlers_block_by_func (impl->location_button,
4490- G_CALLBACK (location_button_toggled_cb), impl);
4491-
4492- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->location_button), button_active);
4493-
4494- g_signal_handlers_unblock_by_func (impl->location_button,
4495- G_CALLBACK (location_button_toggled_cb), impl);
4496- }
4497- }
4498-
4499- impl->location_mode = new_mode;
4500-}
4501-
4502-static void
4503-toggle_location_mode (GtkFileChooserDefault *impl,
4504- gboolean set_button)
4505-{
4506- LocationMode new_mode;
4507-
4508- /* toggle value */
4509- new_mode = (impl->location_mode == LOCATION_MODE_PATH_BAR) ?
4510- LOCATION_MODE_FILENAME_ENTRY : LOCATION_MODE_PATH_BAR;
4511-
4512- location_mode_set (impl, new_mode, set_button);
4513-}
4514-
4515-static void
4516-location_toggle_popup_handler (GtkFileChooserDefault *impl)
4517-{
4518- toggle_location_mode (impl, TRUE);
4519-}
4520-
4521-/* Callback used when one of the location mode buttons is toggled */
4522-static void
4523-location_button_toggled_cb (GtkToggleButton *toggle,
4524- GtkFileChooserDefault *impl)
4525-{
4526- gboolean is_active;
4527-
4528- is_active = gtk_toggle_button_get_active (toggle);
4529-
4530- if (is_active)
4531- g_assert (impl->location_mode == LOCATION_MODE_PATH_BAR);
4532- else
4533- g_assert (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY);
4534-
4535- toggle_location_mode (impl, FALSE);
4536-}
4537-
4538-/* Creates a toggle button for the location entry. */
4539-static void
4540-location_button_create (GtkFileChooserDefault *impl)
4541-{
4542- GtkWidget *image;
4543- const char *str;
4544-
4545- image = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_BUTTON);
4546- gtk_widget_show (image);
4547-
4548- impl->location_button = g_object_new (GTK_TYPE_TOGGLE_BUTTON,
4549- "image", image,
4550- NULL);
4551-
4552- g_signal_connect (impl->location_button, "toggled",
4553- G_CALLBACK (location_button_toggled_cb), impl);
4554-
4555- str = _("Type a file name");
4556-
4557- gtk_tooltips_set_tip (impl->tooltips, impl->location_button, str, NULL);
4558- atk_object_set_name (gtk_widget_get_accessible (impl->location_button), str);
4559 }
4560
4561-/* Creates the main hpaned with the widgets shared by Open and Save mode */
4562-static GtkWidget *
4563-browse_widgets_create (GtkFileChooserDefault *impl)
4564-{
4565- GtkWidget *vbox;
4566- GtkWidget *hbox;
4567- GtkWidget *hpaned;
4568- GtkWidget *widget;
4569- GtkSizeGroup *size_group;
4570-
4571- /* size group is used by the [+][-] buttons and the filter combo */
4572- size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
4573- vbox = gtk_vbox_new (FALSE, 12);
4574-
4575- /* Location widgets */
4576- hbox = gtk_hbox_new (FALSE, 12);
4577- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
4578- gtk_widget_show (hbox);
4579-
4580- location_button_create (impl);
4581- gtk_box_pack_start (GTK_BOX (hbox), impl->location_button, FALSE, FALSE, 0);
4582-
4583- /* Path bar */
4584-
4585- impl->browse_path_bar = create_path_bar (impl);
4586- g_signal_connect (impl->browse_path_bar, "path-clicked", G_CALLBACK (path_bar_clicked), impl);
4587- gtk_widget_show_all (impl->browse_path_bar);
4588- gtk_box_pack_start (GTK_BOX (hbox), impl->browse_path_bar, TRUE, TRUE, 0);
4589-
4590- /* Create Folder */
4591- impl->browse_new_folder_button = gtk_button_new_with_mnemonic (_("Create Fo_lder"));
4592- g_signal_connect (impl->browse_new_folder_button, "clicked",
4593- G_CALLBACK (new_folder_button_clicked), impl);
4594- gtk_box_pack_end (GTK_BOX (hbox), impl->browse_new_folder_button, FALSE, FALSE, 0);
4595-
4596- /* Box for the location label and entry */
4597-
4598- impl->location_entry_box = gtk_hbox_new (FALSE, 12);
4599- gtk_box_pack_start (GTK_BOX (vbox), impl->location_entry_box, FALSE, FALSE, 0);
4600-
4601- impl->location_label = gtk_label_new_with_mnemonic (_("_Location:"));
4602- gtk_widget_show (impl->location_label);
4603- gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_label, FALSE, FALSE, 0);
4604-
4605- /* Paned widget */
4606- hpaned = gtk_hpaned_new ();
4607- gtk_widget_show (hpaned);
4608- gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0);
4609-
4610- widget = shortcuts_pane_create (impl, size_group);
4611- gtk_paned_pack1 (GTK_PANED (hpaned), widget, FALSE, FALSE);
4612- widget = file_pane_create (impl, size_group);
4613- gtk_paned_pack2 (GTK_PANED (hpaned), widget, TRUE, FALSE);
4614+/* Creates the main hpaned with the widgets shared by Open and Save mode */
4615+static GtkWidget *
4616+browse_widgets_create (GtkFileChooserDefault *impl)
4617+{
4618+ GtkWidget *widget;
4619
4620- g_object_unref (size_group);
4621+ widget = file_pane_create (impl);
4622
4623- return vbox;
4624+ return widget;
4625 }
4626
4627 static GObject*
4628@@ -4719,18 +1600,14 @@
4629
4630 gtk_widget_push_composite_child ();
4631
4632- /* Shortcuts model */
4633-
4634- shortcuts_model_create (impl);
4635+ /* Widgets for Save mode */
4636+ impl->save_widgets = save_widgets_create (impl);
4637+ gtk_box_pack_start (GTK_BOX (impl), impl->save_widgets, FALSE, FALSE, 0);
4638
4639 /* The browse widgets */
4640 impl->browse_widgets = browse_widgets_create (impl);
4641 gtk_box_pack_start (GTK_BOX (impl), impl->browse_widgets, TRUE, TRUE, 0);
4642
4643- /* Alignment to hold extra widget */
4644- impl->extra_align = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
4645- gtk_box_pack_start (GTK_BOX (impl), impl->extra_align, FALSE, FALSE, 0);
4646-
4647 gtk_widget_pop_composite_child ();
4648 update_appearance (impl);
4649
4650@@ -4739,34 +1616,6 @@
4651 return object;
4652 }
4653
4654-/* Sets the extra_widget by packing it in the appropriate place */
4655-static void
4656-set_extra_widget (GtkFileChooserDefault *impl,
4657- GtkWidget *extra_widget)
4658-{
4659- if (extra_widget)
4660- {
4661- g_object_ref (extra_widget);
4662- /* FIXME: is this right ? */
4663- gtk_widget_show (extra_widget);
4664- }
4665-
4666- if (impl->extra_widget)
4667- {
4668- gtk_container_remove (GTK_CONTAINER (impl->extra_align), impl->extra_widget);
4669- g_object_unref (impl->extra_widget);
4670- }
4671-
4672- impl->extra_widget = extra_widget;
4673- if (impl->extra_widget)
4674- {
4675- gtk_container_add (GTK_CONTAINER (impl->extra_align), impl->extra_widget);
4676- gtk_widget_show (impl->extra_align);
4677- }
4678- else
4679- gtk_widget_hide (impl->extra_align);
4680-}
4681-
4682 static void
4683 set_local_only (GtkFileChooserDefault *impl,
4684 gboolean local_only)
4685@@ -4775,12 +1624,6 @@
4686 {
4687 impl->local_only = local_only;
4688
4689- if (impl->shortcuts_model && impl->file_system)
4690- {
4691- shortcuts_add_volumes (impl);
4692- shortcuts_add_bookmarks (impl);
4693- }
4694-
4695 if (local_only &&
4696 !gtk_file_system_path_is_local (impl->file_system, impl->current_folder))
4697 {
4698@@ -4807,19 +1650,7 @@
4699 volumes_changed_cb (GtkFileSystem *file_system,
4700 GtkFileChooserDefault *impl)
4701 {
4702- shortcuts_add_volumes (impl);
4703-}
4704-
4705-/* Callback used when the set of bookmarks changes in the file system */
4706-static void
4707-bookmarks_changed_cb (GtkFileSystem *file_system,
4708- GtkFileChooserDefault *impl)
4709-{
4710- shortcuts_add_bookmarks (impl);
4711-
4712- bookmarks_check_add_sensitivity (impl);
4713- bookmarks_check_remove_sensitivity (impl);
4714- shortcuts_check_popup_sensitivity (impl);
4715+ /* FIXME -- update the bar */
4716 }
4717
4718 /* Sets the file chooser to multiple selection mode */
4719@@ -4841,8 +1672,6 @@
4720
4721 impl->select_multiple = select_multiple;
4722 g_object_notify (G_OBJECT (impl), "select-multiple");
4723-
4724- check_preview_change (impl);
4725 }
4726
4727 static void
4728@@ -4855,8 +1684,6 @@
4729 {
4730 g_signal_handler_disconnect (impl->file_system, impl->volumes_changed_id);
4731 impl->volumes_changed_id = 0;
4732- g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id);
4733- impl->bookmarks_changed_id = 0;
4734 g_object_unref (impl->file_system);
4735 }
4736
4737@@ -4892,9 +1719,6 @@
4738 impl->volumes_changed_id = g_signal_connect (impl->file_system, "volumes-changed",
4739 G_CALLBACK (volumes_changed_cb),
4740 impl);
4741- impl->bookmarks_changed_id = g_signal_connect (impl->file_system, "bookmarks-changed",
4742- G_CALLBACK (bookmarks_changed_cb),
4743- impl);
4744 }
4745
4746 profile_end ("end", NULL);
4747@@ -4911,32 +1735,13 @@
4748 if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
4749 impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
4750 {
4751- const char *text;
4752-
4753- gtk_widget_hide (impl->location_button);
4754- save_widgets_create (impl);
4755-
4756- if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
4757- text = _("Save in _folder:");
4758- else
4759- text = _("Create in _folder:");
4760-
4761- gtk_label_set_text_with_mnemonic (GTK_LABEL (impl->save_folder_label), text);
4762+ gtk_widget_show (impl->save_widgets);
4763+ gtk_widget_show (impl->browse_widgets);
4764
4765- if (gtk_expander_get_expanded (GTK_EXPANDER (impl->save_expander)))
4766- {
4767- gtk_widget_set_sensitive (impl->save_folder_label, FALSE);
4768- gtk_widget_set_sensitive (impl->save_folder_combo, FALSE);
4769- gtk_widget_show (impl->browse_widgets);
4770- }
4771+ if (impl->show_create_folder)
4772+ gtk_widget_show (impl->browse_new_folder_button);
4773 else
4774- {
4775- gtk_widget_set_sensitive (impl->save_folder_label, TRUE);
4776- gtk_widget_set_sensitive (impl->save_folder_combo, TRUE);
4777- gtk_widget_hide (impl->browse_widgets);
4778- }
4779-
4780- gtk_widget_show (impl->browse_new_folder_button);
4781+ gtk_widget_hide (impl->browse_new_folder_button);
4782
4783 if (impl->select_multiple)
4784 {
4785@@ -4948,23 +1753,17 @@
4786 else if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
4787 impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
4788 {
4789- gtk_widget_show (impl->location_button);
4790- save_widgets_destroy (impl);
4791+ gtk_widget_hide (impl->save_widgets);
4792+ gtk_widget_hide (impl->browse_new_folder_button);
4793 gtk_widget_show (impl->browse_widgets);
4794- location_mode_set (impl, impl->location_mode, TRUE);
4795 }
4796
4797- if (impl->location_entry)
4798- _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
4799-
4800- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)
4801+ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
4802+ !impl->show_create_folder)
4803 gtk_widget_hide (impl->browse_new_folder_button);
4804 else
4805 gtk_widget_show (impl->browse_new_folder_button);
4806
4807- /* This *is* needed; we need to redraw the file list because the "sensitivity"
4808- * of files may change depending whether we are in a file or folder-only mode.
4809- */
4810 gtk_widget_queue_draw (impl->browse_files_tree_view);
4811
4812 g_signal_emit_by_name (impl, "default-size-changed");
4813@@ -5016,24 +1815,6 @@
4814 set_local_only (impl, g_value_get_boolean (value));
4815 break;
4816
4817- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
4818- set_preview_widget (impl, g_value_get_object (value));
4819- break;
4820-
4821- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
4822- impl->preview_widget_active = g_value_get_boolean (value);
4823- update_preview_widget_visibility (impl);
4824- break;
4825-
4826- case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
4827- impl->use_preview_label = g_value_get_boolean (value);
4828- update_preview_widget_visibility (impl);
4829- break;
4830-
4831- case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
4832- set_extra_widget (impl, g_value_get_object (value));
4833- break;
4834-
4835 case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
4836 {
4837 gboolean select_multiple = g_value_get_boolean (value);
4838@@ -5070,6 +1851,55 @@
4839 }
4840 break;
4841
4842+ case GTK_FILE_CHOOSER_PROP_ROOT_FOLDER:
4843+ {
4844+ GtkFilePath * path;
4845+ gchar * new_root = g_strdup (g_value_get_string (value));
4846+
4847+ if (!new_root)
4848+ {
4849+ new_root = g_strdup ("/");
4850+ }
4851+
4852+ path = gtk_file_system_filename_to_path (impl->file_system,
4853+ new_root);
4854+ if (change_folder (impl, path, FALSE))
4855+ {
4856+ g_free (impl->root_folder);
4857+ impl->root_folder = new_root;
4858+ }
4859+ else
4860+ {
4861+ g_warning ("Unable to set [%s] as root folder", new_root);
4862+ g_free (new_root);
4863+ }
4864+
4865+ gtk_file_path_free (path);
4866+ }
4867+ break;
4868+
4869+ case GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER:
4870+ {
4871+ gboolean show = g_value_get_boolean (value);
4872+ if (show != impl->show_create_folder)
4873+ {
4874+ impl->show_create_folder = show;
4875+
4876+ if (show)
4877+ gtk_widget_show (impl->browse_new_folder_button);
4878+ else
4879+ gtk_widget_hide (impl->browse_new_folder_button);
4880+ }
4881+ }
4882+ break;
4883+
4884+ /* These are not supported */
4885+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
4886+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
4887+ case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
4888+ case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
4889+ break;
4890+
4891 default:
4892 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4893 break;
4894@@ -5098,28 +1928,32 @@
4895 g_value_set_boolean (value, impl->local_only);
4896 break;
4897
4898- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
4899- g_value_set_object (value, impl->preview_widget);
4900+ case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
4901+ g_value_set_boolean (value, impl->select_multiple);
4902 break;
4903
4904- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
4905- g_value_set_boolean (value, impl->preview_widget_active);
4906+ case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
4907+ g_value_set_boolean (value, impl->show_hidden);
4908 break;
4909
4910- case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
4911- g_value_set_boolean (value, impl->use_preview_label);
4912+ case GTK_FILE_CHOOSER_PROP_ROOT_FOLDER:
4913+ g_value_set_string (value, impl->root_folder);
4914 break;
4915
4916- case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
4917- g_value_set_object (value, impl->extra_widget);
4918+ case GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER:
4919+ g_value_set_boolean (value, impl->show_create_folder);
4920 break;
4921
4922- case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
4923- g_value_set_boolean (value, impl->select_multiple);
4924+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
4925+ g_value_set_object (value, NULL);
4926 break;
4927
4928- case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
4929- g_value_set_boolean (value, impl->show_hidden);
4930+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
4931+ g_value_set_boolean (value, FALSE);
4932+ break;
4933+
4934+ case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
4935+ g_value_set_boolean (value, FALSE);
4936 break;
4937
4938 case GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION:
4939@@ -5154,24 +1988,12 @@
4940 GSList *l;
4941 GtkFileChooserDefault *impl = (GtkFileChooserDefault *) object;
4942
4943- if (impl->extra_widget)
4944- {
4945- g_object_unref (impl->extra_widget);
4946- impl->extra_widget = NULL;
4947- }
4948-
4949 if (impl->volumes_changed_id > 0)
4950 {
4951 g_signal_handler_disconnect (impl->file_system, impl->volumes_changed_id);
4952 impl->volumes_changed_id = 0;
4953 }
4954
4955- if (impl->bookmarks_changed_id > 0)
4956- {
4957- g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id);
4958- impl->bookmarks_changed_id = 0;
4959- }
4960-
4961 pending_select_paths_free (impl);
4962
4963 /* cancel all pending operations */
4964@@ -5197,23 +2019,6 @@
4965 impl->reload_icon_handles = NULL;
4966 }
4967
4968- if (impl->loading_shortcuts)
4969- {
4970- for (l = impl->loading_shortcuts; l; l = l->next)
4971- {
4972- GtkFileSystemHandle *handle =l->data;
4973- gtk_file_system_cancel_operation (handle);
4974- }
4975- g_slist_free (impl->loading_shortcuts);
4976- impl->loading_shortcuts = NULL;
4977- }
4978-
4979- if (impl->file_list_drag_data_received_handle)
4980- {
4981- gtk_file_system_cancel_operation (impl->file_list_drag_data_received_handle);
4982- impl->file_list_drag_data_received_handle = NULL;
4983- }
4984-
4985 if (impl->update_current_folder_handle)
4986 {
4987 gtk_file_system_cancel_operation (impl->update_current_folder_handle);
4988@@ -5238,12 +2043,6 @@
4989 impl->update_from_entry_handle = NULL;
4990 }
4991
4992- if (impl->shortcuts_activate_iter_handle)
4993- {
4994- gtk_file_system_cancel_operation (impl->shortcuts_activate_iter_handle);
4995- impl->shortcuts_activate_iter_handle = NULL;
4996- }
4997-
4998 remove_settings_signal (impl, gtk_widget_get_screen (GTK_WIDGET (impl)));
4999
5000 G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->dispose (object);
5001@@ -5256,12 +2055,7 @@
5002 static void
5003 gtk_file_chooser_default_show_all (GtkWidget *widget)
5004 {
5005- GtkFileChooserDefault *impl = (GtkFileChooserDefault *) widget;
5006-
5007 gtk_widget_show (widget);
5008-
5009- if (impl->extra_widget)
5010- gtk_widget_show_all (impl->extra_widget);
5011 }
5012
5013 /* Handler for GtkWindow::set-focus; this is where we save the last-focused
5014@@ -5322,7 +2116,6 @@
5015 else
5016 impl->icon_size = FALLBACK_ICON_SIZE;
5017
5018- shortcuts_reload_icons (impl);
5019 gtk_widget_queue_resize (impl->browse_files_tree_view);
5020
5021 profile_end ("end", NULL);
5022@@ -5441,15 +2234,6 @@
5023
5024 impl->default_width = allocation->width;
5025 impl->default_height = allocation->height;
5026-
5027- if (impl->preview_widget_active &&
5028- impl->preview_widget &&
5029- GTK_WIDGET_DRAWABLE (impl->preview_widget))
5030- impl->default_width -= impl->preview_widget->allocation.width + PREVIEW_HBOX_SPACING;
5031-
5032- if (impl->extra_widget &&
5033- GTK_WIDGET_DRAWABLE (impl->extra_widget))
5034- impl->default_height -= GTK_BOX (widget)->spacing + impl->extra_widget->allocation.height;
5035 }
5036
5037 static gboolean
5038@@ -5503,23 +2287,18 @@
5039 settings_load (GtkFileChooserDefault *impl)
5040 {
5041 GtkFileChooserSettings *settings;
5042- LocationMode location_mode;
5043 gboolean show_hidden;
5044 gboolean expand_folders;
5045
5046 settings = _gtk_file_chooser_settings_new ();
5047
5048- location_mode = _gtk_file_chooser_settings_get_location_mode (settings);
5049 show_hidden = _gtk_file_chooser_settings_get_show_hidden (settings);
5050 expand_folders = _gtk_file_chooser_settings_get_expand_folders (settings);
5051
5052 g_object_unref (settings);
5053
5054- location_mode_set (impl, location_mode, TRUE);
5055 gtk_file_chooser_set_show_hidden (GTK_FILE_CHOOSER (impl), show_hidden);
5056 impl->expand_folders = expand_folders;
5057- if (impl->save_expander)
5058- gtk_expander_set_expanded (GTK_EXPANDER (impl->save_expander), expand_folders);
5059 }
5060
5061 static void
5062@@ -5529,7 +2308,6 @@
5063
5064 settings = _gtk_file_chooser_settings_new ();
5065
5066- _gtk_file_chooser_settings_set_location_mode (settings, impl->location_mode);
5067 _gtk_file_chooser_settings_set_show_hidden (settings, gtk_file_chooser_get_show_hidden (GTK_FILE_CHOOSER (impl)));
5068 _gtk_file_chooser_settings_set_expand_folders (settings, impl->expand_folders);
5069
5070@@ -5570,7 +2348,7 @@
5071 if (impl->current_folder)
5072 {
5073 pending_select_paths_store_selection (impl);
5074- change_folder_and_display_error (impl, impl->current_folder, FALSE);
5075+ change_folder_and_display_error (impl, impl->current_folder);
5076 }
5077 break;
5078
5079@@ -5578,8 +2356,6 @@
5080 g_assert_not_reached ();
5081 }
5082
5083- bookmarks_changed_cb (impl->file_system, impl);
5084-
5085 settings_load (impl);
5086
5087 profile_end ("end", NULL);
5088@@ -5897,12 +2673,10 @@
5089 gpointer user_data)
5090 {
5091 gboolean have_hidden;
5092- gboolean have_filtered;
5093 GSList *l;
5094 struct ShowAndSelectPathsData *data = user_data;
5095
5096 have_hidden = FALSE;
5097- have_filtered = FALSE;
5098
5099 for (l = data->paths; l; l = l->next)
5100 {
5101@@ -5918,12 +2692,9 @@
5102 if (!have_hidden)
5103 have_hidden = gtk_file_info_get_is_hidden (info);
5104
5105- if (!have_filtered)
5106- have_filtered = !gtk_file_info_get_is_folder (info) && get_is_file_filtered (data->impl, path, info);
5107-
5108 gtk_file_info_free (info);
5109
5110- if (have_hidden && have_filtered)
5111+ if (have_hidden)
5112 break; /* we now have all the information we need */
5113 }
5114 }
5115@@ -5937,9 +2708,6 @@
5116 if (have_hidden)
5117 g_object_set (data->impl, "show-hidden", TRUE, NULL);
5118
5119- if (have_filtered)
5120- set_current_filter (data->impl, NULL);
5121-
5122 for (l = data->paths; l; l = l->next)
5123 {
5124 const GtkFilePath *path;
5125@@ -6197,9 +2965,8 @@
5126
5127 if (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5128 || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
5129- || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5130- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
5131- && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)))
5132+ || impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5133+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER))
5134 return;
5135
5136 g_assert (impl->location_entry != NULL);
5137@@ -6387,9 +3154,6 @@
5138 if (!gtk_file_info_get_is_folder (info))
5139 goto out;
5140
5141- if (!_gtk_path_bar_set_path (GTK_PATH_BAR (impl->browse_path_bar), data->path, data->keep_trail, NULL))
5142- goto out;
5143-
5144 if (impl->current_folder != data->path)
5145 {
5146 if (impl->current_folder)
5147@@ -6400,17 +3164,6 @@
5148 impl->reload_state = RELOAD_HAS_FOLDER;
5149 }
5150
5151- /* Update the widgets that may trigger a folder change themselves. */
5152-
5153- if (!impl->changing_folder)
5154- {
5155- impl->changing_folder = TRUE;
5156-
5157- shortcuts_update_current_folder (impl);
5158-
5159- impl->changing_folder = FALSE;
5160- }
5161-
5162 /* Set the folder on the save entry */
5163
5164 if (impl->location_entry)
5165@@ -6430,13 +3183,7 @@
5166
5167 /* Refresh controls */
5168
5169- shortcuts_find_current_folder (impl);
5170-
5171 g_signal_emit_by_name (impl, "current-folder-changed", 0);
5172-
5173- check_preview_change (impl);
5174- bookmarks_check_add_sensitivity (impl);
5175-
5176 g_signal_emit_by_name (impl, "selection-changed", 0);
5177
5178 out:
5179@@ -6698,9 +3445,8 @@
5180
5181 g_assert (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5182 || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
5183- || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5184- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
5185- && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY));
5186+ || impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5187+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
5188
5189 chooser_entry = GTK_FILE_CHOOSER_ENTRY (impl->location_entry);
5190
5191@@ -6878,17 +3624,6 @@
5192 return g_slist_reverse (info.result);
5193 }
5194
5195-static GtkFilePath *
5196-gtk_file_chooser_default_get_preview_path (GtkFileChooser *chooser)
5197-{
5198- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5199-
5200- if (impl->preview_path)
5201- return gtk_file_path_copy (impl->preview_path);
5202- else
5203- return NULL;
5204-}
5205-
5206 static GtkFileSystem *
5207 gtk_file_chooser_default_get_file_system (GtkFileChooser *chooser)
5208 {
5209@@ -6903,9 +3638,9 @@
5210 gboolean show)
5211 {
5212 if (show)
5213- gtk_widget_show (impl->filter_combo_hbox);
5214+ gtk_widget_show (impl->filter_combo);
5215 else
5216- gtk_widget_hide (impl->filter_combo_hbox);
5217+ gtk_widget_hide (impl->filter_combo);
5218 }
5219
5220 static void
5221@@ -6915,6 +3650,8 @@
5222 GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5223 const gchar *name;
5224
5225+ g_debug ("adding filter");
5226+
5227 if (g_slist_find (impl->filters, filter))
5228 {
5229 g_warning ("gtk_file_chooser_add_filter() called on filter already in list\n");
5230@@ -6925,291 +3662,62 @@
5231 impl->filters = g_slist_append (impl->filters, filter);
5232
5233 name = gtk_file_filter_get_name (filter);
5234- if (!name)
5235- name = "Untitled filter"; /* Place-holder, doesn't need to be marked for translation */
5236-
5237- gtk_combo_box_append_text (GTK_COMBO_BOX (impl->filter_combo), name);
5238-
5239- if (!g_slist_find (impl->filters, impl->current_filter))
5240- set_current_filter (impl, filter);
5241-
5242- show_filters (impl, TRUE);
5243-}
5244-
5245-static void
5246-gtk_file_chooser_default_remove_filter (GtkFileChooser *chooser,
5247- GtkFileFilter *filter)
5248-{
5249- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5250- GtkTreeModel *model;
5251- GtkTreeIter iter;
5252- gint filter_index;
5253-
5254- filter_index = g_slist_index (impl->filters, filter);
5255-
5256- if (filter_index < 0)
5257- {
5258- g_warning ("gtk_file_chooser_remove_filter() called on filter not in list\n");
5259- return;
5260- }
5261-
5262- impl->filters = g_slist_remove (impl->filters, filter);
5263-
5264- if (filter == impl->current_filter)
5265- {
5266- if (impl->filters)
5267- set_current_filter (impl, impl->filters->data);
5268- else
5269- set_current_filter (impl, NULL);
5270- }
5271-
5272- /* Remove row from the combo box */
5273- model = gtk_combo_box_get_model (GTK_COMBO_BOX (impl->filter_combo));
5274- if (!gtk_tree_model_iter_nth_child (model, &iter, NULL, filter_index))
5275- g_assert_not_reached ();
5276-
5277- gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
5278-
5279- g_object_unref (filter);
5280-
5281- if (!impl->filters)
5282- show_filters (impl, FALSE);
5283-}
5284-
5285-static GSList *
5286-gtk_file_chooser_default_list_filters (GtkFileChooser *chooser)
5287-{
5288- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5289-
5290- return g_slist_copy (impl->filters);
5291-}
5292-
5293-/* Returns the position in the shortcuts tree where the nth specified shortcut would appear */
5294-static int
5295-shortcuts_get_pos_for_shortcut_folder (GtkFileChooserDefault *impl,
5296- int pos)
5297-{
5298- return pos + shortcuts_get_index (impl, SHORTCUTS_SHORTCUTS);
5299-}
5300-
5301-struct AddShortcutData
5302-{
5303- GtkFileChooserDefault *impl;
5304- GtkFilePath *path;
5305-};
5306-
5307-static void
5308-add_shortcut_get_info_cb (GtkFileSystemHandle *handle,
5309- const GtkFileInfo *info,
5310- const GError *error,
5311- gpointer user_data)
5312-{
5313- int pos;
5314- gboolean cancelled = handle->cancelled;
5315- struct AddShortcutData *data = user_data;
5316-
5317- if (!g_slist_find (data->impl->loading_shortcuts, handle))
5318- goto out;
5319-
5320- data->impl->loading_shortcuts = g_slist_remove (data->impl->loading_shortcuts, handle);
5321-
5322- if (cancelled || error || !gtk_file_info_get_is_folder (info))
5323- goto out;
5324-
5325- pos = shortcuts_get_pos_for_shortcut_folder (data->impl, data->impl->num_shortcuts);
5326-
5327- shortcuts_insert_path (data->impl, pos, FALSE, NULL, data->path, NULL, FALSE, SHORTCUTS_SHORTCUTS);
5328-
5329-out:
5330- g_object_unref (data->impl);
5331- gtk_file_path_free (data->path);
5332- g_free (data);
5333-
5334- g_object_unref (handle);
5335-}
5336-
5337-static gboolean
5338-gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser,
5339- const GtkFilePath *path,
5340- GError **error)
5341-{
5342- GtkFileSystemHandle *handle;
5343- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5344- struct AddShortcutData *data;
5345- GSList *l;
5346- int pos;
5347-
5348- /* Avoid adding duplicates */
5349- pos = shortcut_find_position (impl, path);
5350- if (pos >= 0 && pos < shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR))
5351- {
5352- gchar *uri;
5353-
5354- uri = gtk_file_system_path_to_uri (impl->file_system, path);
5355- /* translators, "Shortcut" means "Bookmark" here */
5356- g_set_error (error,
5357- GTK_FILE_CHOOSER_ERROR,
5358- GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
5359- _("Shortcut %s already exists"),
5360- uri);
5361- g_free (uri);
5362-
5363- return FALSE;
5364- }
5365-
5366- for (l = impl->loading_shortcuts; l; l = l->next)
5367- {
5368- GtkFileSystemHandle *h = l->data;
5369- GtkFilePath *p;
5370-
5371- p = g_object_get_data (G_OBJECT (h), "add-shortcut-path-key");
5372- if (p && !gtk_file_path_compare (path, p))
5373- {
5374- gchar *uri;
5375-
5376- uri = gtk_file_system_path_to_uri (impl->file_system, path);
5377- g_set_error (error,
5378- GTK_FILE_CHOOSER_ERROR,
5379- GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
5380- _("Shortcut %s already exists"),
5381- uri);
5382- g_free (uri);
5383-
5384- return FALSE;
5385- }
5386- }
5387-
5388- data = g_new0 (struct AddShortcutData, 1);
5389- data->impl = g_object_ref (impl);
5390- data->path = gtk_file_path_copy (path);
5391-
5392- handle = gtk_file_system_get_info (impl->file_system, path,
5393- GTK_FILE_INFO_IS_FOLDER,
5394- add_shortcut_get_info_cb, data);
5395+ if (!name)
5396+ name = "Untitled filter"; /* Place-holder, doesn't need to be marked for translation */
5397
5398- if (!handle)
5399- return FALSE;
5400+ gtk_combo_box_append_text (GTK_COMBO_BOX (impl->filter_combo), name);
5401
5402- impl->loading_shortcuts = g_slist_append (impl->loading_shortcuts, handle);
5403- g_object_set_data (G_OBJECT (handle), "add-shortcut-path-key", data->path);
5404+ if (!g_slist_find (impl->filters, impl->current_filter))
5405+ set_current_filter (impl, filter);
5406
5407- return TRUE;
5408+ show_filters (impl, g_slist_length (impl->filters) > 1);
5409 }
5410
5411-static gboolean
5412-gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser,
5413- const GtkFilePath *path,
5414- GError **error)
5415+static void
5416+gtk_file_chooser_default_remove_filter (GtkFileChooser *chooser,
5417+ GtkFileFilter *filter)
5418 {
5419 GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5420- int pos;
5421+ GtkTreeModel *model;
5422 GtkTreeIter iter;
5423- GSList *l;
5424- char *uri;
5425- int i;
5426+ gint filter_index;
5427
5428- for (l = impl->loading_shortcuts; l; l = l->next)
5429- {
5430- GtkFileSystemHandle *h = l->data;
5431- GtkFilePath *p;
5432+ filter_index = g_slist_index (impl->filters, filter);
5433
5434- p = g_object_get_data (G_OBJECT (h), "add-shortcut-path-key");
5435- if (p && !gtk_file_path_compare (path, p))
5436- {
5437- impl->loading_shortcuts = g_slist_remove (impl->loading_shortcuts, h);
5438- gtk_file_system_cancel_operation (h);
5439- return TRUE;
5440- }
5441+ if (filter_index < 0)
5442+ {
5443+ g_warning ("gtk_file_chooser_remove_filter() called on filter not in list\n");
5444+ return;
5445 }
5446
5447- if (impl->num_shortcuts == 0)
5448- goto out;
5449-
5450- pos = shortcuts_get_pos_for_shortcut_folder (impl, 0);
5451- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->shortcuts_model), &iter, NULL, pos))
5452- g_assert_not_reached ();
5453+ impl->filters = g_slist_remove (impl->filters, filter);
5454
5455- for (i = 0; i < impl->num_shortcuts; i++)
5456+ if (filter == impl->current_filter)
5457 {
5458- gpointer col_data;
5459- gboolean is_volume;
5460- GtkFilePath *shortcut;
5461-
5462- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
5463- SHORTCUTS_COL_DATA, &col_data,
5464- SHORTCUTS_COL_IS_VOLUME, &is_volume,
5465- -1);
5466- g_assert (col_data != NULL);
5467- g_assert (!is_volume);
5468-
5469- shortcut = col_data;
5470- if (gtk_file_path_compare (shortcut, path) == 0)
5471- {
5472- shortcuts_remove_rows (impl, pos + i, 1);
5473- impl->num_shortcuts--;
5474- return TRUE;
5475- }
5476-
5477- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
5478- g_assert_not_reached ();
5479+ if (impl->filters)
5480+ set_current_filter (impl, impl->filters->data);
5481+ else
5482+ set_current_filter (impl, NULL);
5483 }
5484
5485- out:
5486+ /* Remove row from the combo box */
5487+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (impl->filter_combo));
5488+ if (!gtk_tree_model_iter_nth_child (model, &iter, NULL, filter_index))
5489+ g_assert_not_reached ();
5490
5491- uri = gtk_file_system_path_to_uri (impl->file_system, path);
5492- /* translators, "Shortcut" means "Bookmark" here */
5493- g_set_error (error,
5494- GTK_FILE_CHOOSER_ERROR,
5495- GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
5496- _("Shortcut %s does not exist"),
5497- uri);
5498- g_free (uri);
5499+ gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
5500
5501- return FALSE;
5502+ g_object_unref (filter);
5503+
5504+ show_filters (impl, g_slist_length (impl->filters) > 1);
5505 }
5506
5507 static GSList *
5508-gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser)
5509+gtk_file_chooser_default_list_filters (GtkFileChooser *chooser)
5510 {
5511 GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5512- int pos;
5513- GtkTreeIter iter;
5514- int i;
5515- GSList *list;
5516-
5517- if (impl->num_shortcuts == 0)
5518- return NULL;
5519-
5520- pos = shortcuts_get_pos_for_shortcut_folder (impl, 0);
5521- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->shortcuts_model), &iter, NULL, pos))
5522- g_assert_not_reached ();
5523-
5524- list = NULL;
5525-
5526- for (i = 0; i < impl->num_shortcuts; i++)
5527- {
5528- gpointer col_data;
5529- gboolean is_volume;
5530- GtkFilePath *shortcut;
5531-
5532- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
5533- SHORTCUTS_COL_DATA, &col_data,
5534- SHORTCUTS_COL_IS_VOLUME, &is_volume,
5535- -1);
5536- g_assert (col_data != NULL);
5537- g_assert (!is_volume);
5538-
5539- shortcut = col_data;
5540- list = g_slist_prepend (list, gtk_file_path_copy (shortcut));
5541
5542- if (i != impl->num_shortcuts - 1)
5543- {
5544- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
5545- g_assert_not_reached ();
5546- }
5547- }
5548-
5549- return g_slist_reverse (list);
5550+ return g_slist_copy (impl->filters);
5551 }
5552
5553 /* Guesses a size based upon font sizes */
5554@@ -7256,25 +3764,9 @@
5555 gint *default_height)
5556 {
5557 GtkFileChooserDefault *impl;
5558- GtkRequisition req;
5559
5560 impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
5561 find_good_size_from_style (GTK_WIDGET (chooser_embed), default_width, default_height);
5562-
5563- if (impl->preview_widget_active &&
5564- impl->preview_widget &&
5565- GTK_WIDGET_VISIBLE (impl->preview_widget))
5566- {
5567- gtk_widget_size_request (impl->preview_box, &req);
5568- *default_width += PREVIEW_HBOX_SPACING + req.width;
5569- }
5570-
5571- if (impl->extra_widget &&
5572- GTK_WIDGET_VISIBLE (impl->extra_widget))
5573- {
5574- gtk_widget_size_request (impl->extra_align, &req);
5575- *default_height += GTK_BOX (chooser_embed)->spacing + req.height;
5576- }
5577 }
5578
5579 static gboolean
5580@@ -7285,8 +3777,7 @@
5581 impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
5582
5583 return (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
5584- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
5585- gtk_expander_get_expanded (GTK_EXPANDER (impl->save_expander)));
5586+ impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
5587 }
5588
5589 struct switch_folder_closure {
5590@@ -7333,7 +3824,7 @@
5591
5592 g_assert (closure.path && closure.num_selected == 1);
5593
5594- change_folder_and_display_error (impl, closure.path, FALSE);
5595+ change_folder_and_display_error (impl, closure.path);
5596 }
5597
5598 /* Gets the GtkFileInfo for the selected row in the file list; assumes single
5599@@ -7628,7 +4119,7 @@
5600 else
5601 {
5602 /* This will display an error, which is what we want */
5603- change_folder_and_display_error (data->impl, data->parent_path, FALSE);
5604+ change_folder_and_display_error (data->impl, data->parent_path);
5605 }
5606
5607 out:
5608@@ -7706,50 +4197,6 @@
5609 g_object_unref (handle);
5610 }
5611
5612-static void
5613-paste_text_received (GtkClipboard *clipboard,
5614- const gchar *text,
5615- GtkFileChooserDefault *impl)
5616-{
5617- GtkFilePath *path;
5618-
5619- if (!text)
5620- return;
5621-
5622- path = gtk_file_system_uri_to_path (impl->file_system, text);
5623- if (!path)
5624- {
5625- if (!g_path_is_absolute (text))
5626- {
5627- location_popup_handler (impl, text);
5628- return;
5629- }
5630-
5631- path = gtk_file_system_filename_to_path (impl->file_system, text);
5632- if (!path)
5633- {
5634- location_popup_handler (impl, text);
5635- return;
5636- }
5637- }
5638-
5639- if (!gtk_file_chooser_default_select_path (GTK_FILE_CHOOSER (impl), path, NULL))
5640- location_popup_handler (impl, text);
5641-
5642- gtk_file_path_free (path);
5643-}
5644-
5645-/* Handler for the "location-popup-on-paste" keybinding signal */
5646-static void
5647-location_popup_on_paste_handler (GtkFileChooserDefault *impl)
5648-{
5649- GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (impl),
5650- GDK_SELECTION_CLIPBOARD);
5651- gtk_clipboard_request_text (clipboard,
5652- (GtkClipboardTextReceivedFunc) paste_text_received,
5653- impl);
5654-}
5655-
5656
5657 /* Implementation for GtkFileChooserEmbed::should_respond() */
5658 static gboolean
5659@@ -7855,9 +4302,8 @@
5660
5661 g_assert (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5662 || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
5663- || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5664- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
5665- && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY));
5666+ || impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5667+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
5668
5669 entry = GTK_FILE_CHOOSER_ENTRY (impl->location_entry);
5670 check_save_entry (impl, &path, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder);
5671@@ -7873,7 +4319,7 @@
5672 if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5673 || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
5674 {
5675- change_folder_and_display_error (impl, path, TRUE);
5676+ change_folder_and_display_error (impl, path);
5677 retval = FALSE;
5678 }
5679 else if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
5680@@ -7896,430 +4342,126 @@
5681
5682 /* We need to check whether path exists and is not a folder */
5683
5684- data = g_new0 (struct FileExistsData, 1);
5685- data->impl = g_object_ref (impl);
5686- data->path = gtk_file_path_copy (path);
5687- data->parent_path = gtk_file_path_copy (_gtk_file_chooser_entry_get_current_folder (entry));
5688-
5689- if (impl->file_exists_get_info_handle)
5690- gtk_file_system_cancel_operation (impl->file_exists_get_info_handle);
5691-
5692- impl->file_exists_get_info_handle =
5693- gtk_file_system_get_info (impl->file_system, path,
5694- GTK_FILE_INFO_IS_FOLDER,
5695- file_exists_get_info_cb,
5696- data);
5697-
5698- set_busy_cursor (impl, TRUE);
5699- retval = FALSE;
5700-
5701- if (error != NULL)
5702- g_error_free (error);
5703- }
5704-
5705- gtk_file_path_free (path);
5706- return retval;
5707- }
5708- else if (impl->toplevel_last_focus_widget == impl->browse_shortcuts_tree_view)
5709- {
5710- /* The focus is on a dialog's action area button, *and* the widget that
5711- * was focused immediately before it is the shortcuts list. Switch to the
5712- * selected shortcut and tell the caller not to respond.
5713- */
5714- GtkTreeIter iter;
5715-
5716- if (shortcuts_get_selected (impl, &iter))
5717- {
5718- shortcuts_activate_iter (impl, &iter);
5719-
5720- gtk_widget_grab_focus (impl->browse_files_tree_view);
5721- }
5722- else
5723- goto file_list;
5724-
5725- return FALSE;
5726- }
5727- else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view)
5728- {
5729- /* The focus is on a dialog's action area button, *and* the widget that
5730- * was focused immediately before it is the file list.
5731- */
5732- goto file_list;
5733- }
5734- else if (impl->location_entry && impl->toplevel_last_focus_widget == impl->location_entry)
5735- {
5736- /* The focus is on a dialog's action area button, *and* the widget that
5737- * was focused immediately before it is the location entry.
5738- */
5739- goto save_entry;
5740- }
5741- else
5742- /* The focus is on a dialog's action area button or something else */
5743- if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5744- || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
5745- goto save_entry;
5746- else
5747- goto file_list;
5748-
5749- g_assert_not_reached ();
5750- return FALSE;
5751-}
5752-
5753-/* Implementation for GtkFileChooserEmbed::initial_focus() */
5754-static void
5755-gtk_file_chooser_default_initial_focus (GtkFileChooserEmbed *chooser_embed)
5756-{
5757- GtkFileChooserDefault *impl;
5758- GtkWidget *widget;
5759-
5760- impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
5761-
5762- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5763- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
5764- {
5765- if (impl->location_mode == LOCATION_MODE_PATH_BAR)
5766- widget = impl->browse_files_tree_view;
5767- else
5768- widget = impl->location_entry;
5769- }
5770- else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5771- || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
5772- widget = impl->location_entry;
5773- else
5774- {
5775- g_assert_not_reached ();
5776- widget = NULL;
5777- }
5778-
5779- g_assert (widget != NULL);
5780- gtk_widget_grab_focus (widget);
5781-}
5782-
5783-static void
5784-set_current_filter (GtkFileChooserDefault *impl,
5785- GtkFileFilter *filter)
5786-{
5787- if (impl->current_filter != filter)
5788- {
5789- int filter_index;
5790-
5791- /* NULL filters are allowed to reset to non-filtered status
5792- */
5793- filter_index = g_slist_index (impl->filters, filter);
5794- if (impl->filters && filter && filter_index < 0)
5795- return;
5796-
5797- if (impl->current_filter)
5798- g_object_unref (impl->current_filter);
5799- impl->current_filter = filter;
5800- if (impl->current_filter)
5801- {
5802- g_object_ref_sink (impl->current_filter);
5803- }
5804-
5805- if (impl->filters)
5806- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->filter_combo),
5807- filter_index);
5808-
5809- if (impl->browse_files_model)
5810- install_list_model_filter (impl);
5811-
5812- g_object_notify (G_OBJECT (impl), "filter");
5813- }
5814-}
5815-
5816-static void
5817-filter_combo_changed (GtkComboBox *combo_box,
5818- GtkFileChooserDefault *impl)
5819-{
5820- gint new_index = gtk_combo_box_get_active (combo_box);
5821- GtkFileFilter *new_filter = g_slist_nth_data (impl->filters, new_index);
5822-
5823- set_current_filter (impl, new_filter);
5824-}
5825-
5826-static void
5827-check_preview_change (GtkFileChooserDefault *impl)
5828-{
5829- GtkTreePath *cursor_path;
5830- const GtkFilePath *new_path;
5831- const GtkFileInfo *new_info;
5832-
5833- gtk_tree_view_get_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view), &cursor_path, NULL);
5834- if (cursor_path && impl->sort_model)
5835- {
5836- GtkTreeIter iter;
5837- GtkTreeIter child_iter;
5838-
5839- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, cursor_path))
5840- g_assert_not_reached ();
5841-
5842- gtk_tree_path_free (cursor_path);
5843-
5844- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter);
5845-
5846- new_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter);
5847- new_info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
5848- }
5849- else
5850- {
5851- new_path = NULL;
5852- new_info = NULL;
5853- }
5854-
5855- if (new_path != impl->preview_path &&
5856- !(new_path && impl->preview_path &&
5857- gtk_file_path_compare (new_path, impl->preview_path) == 0))
5858- {
5859- if (impl->preview_path)
5860- {
5861- gtk_file_path_free (impl->preview_path);
5862- g_free (impl->preview_display_name);
5863- }
5864-
5865- if (new_path)
5866- {
5867- impl->preview_path = gtk_file_path_copy (new_path);
5868- impl->preview_display_name = g_strdup (gtk_file_info_get_display_name (new_info));
5869- }
5870- else
5871- {
5872- impl->preview_path = NULL;
5873- impl->preview_display_name = NULL;
5874- }
5875-
5876- if (impl->use_preview_label && impl->preview_label)
5877- gtk_label_set_text (GTK_LABEL (impl->preview_label), impl->preview_display_name);
5878-
5879- g_signal_emit_by_name (impl, "update-preview");
5880- }
5881-}
5882-
5883-static void
5884-shortcuts_activate_volume_mount_cb (GtkFileSystemHandle *handle,
5885- GtkFileSystemVolume *volume,
5886- const GError *error,
5887- gpointer data)
5888-{
5889- GtkFilePath *path;
5890- gboolean cancelled = handle->cancelled;
5891- GtkFileChooserDefault *impl = data;
5892-
5893- if (handle != impl->shortcuts_activate_iter_handle)
5894- goto out;
5895-
5896- impl->shortcuts_activate_iter_handle = NULL;
5897-
5898- set_busy_cursor (impl, FALSE);
5899+ data = g_new0 (struct FileExistsData, 1);
5900+ data->impl = g_object_ref (impl);
5901+ data->path = gtk_file_path_copy (path);
5902+ data->parent_path = gtk_file_path_copy (_gtk_file_chooser_entry_get_current_folder (entry));
5903
5904- if (cancelled)
5905- goto out;
5906+ if (impl->file_exists_get_info_handle)
5907+ gtk_file_system_cancel_operation (impl->file_exists_get_info_handle);
5908
5909- if (error)
5910- {
5911- char *msg;
5912+ impl->file_exists_get_info_handle =
5913+ gtk_file_system_get_info (impl->file_system, path,
5914+ GTK_FILE_INFO_IS_FOLDER,
5915+ file_exists_get_info_cb,
5916+ data);
5917
5918- msg = g_strdup_printf (_("Could not mount %s"),
5919- gtk_file_system_volume_get_display_name (impl->file_system, volume));
5920- error_message (impl, msg, error->message);
5921- g_free (msg);
5922+ set_busy_cursor (impl, TRUE);
5923+ retval = FALSE;
5924
5925- goto out;
5926- }
5927+ if (error != NULL)
5928+ g_error_free (error);
5929+ }
5930
5931- path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
5932- if (path != NULL)
5933- {
5934- change_folder_and_display_error (impl, path, FALSE);
5935 gtk_file_path_free (path);
5936+ return retval;
5937 }
5938-
5939-out:
5940- g_object_unref (impl);
5941- g_object_unref (handle);
5942-}
5943-
5944-
5945-/* Activates a volume by mounting it if necessary and then switching to its
5946- * base path.
5947- */
5948-static void
5949-shortcuts_activate_volume (GtkFileChooserDefault *impl,
5950- GtkFileSystemVolume *volume)
5951-{
5952- GtkFilePath *path;
5953-
5954- /* We ref the file chooser since volume_mount() may run a main loop, and the
5955- * user could close the file chooser window in the meantime.
5956- */
5957- g_object_ref (impl);
5958-
5959- if (!gtk_file_system_volume_get_is_mounted (impl->file_system, volume))
5960+ else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view)
5961 {
5962- set_busy_cursor (impl, TRUE);
5963-
5964- impl->shortcuts_activate_iter_handle =
5965- gtk_file_system_volume_mount (impl->file_system, volume,
5966- shortcuts_activate_volume_mount_cb,
5967- g_object_ref (impl));
5968+ /* The focus is on a dialog's action area button, *and* the widget that
5969+ * was focused immediately before it is the file list.
5970+ */
5971+ goto file_list;
5972 }
5973- else
5974+ else if (impl->location_entry && impl->toplevel_last_focus_widget == impl->location_entry)
5975 {
5976- path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
5977- if (path != NULL)
5978- {
5979- change_folder_and_display_error (impl, path, FALSE);
5980- gtk_file_path_free (path);
5981- }
5982+ /* The focus is on a dialog's action area button, *and* the widget that
5983+ * was focused immediately before it is the location entry.
5984+ */
5985+ goto save_entry;
5986 }
5987-
5988- g_object_unref (impl);
5989-}
5990-
5991-/* Opens the folder or volume at the specified iter in the shortcuts model */
5992-struct ShortcutsActivateData
5993-{
5994- GtkFileChooserDefault *impl;
5995- GtkFilePath *path;
5996-};
5997-
5998-static void
5999-shortcuts_activate_get_info_cb (GtkFileSystemHandle *handle,
6000- const GtkFileInfo *info,
6001- const GError *error,
6002- gpointer user_data)
6003-{
6004- gboolean cancelled = handle->cancelled;
6005- struct ShortcutsActivateData *data = user_data;
6006-
6007- if (handle != data->impl->shortcuts_activate_iter_handle)
6008- goto out;
6009-
6010- data->impl->shortcuts_activate_iter_handle = NULL;
6011-
6012- if (cancelled)
6013- goto out;
6014-
6015- if (!error && gtk_file_info_get_is_folder (info))
6016- change_folder_and_display_error (data->impl, data->path, FALSE);
6017 else
6018- gtk_file_chooser_default_select_path (GTK_FILE_CHOOSER (data->impl), data->path, NULL);
6019-
6020-out:
6021- g_object_unref (data->impl);
6022- gtk_file_path_free (data->path);
6023- g_free (data);
6024+ /* The focus is on a dialog's action area button or something else */
6025+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
6026+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
6027+ goto save_entry;
6028+ else
6029+ goto file_list;
6030
6031- g_object_unref (handle);
6032+ g_assert_not_reached ();
6033+ return FALSE;
6034 }
6035
6036+/* Implementation for GtkFileChooserEmbed::initial_focus() */
6037 static void
6038-shortcuts_activate_iter (GtkFileChooserDefault *impl,
6039- GtkTreeIter *iter)
6040+gtk_file_chooser_default_initial_focus (GtkFileChooserEmbed *chooser_embed)
6041 {
6042- gpointer col_data;
6043- gboolean is_volume;
6044-
6045- if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY && impl->action != GTK_FILE_CHOOSER_ACTION_SAVE)
6046- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
6047-
6048- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), iter,
6049- SHORTCUTS_COL_DATA, &col_data,
6050- SHORTCUTS_COL_IS_VOLUME, &is_volume,
6051- -1);
6052+ GtkFileChooserDefault *impl;
6053+ GtkWidget *widget;
6054
6055- if (!col_data)
6056- return; /* We are on a separator */
6057+ impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
6058
6059- if (impl->shortcuts_activate_iter_handle)
6060+ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
6061+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
6062 {
6063- gtk_file_system_cancel_operation (impl->shortcuts_activate_iter_handle);
6064- impl->shortcuts_activate_iter_handle = NULL;
6065+ widget = impl->browse_files_tree_view;
6066 }
6067-
6068- if (is_volume)
6069+ else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
6070+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
6071 {
6072- GtkFileSystemVolume *volume;
6073-
6074- volume = col_data;
6075-
6076- shortcuts_activate_volume (impl, volume);
6077+ widget = impl->location_entry;
6078 }
6079 else
6080 {
6081- struct ShortcutsActivateData *data;
6082-
6083- data = g_new0 (struct ShortcutsActivateData, 1);
6084- data->impl = g_object_ref (impl);
6085- data->path = gtk_file_path_copy (col_data);
6086-
6087- impl->shortcuts_activate_iter_handle =
6088- gtk_file_system_get_info (impl->file_system, data->path,
6089- GTK_FILE_INFO_IS_FOLDER,
6090- shortcuts_activate_get_info_cb, data);
6091+ g_assert_not_reached ();
6092+ widget = NULL;
6093 }
6094+
6095+ g_assert (widget != NULL);
6096+ gtk_widget_grab_focus (widget);
6097 }
6098
6099-/* Callback used when a row in the shortcuts list is activated */
6100 static void
6101-shortcuts_row_activated_cb (GtkTreeView *tree_view,
6102- GtkTreePath *path,
6103- GtkTreeViewColumn *column,
6104- GtkFileChooserDefault *impl)
6105+set_current_filter (GtkFileChooserDefault *impl,
6106+ GtkFileFilter *filter)
6107 {
6108- GtkTreeIter iter;
6109- GtkTreeIter child_iter;
6110-
6111- if (!gtk_tree_model_get_iter (impl->shortcuts_filter_model, &iter, path))
6112- return;
6113-
6114- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model),
6115- &child_iter,
6116- &iter);
6117- shortcuts_activate_iter (impl, &child_iter);
6118+ if (impl->current_filter != filter)
6119+ {
6120+ int filter_index;
6121
6122- gtk_widget_grab_focus (impl->browse_files_tree_view);
6123-}
6124+ /* NULL filters are allowed to reset to non-filtered status
6125+ */
6126+ filter_index = g_slist_index (impl->filters, filter);
6127+ if (impl->filters && filter && filter_index < 0)
6128+ return;
6129
6130-/* Handler for GtkWidget::key-press-event on the shortcuts list */
6131-static gboolean
6132-shortcuts_key_press_event_cb (GtkWidget *widget,
6133- GdkEventKey *event,
6134- GtkFileChooserDefault *impl)
6135-{
6136- guint modifiers;
6137+ if (impl->current_filter)
6138+ g_object_unref (impl->current_filter);
6139+ impl->current_filter = filter;
6140+ if (impl->current_filter)
6141+ {
6142+ g_object_ref_sink (impl->current_filter);
6143+ }
6144
6145- modifiers = gtk_accelerator_get_default_mod_mask ();
6146+ if (impl->filters)
6147+ gtk_combo_box_set_active (GTK_COMBO_BOX (impl->filter_combo),
6148+ filter_index);
6149
6150- if ((event->keyval == GDK_BackSpace
6151- || event->keyval == GDK_Delete
6152- || event->keyval == GDK_KP_Delete)
6153- && (event->state & modifiers) == 0)
6154- {
6155- remove_selected_bookmarks (impl);
6156- return TRUE;
6157- }
6158+ if (impl->browse_files_model)
6159+ install_list_model_filter (impl);
6160
6161- if ((event->keyval == GDK_F2)
6162- && (event->state & modifiers) == 0)
6163- {
6164- rename_selected_bookmark (impl);
6165- return TRUE;
6166+ g_object_notify (G_OBJECT (impl), "filter");
6167 }
6168-
6169- return FALSE;
6170 }
6171
6172-static gboolean
6173-shortcuts_select_func (GtkTreeSelection *selection,
6174- GtkTreeModel *model,
6175- GtkTreePath *path,
6176- gboolean path_currently_selected,
6177- gpointer data)
6178+static void
6179+filter_combo_changed (GtkComboBox *combo_box,
6180+ GtkFileChooserDefault *impl)
6181 {
6182- GtkFileChooserDefault *impl = data;
6183+ gint new_index = gtk_combo_box_get_active (combo_box);
6184+ GtkFileFilter *new_filter = g_slist_nth_data (impl->filters, new_index);
6185
6186- return (*gtk_tree_path_get_indices (path) != shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR));
6187+ set_current_filter (impl, new_filter);
6188 }
6189
6190 static gboolean
6191@@ -8373,8 +4515,6 @@
6192
6193 if (impl->location_entry)
6194 update_chooser_entry (impl);
6195- check_preview_change (impl);
6196- bookmarks_check_add_sensitivity (impl);
6197
6198 g_signal_emit_by_name (impl, "selection-changed", 0);
6199 }
6200@@ -8401,7 +4541,8 @@
6201 const GtkFilePath *file_path;
6202
6203 file_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter);
6204- change_folder_and_display_error (impl, file_path, FALSE);
6205+
6206+ change_folder_and_display_error (impl, file_path);
6207
6208 return;
6209 }
6210@@ -8411,27 +4552,6 @@
6211 g_signal_emit_by_name (impl, "file-activated");
6212 }
6213
6214-static void
6215-path_bar_clicked (GtkPathBar *path_bar,
6216- GtkFilePath *file_path,
6217- GtkFilePath *child_path,
6218- gboolean child_is_hidden,
6219- GtkFileChooserDefault *impl)
6220-{
6221- if (child_path)
6222- pending_select_paths_add (impl, child_path);
6223-
6224- if (!change_folder_and_display_error (impl, file_path, FALSE))
6225- return;
6226-
6227- /* Say we have "/foo/bar/[.baz]" and the user clicks on "bar". We should then
6228- * show hidden files so that ".baz" appears in the file list, as it will still
6229- * be shown in the path bar: "/foo/[bar]/.baz"
6230- */
6231- if (child_is_hidden)
6232- g_object_set (impl, "show-hidden", TRUE, NULL);
6233-}
6234-
6235 static const GtkFileInfo *
6236 get_list_file_info (GtkFileChooserDefault *impl,
6237 GtkTreeIter *iter)
6238@@ -8659,210 +4779,73 @@
6239 NULL);
6240 }
6241
6242-static void
6243-location_set_user_text (GtkFileChooserDefault *impl,
6244- const gchar *path)
6245-{
6246- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), path);
6247- gtk_editable_set_position (GTK_EDITABLE (impl->location_entry), -1);
6248-}
6249-
6250-static void
6251-location_popup_handler (GtkFileChooserDefault *impl,
6252- const gchar *path)
6253-{
6254- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
6255- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
6256- {
6257- LocationMode new_mode;
6258-
6259- if (path != NULL)
6260- {
6261- /* since the user typed something, we unconditionally want to turn on the entry */
6262- new_mode = LOCATION_MODE_FILENAME_ENTRY;
6263- }
6264- else if (impl->location_mode == LOCATION_MODE_PATH_BAR)
6265- new_mode = LOCATION_MODE_FILENAME_ENTRY;
6266- else if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
6267- new_mode = LOCATION_MODE_PATH_BAR;
6268- else
6269- {
6270- g_assert_not_reached ();
6271- return;
6272- }
6273-
6274- location_mode_set (impl, new_mode, TRUE);
6275- if (new_mode == LOCATION_MODE_FILENAME_ENTRY)
6276- {
6277- if (path != NULL)
6278- location_set_user_text (impl, path);
6279- else
6280- {
6281- location_entry_set_initial_text (impl);
6282- gtk_editable_select_region (GTK_EDITABLE (impl->location_entry), 0, -1);
6283- }
6284- }
6285- }
6286- else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
6287- || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
6288- {
6289- gtk_widget_grab_focus (impl->location_entry);
6290- if (path != NULL)
6291- location_set_user_text (impl, path);
6292- }
6293- else
6294- g_assert_not_reached ();
6295-}
6296-
6297 /* Handler for the "up-folder" keybinding signal */
6298 static void
6299 up_folder_handler (GtkFileChooserDefault *impl)
6300 {
6301- _gtk_path_bar_up (GTK_PATH_BAR (impl->browse_path_bar));
6302+ GtkFilePath * parent;
6303+ pending_select_paths_add (impl, impl->current_folder);
6304+
6305+ if (gtk_file_system_get_parent (impl->file_system, impl->current_folder,
6306+ &parent, NULL) && parent)
6307+ {
6308+ impl->path_history = g_slist_prepend (impl->path_history,
6309+ gtk_file_path_copy (impl->current_folder));
6310+
6311+ change_folder_and_display_error (impl, parent);
6312+ gtk_file_path_free (parent);
6313+ }
6314 }
6315
6316 /* Handler for the "down-folder" keybinding signal */
6317 static void
6318 down_folder_handler (GtkFileChooserDefault *impl)
6319 {
6320- _gtk_path_bar_down (GTK_PATH_BAR (impl->browse_path_bar));
6321-}
6322-
6323-/* Switches to the shortcut in the specified index */
6324-static void
6325-switch_to_shortcut (GtkFileChooserDefault *impl,
6326- int pos)
6327-{
6328- GtkTreeIter iter;
6329-
6330- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->shortcuts_model), &iter, NULL, pos))
6331- g_assert_not_reached ();
6332-
6333- shortcuts_activate_iter (impl, &iter);
6334+ if (impl->path_history)
6335+ {
6336+ GtkFilePath * path = impl->path_history->data;
6337+
6338+ change_folder_and_display_error (impl, path);
6339+ impl->path_history = g_slist_remove (impl->path_history, path);
6340+ gtk_file_path_free (path);
6341+ }
6342 }
6343
6344 /* Handler for the "home-folder" keybinding signal */
6345 static void
6346 home_folder_handler (GtkFileChooserDefault *impl)
6347 {
6348- if (impl->has_home)
6349- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_HOME));
6350-}
6351-
6352-/* Handler for the "desktop-folder" keybinding signal */
6353-static void
6354-desktop_folder_handler (GtkFileChooserDefault *impl)
6355-{
6356- if (impl->has_desktop)
6357- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_DESKTOP));
6358-}
6359-
6360-static void
6361-quick_bookmark_handler (GtkFileChooserDefault *impl,
6362- gint bookmark_index)
6363-{
6364- int bookmark_pos;
6365- GtkTreePath *path;
6366-
6367- if (bookmark_index < 0 || bookmark_index >= impl->num_bookmarks)
6368- return;
6369-
6370- bookmark_pos = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS) + bookmark_index;
6371-
6372- path = gtk_tree_path_new_from_indices (bookmark_pos, -1);
6373- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
6374- path, NULL,
6375- FALSE, 0.0, 0.0);
6376- gtk_tree_path_free (path);
6377-
6378- switch_to_shortcut (impl, bookmark_pos);
6379 }
6380
6381 static void
6382 show_hidden_handler (GtkFileChooserDefault *impl)
6383 {
6384- g_object_set (impl,
6385- "show-hidden", !impl->show_hidden,
6386- NULL);
6387-}
6388-
6389-
6390-/* Drag and drop interfaces */
6391-
6392-static void
6393-_shortcuts_model_filter_class_init (ShortcutsModelFilterClass *class)
6394-{
6395 }
6396
6397-static void
6398-_shortcuts_model_filter_init (ShortcutsModelFilter *model)
6399+static GtkFilePath *
6400+gtk_file_chooser_default_get_preview_path (GtkFileChooser *chooser)
6401 {
6402- model->impl = NULL;
6403+ return NULL;
6404 }
6405
6406-/* GtkTreeDragSource::row_draggable implementation for the shortcuts filter model */
6407 static gboolean
6408-shortcuts_model_filter_row_draggable (GtkTreeDragSource *drag_source,
6409- GtkTreePath *path)
6410+gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser,
6411+ const GtkFilePath *path,
6412+ GError **error)
6413 {
6414- ShortcutsModelFilter *model;
6415- int pos;
6416- int bookmarks_pos;
6417-
6418- model = SHORTCUTS_MODEL_FILTER (drag_source);
6419-
6420- pos = *gtk_tree_path_get_indices (path);
6421- bookmarks_pos = shortcuts_get_index (model->impl, SHORTCUTS_BOOKMARKS);
6422-
6423- return (pos >= bookmarks_pos && pos < bookmarks_pos + model->impl->num_bookmarks);
6424+ return FALSE;
6425 }
6426
6427-/* GtkTreeDragSource::drag_data_get implementation for the shortcuts filter model */
6428 static gboolean
6429-shortcuts_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
6430- GtkTreePath *path,
6431- GtkSelectionData *selection_data)
6432-{
6433- ShortcutsModelFilter *model;
6434-
6435- model = SHORTCUTS_MODEL_FILTER (drag_source);
6436-
6437- /* FIXME */
6438-
6439- return FALSE;
6440-}
6441-
6442-/* Fill the GtkTreeDragSourceIface vtable */
6443-static void
6444-shortcuts_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface)
6445+gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser,
6446+ const GtkFilePath *path,
6447+ GError **error)
6448 {
6449- iface->row_draggable = shortcuts_model_filter_row_draggable;
6450- iface->drag_data_get = shortcuts_model_filter_drag_data_get;
6451+ return TRUE;
6452 }
6453
6454-#if 0
6455-/* Fill the GtkTreeDragDestIface vtable */
6456-static void
6457-shortcuts_model_filter_drag_dest_iface_init (GtkTreeDragDestIface *iface)
6458+static GSList *
6459+gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser)
6460 {
6461- iface->drag_data_received = shortcuts_model_filter_drag_data_received;
6462- iface->row_drop_possible = shortcuts_model_filter_row_drop_possible;
6463-}
6464-#endif
6465-
6466-static GtkTreeModel *
6467-shortcuts_model_filter_new (GtkFileChooserDefault *impl,
6468- GtkTreeModel *child_model,
6469- GtkTreePath *root)
6470-{
6471- ShortcutsModelFilter *model;
6472-
6473- model = g_object_new (SHORTCUTS_MODEL_FILTER_TYPE,
6474- "child-model", child_model,
6475- "virtual-root", root,
6476- NULL);
6477-
6478- model->impl = impl;
6479-
6480- return GTK_TREE_MODEL (model);
6481+ return NULL;
6482 }
6483Index: gtk+-2.10.14/gtk/gtkfilechooserprivate.h
6484===================================================================
6485--- gtk+-2.10.14.orig/gtk/gtkfilechooserprivate.h 2007-07-16 20:44:17.000000000 +0100
6486+++ gtk+-2.10.14/gtk/gtkfilechooserprivate.h 2007-08-29 18:02:50.000000000 +0100
6487@@ -153,36 +153,19 @@
6488
6489 /* Save mode widgets */
6490 GtkWidget *save_widgets;
6491-
6492- GtkWidget *save_folder_label;
6493- GtkWidget *save_folder_combo;
6494- GtkWidget *save_expander;
6495+ GtkWidget *save_file_name_entry;
6496
6497 /* The file browsing widgets */
6498 GtkWidget *browse_widgets;
6499- GtkWidget *browse_shortcuts_tree_view;
6500- GtkWidget *browse_shortcuts_add_button;
6501- GtkWidget *browse_shortcuts_remove_button;
6502- GtkWidget *browse_shortcuts_popup_menu;
6503- GtkWidget *browse_shortcuts_popup_menu_remove_item;
6504- GtkWidget *browse_shortcuts_popup_menu_rename_item;
6505 GtkWidget *browse_files_tree_view;
6506- GtkWidget *browse_files_popup_menu;
6507- GtkWidget *browse_files_popup_menu_add_shortcut_item;
6508- GtkWidget *browse_files_popup_menu_hidden_files_item;
6509 GtkWidget *browse_new_folder_button;
6510- GtkWidget *browse_path_bar;
6511+ GtkWidget *bar;
6512+ GtkWidget *up_button;
6513
6514 GtkFileSystemModel *browse_files_model;
6515- char *browse_files_last_selected_name;
6516+ char *browse_files_last_selected_name; /* ??? */
6517
6518- GtkWidget *filter_combo_hbox;
6519 GtkWidget *filter_combo;
6520- GtkWidget *preview_box;
6521- GtkWidget *preview_label;
6522- GtkWidget *preview_widget;
6523- GtkWidget *extra_align;
6524- GtkWidget *extra_widget;
6525
6526 GtkWidget *location_button;
6527 GtkWidget *location_entry_box;
6528@@ -198,7 +181,6 @@
6529 /* Handles */
6530 GSList *loading_shortcuts;
6531 GSList *reload_icon_handles;
6532- GtkFileSystemHandle *file_list_drag_data_received_handle;
6533 GtkFileSystemHandle *update_current_folder_handle;
6534 GtkFileSystemHandle *show_and_select_paths_handle;
6535 GtkFileSystemHandle *should_respond_get_info_handle;
6536@@ -212,29 +194,24 @@
6537 guint load_timeout_id;
6538
6539 GSList *pending_select_paths;
6540+ GSList *path_history;
6541
6542 GtkFileFilter *current_filter;
6543 GSList *filters;
6544
6545 GtkTooltips *tooltips;
6546
6547- gboolean has_home;
6548- gboolean has_desktop;
6549-
6550 int num_volumes;
6551- int num_shortcuts;
6552- int num_bookmarks;
6553
6554 gulong volumes_changed_id;
6555- gulong bookmarks_changed_id;
6556
6557 GtkFilePath *current_volume_path;
6558 GtkFilePath *current_folder;
6559- GtkFilePath *preview_path;
6560- char *preview_display_name;
6561
6562 GtkTreeViewColumn *list_name_column;
6563 GtkCellRenderer *list_name_renderer;
6564+ guint32 list_press_time;
6565+ GtkTreePath *list_press_path;
6566
6567 GSource *edited_idle;
6568 char *edited_new_text;
6569@@ -245,10 +222,7 @@
6570 gulong toplevel_set_focus_id;
6571 GtkWidget *toplevel_last_focus_widget;
6572
6573-#if 0
6574- GdkDragContext *shortcuts_drag_context;
6575- GSource *shortcuts_drag_outside_idle;
6576-#endif
6577+ gchar * root_folder;
6578
6579 gint default_width;
6580 gint default_height;
6581@@ -256,19 +230,13 @@
6582 /* Flags */
6583
6584 guint local_only : 1;
6585- guint preview_widget_active : 1;
6586- guint use_preview_label : 1;
6587 guint select_multiple : 1;
6588 guint show_hidden : 1;
6589+ guint show_create_folder : 1;
6590 guint do_overwrite_confirmation : 1;
6591 guint list_sort_ascending : 1;
6592 guint changing_folder : 1;
6593- guint shortcuts_current_folder_active : 1;
6594 guint expand_folders : 1;
6595-
6596-#if 0
6597- guint shortcuts_drag_outside : 1;
6598-#endif
6599 };
6600
6601
6602Index: gtk+-2.10.14/tests/autotestfilechooser.c
6603===================================================================
6604--- gtk+-2.10.14.orig/tests/autotestfilechooser.c 2007-07-16 20:45:12.000000000 +0100
6605+++ gtk+-2.10.14/tests/autotestfilechooser.c 2007-08-28 15:19:31.000000000 +0100
6606@@ -452,9 +452,6 @@
6607 && (impl->location_mode == LOCATION_MODE_PATH_BAR
6608 ? impl->location_entry == NULL
6609 : impl->location_entry != NULL)
6610- && impl->save_folder_label == NULL
6611- && impl->save_folder_combo == NULL
6612- && impl->save_expander == NULL
6613 && GTK_IS_CONTAINER (impl->browse_widgets) && GTK_WIDGET_DRAWABLE (impl->browse_widgets));
6614 }
6615 else if (has_action (save_actions, G_N_ELEMENTS (save_actions), impl->action))
6616@@ -465,9 +462,6 @@
6617 */
6618 passed = passed && (GTK_IS_CONTAINER (impl->save_widgets) && GTK_WIDGET_DRAWABLE (impl->save_widgets)
6619 && impl->location_entry != NULL && GTK_WIDGET_DRAWABLE (impl->location_entry)
6620- && GTK_IS_LABEL (impl->save_folder_label) && GTK_WIDGET_DRAWABLE (impl->save_folder_label)
6621- && GTK_IS_COMBO_BOX (impl->save_folder_combo) && GTK_WIDGET_DRAWABLE (impl->save_folder_combo)
6622- && GTK_IS_EXPANDER (impl->save_expander) && GTK_WIDGET_DRAWABLE (impl->save_expander)
6623 && GTK_IS_CONTAINER (impl->browse_widgets));
6624
6625 /* FIXME: we are in a SAVE mode; test the visibility and sensitivity of
6626@@ -968,11 +962,6 @@
6627 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), base_dir);
6628 sleep_in_main_loop (500);
6629
6630- g_signal_emit_by_name (impl->browse_path_bar, "path-clicked",
6631- (GtkFilePath *) cwd_path,
6632- (GtkFilePath *) base_dir_path,
6633- FALSE);
6634- sleep_in_main_loop (500);
6635 passed = passed && (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == txt_filter);
6636
6637 log_test (passed, "test_folder_switch_and_filters(): filter after changing folder");
diff --git a/meta/packages/gtk+/gtk+-2.10.14/filechooser-respect-style.patch b/meta/packages/gtk+/gtk+-2.10.14/filechooser-respect-style.patch
new file mode 100644
index 0000000000..0de8e02dce
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.10.14/filechooser-respect-style.patch
@@ -0,0 +1,77 @@
1Index: gtk+-2.10.14/gtk/gtkfilechooserdialog.c
2===================================================================
3--- gtk+-2.10.14.orig/gtk/gtkfilechooserdialog.c 2007-08-29 18:03:04.000000000 +0100
4+++ gtk+-2.10.14/gtk/gtkfilechooserdialog.c 2007-08-29 18:04:27.000000000 +0100
5@@ -50,8 +50,6 @@
6
7 static void gtk_file_chooser_dialog_map (GtkWidget *widget);
8 static void gtk_file_chooser_dialog_unmap (GtkWidget *widget);
9-static void gtk_file_chooser_dialog_style_set (GtkWidget *widget,
10- GtkStyle *previous_style);
11
12 static void response_cb (GtkDialog *dialog,
13 gint response_id);
14@@ -73,7 +71,6 @@
15
16 widget_class->map = gtk_file_chooser_dialog_map;
17 widget_class->unmap = gtk_file_chooser_dialog_unmap;
18- widget_class->style_set = gtk_file_chooser_dialog_style_set;
19
20 _gtk_file_chooser_install_properties (gobject_class);
21
22@@ -86,10 +83,16 @@
23 GtkFileChooserDialogPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog,
24 GTK_TYPE_FILE_CHOOSER_DIALOG,
25 GtkFileChooserDialogPrivate);
26+
27+ GtkDialog *fc_dialog = GTK_DIALOG (dialog);
28+
29 dialog->priv = priv;
30 dialog->priv->response_requested = FALSE;
31
32- gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
33+ gtk_dialog_set_has_separator (fc_dialog, FALSE);
34+ gtk_container_set_border_width (GTK_CONTAINER (fc_dialog), 5);
35+ gtk_box_set_spacing (GTK_BOX (fc_dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
36+ gtk_container_set_border_width (GTK_CONTAINER (fc_dialog->action_area), 5);
37
38 /* We do a signal connection here rather than overriding the method in
39 * class_init because GtkDialog::response is a RUN_LAST signal. We want *our*
40@@ -285,6 +288,7 @@
41 g_signal_connect (priv->widget, "response-requested",
42 G_CALLBACK (file_chooser_widget_response_requested), object);
43
44+ gtk_container_set_border_width (GTK_CONTAINER (priv->widget), 5);
45 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (object)->vbox), priv->widget, TRUE, TRUE, 0);
46
47 gtk_widget_show (priv->widget);
48@@ -414,29 +418,6 @@
49 gtk_widget_unmap (priv->widget);
50 }
51
52-static void
53-gtk_file_chooser_dialog_style_set (GtkWidget *widget,
54- GtkStyle *previous_style)
55-{
56- GtkDialog *dialog;
57-
58- if (GTK_WIDGET_CLASS (gtk_file_chooser_dialog_parent_class)->style_set)
59- GTK_WIDGET_CLASS (gtk_file_chooser_dialog_parent_class)->style_set (widget, previous_style);
60-
61- dialog = GTK_DIALOG (widget);
62-
63- /* Override the style properties with HIG-compliant spacings. Ugh.
64- * http://developer.gnome.org/projects/gup/hig/1.0/layout.html#layout-dialogs
65- * http://developer.gnome.org/projects/gup/hig/1.0/windows.html#alert-spacing
66- */
67-
68- gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 12);
69- gtk_box_set_spacing (GTK_BOX (dialog->vbox), 24);
70-
71- gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 0);
72- gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
73-}
74-
75 /* GtkDialog::response handler */
76 static void
77 response_cb (GtkDialog *dialog,
diff --git a/meta/packages/gtk+/gtk+-2.10.14/filechooser-utils.patch b/meta/packages/gtk+/gtk+-2.10.14/filechooser-utils.patch
new file mode 100644
index 0000000000..c22ccba377
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.10.14/filechooser-utils.patch
@@ -0,0 +1,32 @@
1Index: gtk+-2.10.14/gtk/gtkfilechooserutils.h
2===================================================================
3--- gtk+-2.10.14.orig/gtk/gtkfilechooserutils.h 2007-08-24 08:37:40.000000000 +0100
4+++ gtk+-2.10.14/gtk/gtkfilechooserutils.h 2007-08-24 08:51:59.000000000 +0100
5@@ -41,7 +41,9 @@
6 GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE,
7 GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN,
8 GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION,
9- GTK_FILE_CHOOSER_PROP_LAST = GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION
10+ GTK_FILE_CHOOSER_PROP_ROOT_FOLDER,
11+ GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER,
12+ GTK_FILE_CHOOSER_PROP_LAST = GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER
13 } GtkFileChooserProp;
14
15 void _gtk_file_chooser_install_properties (GObjectClass *klass);
16Index: gtk+-2.10.14/gtk/gtkfilechooserutils.c
17===================================================================
18--- gtk+-2.10.14.orig/gtk/gtkfilechooserutils.c 2007-08-24 08:37:28.000000000 +0100
19+++ gtk+-2.10.14/gtk/gtkfilechooserutils.c 2007-08-24 08:51:47.000000000 +0100
20@@ -117,6 +117,12 @@
21 g_object_class_override_property (klass,
22 GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION,
23 "do-overwrite-confirmation");
24+ g_object_class_override_property (klass,
25+ GTK_FILE_CHOOSER_PROP_ROOT_FOLDER,
26+ "root-folder");
27+ g_object_class_override_property (klass,
28+ GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER,
29+ "show-create-folder");
30 }
31
32 /**
diff --git a/meta/packages/gtk+/gtk+-2.10.14/filechooser.patch b/meta/packages/gtk+/gtk+-2.10.14/filechooser.patch
new file mode 100644
index 0000000000..bb09049865
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.10.14/filechooser.patch
@@ -0,0 +1,25 @@
1Index: gtk+-2.10.14/gtk/gtkfilechooser.c
2===================================================================
3--- gtk+-2.10.14.orig/gtk/gtkfilechooser.c 2007-08-24 08:52:32.000000000 +0100
4+++ gtk+-2.10.14/gtk/gtkfilechooser.c 2007-08-24 08:57:21.000000000 +0100
5@@ -272,6 +272,20 @@
6 "if necessary."),
7 FALSE,
8 GTK_PARAM_READWRITE));
9+
10+ g_object_interface_install_property (g_iface,
11+ g_param_spec_string ("root-folder",
12+ P_("File System Root"),
13+ P_("Root folder for the file system below which the user should not be able to switch"),
14+ NULL,
15+ G_PARAM_WRITABLE));
16+
17+ g_object_interface_install_property (g_iface,
18+ g_param_spec_boolean ("show-create-folder",
19+ P_("Show Create Folder button"),
20+ P_("Whether the Create Folder button should be visible on the bar"),
21+ TRUE,
22+ G_PARAM_READWRITE));
23 }
24
25 /**
diff --git a/meta/packages/gtk+/gtk+-2.10.14/filesystem-volumes.patch b/meta/packages/gtk+/gtk+-2.10.14/filesystem-volumes.patch
new file mode 100644
index 0000000000..ec15ea3f5d
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.10.14/filesystem-volumes.patch
@@ -0,0 +1,198 @@
1Index: gtk+-2.10.14/gtk/gtkfilesystemunix.c
2===================================================================
3--- gtk+-2.10.14.orig/gtk/gtkfilesystemunix.c 2007-07-16 20:44:17.000000000 +0100
4+++ gtk+-2.10.14/gtk/gtkfilesystemunix.c 2007-08-24 08:29:43.000000000 +0100
5@@ -38,6 +38,7 @@
6 #include <errno.h>
7 #include <string.h>
8 #include <sys/stat.h>
9+#include <sys/statvfs.h>
10 #include <sys/types.h>
11 #include <pwd.h>
12 #ifdef HAVE_UNISTD_H
13@@ -475,7 +476,55 @@
14 static GSList *
15 gtk_file_system_unix_list_volumes (GtkFileSystem *file_system)
16 {
17- return g_slist_append (NULL, get_root_volume ());
18+ struct statvfs stv;
19+ struct stat st;
20+ GSList * l = g_slist_append (NULL, get_root_volume ());
21+
22+ if (!statvfs ("/.", &stv))
23+ {
24+ fsblkcnt_t root_blocks = stv.f_blocks;
25+ fsfilcnt_t root_files = stv.f_files;
26+
27+ GDir * dir;
28+ if ((dir = g_dir_open ("/media", 0, NULL)) != NULL)
29+ {
30+ const gchar * name;
31+ while ((name = g_dir_read_name (dir)) != NULL)
32+ {
33+ gchar * abs_name;
34+
35+ /* Skip ram disks */
36+ if (!strcmp (name, "ram"))
37+ continue;
38+
39+ abs_name = g_strconcat ("/media/", name, NULL);
40+
41+ if (!stat (abs_name, &st) && S_ISDIR (st.st_mode))
42+ {
43+ gchar * dot = g_strconcat (abs_name, "/.", NULL);
44+ if (!statvfs (dot, &stv) &&
45+ (stv.f_blocks != root_blocks ||
46+ stv.f_files != root_files))
47+ {
48+ GtkFilePath * path =
49+ gtk_file_system_filename_to_path (file_system,
50+ abs_name);
51+
52+ if (path)
53+ l = g_slist_append (l, path);
54+ }
55+
56+ g_free (dot);
57+ }
58+
59+ g_free (abs_name);
60+ }
61+
62+ g_dir_close (dir);
63+ }
64+ }
65+
66+ return l;
67 }
68
69 static GtkFileSystemVolume *
70@@ -489,13 +538,18 @@
71 remove_trailing_slash (const char *filename)
72 {
73 int len;
74-
75+
76 len = strlen (filename);
77
78- if (len > 1 && filename[len - 1] == '/')
79- return g_strndup (filename, len - 1);
80- else
81- return g_memdup (filename, len + 1);
82+ if (len > 1)
83+ {
84+ gchar *c = g_utf8_prev_char (filename + len);
85+
86+ if (c && *c == '/')
87+ return g_strndup (filename, len - 1);
88+ }
89+
90+ return g_memdup (filename, len + 1);
91 }
92
93 /* Delay callback dispatching
94@@ -1143,7 +1197,7 @@
95 gtk_file_system_unix_volume_get_base_path (GtkFileSystem *file_system,
96 GtkFileSystemVolume *volume)
97 {
98- return gtk_file_path_new_dup ("/");
99+ return gtk_file_path_copy ((GtkFilePath*)volume);
100 }
101
102 static gboolean
103@@ -1177,7 +1231,32 @@
104 gtk_file_system_unix_volume_get_display_name (GtkFileSystem *file_system,
105 GtkFileSystemVolume *volume)
106 {
107- return g_strdup (_("File System")); /* Same as Nautilus */
108+ gchar * slash;
109+ gchar * path;
110+ gchar * c;
111+
112+ g_return_val_if_fail (file_system && volume, NULL);
113+
114+ path = gtk_file_system_path_to_filename (file_system, (GtkFilePath*) volume);
115+
116+ g_return_val_if_fail (path && *path, NULL);
117+
118+ if (path[0] == '/' && !path[1])
119+ return g_strdup (_("Filesystem")); /* Same as Nautilus */
120+
121+ /* Now the media volumes */
122+ /* strip trailing / if any */
123+ c = g_utf8_prev_char (path + strlen(path));
124+
125+ if (*c == '/')
126+ *c = 0;
127+
128+ slash = g_utf8_strrchr (path, -1, '/');
129+
130+ if (!slash)
131+ return g_strdup (path);
132+
133+ return g_strdup (slash + 1);
134 }
135
136 static IconType
137@@ -1265,10 +1344,57 @@
138 GtkFileSystemVolume *volume,
139 GError **error)
140 {
141- /* FIXME: maybe we just always want to return GTK_STOCK_HARDDISK here?
142- * or the new tango icon name?
143- */
144- return g_strdup ("gnome-dev-harddisk");
145+ gchar * c;
146+ gchar * slash;
147+ gchar * path = NULL;
148+ GtkFilePath * fpath;
149+ const gchar * id = NULL;
150+
151+ g_return_val_if_fail (file_system && volume, NULL);
152+
153+ fpath = gtk_file_system_volume_get_base_path (file_system, volume);
154+
155+ if (!fpath)
156+ goto out;
157+
158+ path = gtk_file_system_path_to_filename (file_system, fpath);
159+ gtk_file_path_free (fpath);
160+
161+ if (!path || !*path || (*path == '/' && !path[1]))
162+ goto out;
163+
164+ /* Now the media volumes */
165+ /* strip trailing / if any */
166+ c = g_utf8_prev_char (path + strlen(path));
167+
168+ if (*c == '/')
169+ *c = 0;
170+
171+ slash = g_utf8_strrchr (path, -1, '/');
172+
173+ if (slash)
174+ {
175+ slash++;
176+
177+ if (!strcmp (slash, "card"))
178+ id = "gnome-dev-media-sdmmc";
179+ else if (!strcmp (slash, "cf"))
180+ id = "gnome-dev-media-cf";
181+ else if (!strncmp (slash, "mmc", 3))
182+ id = "gnome-dev-media-sdmmc";
183+ else if (!strcmp (slash, "usbhdd"))
184+ id = "gnome-dev-removable-usb";
185+ else
186+ id = "gnome-dev-removable";
187+ }
188+
189+ out:
190+ g_free (path);
191+
192+ if (!id)
193+ id = "gnome-fs-blockdev";
194+
195+ return g_strdup (id);
196 }
197
198 static char *
diff --git a/meta/packages/gtk+/gtk+_2.10.14.bb b/meta/packages/gtk+/gtk+_2.10.14.bb
index 0140286173..6ef8253491 100644
--- a/meta/packages/gtk+/gtk+_2.10.14.bb
+++ b/meta/packages/gtk+/gtk+_2.10.14.bb
@@ -1,7 +1,7 @@
1require gtk+.inc 1require gtk+.inc
2 2
3DEPENDS += "cairo" 3DEPENDS += "cairo"
4PR = "r12" 4PR = "r13"
5 5
6# disable per default - untested and not all patches included. 6# disable per default - untested and not all patches included.
7DEFAULT_PREFERENCE = "-1" 7DEFAULT_PREFERENCE = "-1"
@@ -24,12 +24,18 @@ SRC_URI = "ftp://ftp.gtk.org/pub/gtk/v2.10/gtk+-${PV}.tar.bz2 \
24 file://toggle-font.diff;patch=1;pnum=0 \ 24 file://toggle-font.diff;patch=1;pnum=0 \
25 file://combo-arrow-size.patch;patch=1;pnum=0 \ 25 file://combo-arrow-size.patch;patch=1;pnum=0 \
26 file://range-no-redraw.patch;patch=1;pnum=0 \ 26 file://range-no-redraw.patch;patch=1;pnum=0 \
27 file://scrolled-placement.patch;patch=1;pnum=0" 27 file://scrolled-placement.patch;patch=1;pnum=0 \
28# file://scroll-timings.patch;patch=1 \ 28# file://scroll-timings.patch;patch=1 \
29# file://pangoxft2.10.6.diff;patch=1" 29# file://pangoxft2.10.6.diff;patch=1"
30# file://gtk+-handhelds.patch;patch=1 30# file://gtk+-handhelds.patch;patch=1
31# file://single-click.patch;patch=1 31# file://single-click.patch;patch=1
32# file://spinbutton.patch;patch=1 \ 32# file://spinbutton.patch;patch=1 \
33 file://filesystem-volumes.patch;patch=1\
34 file://filechooser-utils.patch;patch=1\
35 file://filechooser.patch;patch=1\
36 file://filechooser-default.patch;patch=1\
37 file://filechooser-respect-style.patch;patch=1"
38
33 39
34EXTRA_OECONF = "--without-libtiff --disable-xkb --disable-glibtest --enable-display-migration" 40EXTRA_OECONF = "--without-libtiff --disable-xkb --disable-glibtest --enable-display-migration"
35 41