summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Frydrych <tf@openedhand.com>2007-02-09 13:16:38 +0000
committerTomas Frydrych <tf@openedhand.com>2007-02-09 13:16:38 +0000
commit19d07794eed15aad348bb6c8b4514936b49a421a (patch)
tree01197036b61759006f6dfefdbf4ec347bfb159d7
parent2f9b5a87f732dbe9cabab188596956e919638f47 (diff)
downloadopenembedded-core-19d07794eed15aad348bb6c8b4514936b49a421a.tar.gz
openembedded-core-19d07794eed15aad348bb6c8b4514936b49a421a.tar.bz2
openembedded-core-19d07794eed15aad348bb6c8b4514936b49a421a.zip
simplified filechooser dialog
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@1266 311d38ba-8fff-0310-9ca6-ca027cbcb966
-rw-r--r--meta/packages/gtk+/gtk+-2.6.8/filechooser-default.patch5152
-rw-r--r--meta/packages/gtk+/gtk+-2.6.8/filechooser-respect-style.patch77
-rw-r--r--meta/packages/gtk+/gtk+_2.6.8.bb6
3 files changed, 5233 insertions, 2 deletions
diff --git a/meta/packages/gtk+/gtk+-2.6.8/filechooser-default.patch b/meta/packages/gtk+/gtk+-2.6.8/filechooser-default.patch
new file mode 100644
index 0000000000..d4534212a0
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.6.8/filechooser-default.patch
@@ -0,0 +1,5152 @@
+--- gtk+-2.6.8/gtk/gtkfilechooserdefault.c.orig 2007-02-09 12:28:31.000000000 +0000
++++ gtk+-2.6.8/gtk/gtkfilechooserdefault.c 2007-02-09 12:28:31.000000000 +0000
+@@ -31,7 +31,6 @@
+ #include "gtkcombobox.h"
+ #include "gtkentry.h"
+ #include "gtkeventbox.h"
+-#include "gtkexpander.h"
+ #include "gtkfilechooserdefault.h"
+ #include "gtkfilechooserembed.h"
+ #include "gtkfilechooserentry.h"
+@@ -50,7 +49,6 @@
+ #include "gtkmarshalers.h"
+ #include "gtkmenuitem.h"
+ #include "gtkmessagedialog.h"
+-#include "gtkpathbar.h"
+ #include "gtkprivate.h"
+ #include "gtkscrolledwindow.h"
+ #include "gtkseparatormenuitem.h"
+@@ -79,18 +77,23 @@
+ #include <string.h>
+ #include <time.h>
+
++#define DEFAULT_SPACING 5
++
++#define GTK26
+ typedef struct _GtkFileChooserDefaultClass GtkFileChooserDefaultClass;
+
+ #define GTK_FILE_CHOOSER_DEFAULT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_CHOOSER_DEFAULT, GtkFileChooserDefaultClass))
+ #define GTK_IS_FILE_CHOOSER_DEFAULT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_CHOOSER_DEFAULT))
+ #define GTK_FILE_CHOOSER_DEFAULT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_CHOOSER_DEFAULT, GtkFileChooserDefaultClass))
+
++#ifdef GTK26
+ typedef enum {
+ LOAD_EMPTY, /* There is no model */
+ LOAD_PRELOAD, /* Model is loading and a timer is running; model isn't inserted into the tree yet */
+ LOAD_LOADING, /* Timeout expired, model is inserted into the tree, but not fully loaded yet */
+ LOAD_FINISHED /* Model is fully loaded and inserted into the tree */
+ } LoadState;
++#endif
+
+ #define MAX_LOADING_TIME 500
+
+@@ -109,63 +112,33 @@
+
+ /* Save mode widgets */
+ GtkWidget *save_widgets;
+-
+ GtkWidget *save_file_name_entry;
+- GtkWidget *save_folder_label;
+- GtkWidget *save_folder_combo;
+- GtkWidget *save_expander;
+
+ /* The file browsing widgets */
+ GtkWidget *browse_widgets;
+- GtkWidget *browse_shortcuts_tree_view;
+- GtkWidget *browse_shortcuts_add_button;
+- GtkWidget *browse_shortcuts_remove_button;
+ GtkWidget *browse_files_tree_view;
+- GtkWidget *browse_files_popup_menu;
+- GtkWidget *browse_files_popup_menu_add_shortcut_item;
+- GtkWidget *browse_files_popup_menu_hidden_files_item;
+ GtkWidget *browse_new_folder_button;
+- GtkWidget *browse_path_bar;
+-
++ GtkWidget *bar;
++ GtkWidget * up_button;
++
+ GtkFileSystemModel *browse_files_model;
+
+- GtkWidget *filter_combo_hbox;
+- GtkWidget *filter_combo;
+- GtkWidget *preview_box;
+- GtkWidget *preview_label;
+- GtkWidget *preview_widget;
+- GtkWidget *extra_align;
+- GtkWidget *extra_widget;
+-
+- GtkListStore *shortcuts_model;
+- GtkTreeModel *shortcuts_filter_model;
+-
+ GtkTreeModelSort *sort_model;
+
+ LoadState load_state;
+ guint load_timeout_id;
+
+ GSList *pending_select_paths;
+-
+- GtkFileFilter *current_filter;
+- GSList *filters;
+-
++ GSList * path_history;
++
+ GtkTooltips *tooltips;
+
+- gboolean has_home;
+- gboolean has_desktop;
+-
+ int num_volumes;
+- int num_shortcuts;
+- int num_bookmarks;
+
+ gulong volumes_changed_id;
+- gulong bookmarks_changed_id;
+
+ GtkFilePath *current_volume_path;
+ GtkFilePath *current_folder;
+- GtkFilePath *preview_path;
+- char *preview_display_name;
+
+ GtkTreeViewColumn *list_name_column;
+ GtkCellRenderer *list_name_renderer;
+@@ -179,25 +152,15 @@
+ gulong toplevel_set_focus_id;
+ GtkWidget *toplevel_last_focus_widget;
+
+-#if 0
+- GdkDragContext *shortcuts_drag_context;
+- GSource *shortcuts_drag_outside_idle;
+-#endif
+-
++ gchar * root_folder;
++
+ /* Flags */
+
+ guint local_only : 1;
+- guint preview_widget_active : 1;
+- guint use_preview_label : 1;
+ guint select_multiple : 1;
+ guint show_hidden : 1;
+ guint list_sort_ascending : 1;
+ guint changing_folder : 1;
+- guint shortcuts_current_folder_active : 1;
+-
+-#if 0
+- guint shortcuts_drag_outside : 1;
+-#endif
+ };
+
+ /* Signal IDs */
+@@ -211,17 +174,6 @@
+
+ static guint signals[LAST_SIGNAL] = { 0 };
+
+-/* Column numbers for the shortcuts tree. Keep these in sync with shortcuts_model_create() */
+-enum {
+- SHORTCUTS_COL_PIXBUF,
+- SHORTCUTS_COL_NAME,
+- SHORTCUTS_COL_DATA,
+- SHORTCUTS_COL_IS_VOLUME,
+- SHORTCUTS_COL_REMOVABLE,
+- SHORTCUTS_COL_PIXBUF_VISIBLE,
+- SHORTCUTS_COL_NUM_COLUMNS
+-};
+-
+ /* Column numbers for the file list */
+ enum {
+ FILE_LIST_COL_NAME,
+@@ -236,23 +188,6 @@
+ TEXT_URI_LIST
+ };
+
+-/* Target types for dragging from the shortcuts list */
+-static const GtkTargetEntry shortcuts_source_targets[] = {
+- { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW }
+-};
+-
+-static const int num_shortcuts_source_targets = (sizeof (shortcuts_source_targets)
+- / sizeof (shortcuts_source_targets[0]));
+-
+-/* Target types for dropping into the shortcuts list */
+-static const GtkTargetEntry shortcuts_dest_targets[] = {
+- { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW },
+- { "text/uri-list", 0, TEXT_URI_LIST }
+-};
+-
+-static const int num_shortcuts_dest_targets = (sizeof (shortcuts_dest_targets)
+- / sizeof (shortcuts_dest_targets[0]));
+-
+ /* Target types for DnD from the file list */
+ static const GtkTargetEntry file_list_source_targets[] = {
+ { "text/uri-list", 0, TEXT_URI_LIST }
+@@ -261,22 +196,10 @@
+ static const int num_file_list_source_targets = (sizeof (file_list_source_targets)
+ / sizeof (file_list_source_targets[0]));
+
+-/* Interesting places in the shortcuts bar */
+-typedef enum {
+- SHORTCUTS_HOME,
+- SHORTCUTS_DESKTOP,
+- SHORTCUTS_VOLUMES,
+- SHORTCUTS_SHORTCUTS,
+- SHORTCUTS_BOOKMARKS_SEPARATOR,
+- SHORTCUTS_BOOKMARKS,
+- SHORTCUTS_CURRENT_FOLDER_SEPARATOR,
+- SHORTCUTS_CURRENT_FOLDER
+-} ShortcutsIndex;
+-
+ /* Icon size for if we can't get it from the theme */
+ #define FALLBACK_ICON_SIZE 16
+
+-#define PREVIEW_HBOX_SPACING 12
++#define LIST_HBOX_SPACING DEFAULT_SPACING
+ #define NUM_LINES 40
+ #define NUM_CHARS 60
+
+@@ -335,7 +258,6 @@
+ const GtkFilePath *path,
+ GError **error);
+ static GSList * gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser);
+-
+ static void gtk_file_chooser_default_get_default_size (GtkFileChooserEmbed *chooser_embed,
+ gint *default_width,
+ gint *default_height);
+@@ -352,37 +274,6 @@
+ static void home_folder_handler (GtkFileChooserDefault *impl);
+ static void update_appearance (GtkFileChooserDefault *impl);
+
+-static void set_current_filter (GtkFileChooserDefault *impl,
+- GtkFileFilter *filter);
+-static void check_preview_change (GtkFileChooserDefault *impl);
+-
+-static void filter_combo_changed (GtkComboBox *combo_box,
+- GtkFileChooserDefault *impl);
+-static void shortcuts_row_activated_cb (GtkTreeView *tree_view,
+- GtkTreePath *path,
+- GtkTreeViewColumn *column,
+- GtkFileChooserDefault *impl);
+-
+-static gboolean shortcuts_key_press_event_cb (GtkWidget *widget,
+- GdkEventKey *event,
+- GtkFileChooserDefault *impl);
+-
+-static gboolean shortcuts_select_func (GtkTreeSelection *selection,
+- GtkTreeModel *model,
+- GtkTreePath *path,
+- gboolean path_currently_selected,
+- gpointer data);
+-static gboolean shortcuts_get_selected (GtkFileChooserDefault *impl,
+- GtkTreeIter *iter);
+-static void shortcuts_activate_iter (GtkFileChooserDefault *impl,
+- GtkTreeIter *iter);
+-static int shortcuts_get_index (GtkFileChooserDefault *impl,
+- ShortcutsIndex where);
+-static int shortcut_find_position (GtkFileChooserDefault *impl,
+- const GtkFilePath *path);
+-
+-static void bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl);
+-
+ static gboolean list_select_func (GtkTreeSelection *selection,
+ GtkTreeModel *model,
+ GtkTreePath *path,
+@@ -401,16 +292,6 @@
+ GtkTreeIter *iter,
+ gpointer user_data);
+
+-static void path_bar_clicked (GtkPathBar *path_bar,
+- GtkFilePath *file_path,
+- gboolean child_is_hidden,
+- GtkFileChooserDefault *impl);
+-
+-static void add_bookmark_button_clicked_cb (GtkButton *button,
+- GtkFileChooserDefault *impl);
+-static void remove_bookmark_button_clicked_cb (GtkButton *button,
+- GtkFileChooserDefault *impl);
+-
+ static void list_icon_data_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+@@ -441,36 +322,6 @@
+
+ static GObjectClass *parent_class;
+
+-
+-
+-/* Drag and drop interface declarations */
+-
+-typedef struct {
+- GtkTreeModelFilter parent;
+-
+- GtkFileChooserDefault *impl;
+-} ShortcutsModelFilter;
+-
+-typedef struct {
+- GtkTreeModelFilterClass parent_class;
+-} ShortcutsModelFilterClass;
+-
+-#define SHORTCUTS_MODEL_FILTER_TYPE (_shortcuts_model_filter_get_type ())
+-#define SHORTCUTS_MODEL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHORTCUTS_MODEL_FILTER_TYPE, ShortcutsModelFilter))
+-
+-static void shortcuts_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface);
+-
+-G_DEFINE_TYPE_WITH_CODE (ShortcutsModelFilter,
+- _shortcuts_model_filter,
+- GTK_TYPE_TREE_MODEL_FILTER,
+- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
+- shortcuts_model_filter_drag_source_iface_init));
+-
+-static GtkTreeModel *shortcuts_model_filter_new (GtkFileChooserDefault *impl,
+- GtkTreeModel *child_model,
+- GtkTreePath *root);
+-
+-
+
+ GType
+ _gtk_file_chooser_default_get_type (void)
+@@ -520,6 +371,11 @@
+ return file_chooser_default_type;
+ }
+
++enum
++{
++ GTK_FILE_CHOOSER_PROP_ROOT_FOLDER = GTK_FILE_CHOOSER_PROP_LAST + 1,
++};
++
+ static void
+ gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
+ {
+@@ -617,6 +473,14 @@
+ "home-folder",
+ 0);
+
++ g_object_class_install_property (gobject_class,
++ GTK_FILE_CHOOSER_PROP_ROOT_FOLDER,
++ g_param_spec_string ("root-folder",
++ P_("File System Root"),
++ P_("Root folder for the file system below which the user should not be able to switch"),
++ NULL,
++ G_PARAM_WRITABLE));
++
+ _gtk_file_chooser_install_properties (gobject_class);
+
+ gtk_settings_install_property (g_param_spec_string ("gtk-file-chooser-backend",
+@@ -634,17 +498,19 @@
+ iface->select_all = gtk_file_chooser_default_select_all;
+ iface->unselect_all = gtk_file_chooser_default_unselect_all;
+ iface->get_paths = gtk_file_chooser_default_get_paths;
+- iface->get_preview_path = gtk_file_chooser_default_get_preview_path;
+ iface->get_file_system = gtk_file_chooser_default_get_file_system;
+ iface->set_current_folder = gtk_file_chooser_default_set_current_folder;
+ iface->get_current_folder = gtk_file_chooser_default_get_current_folder;
+ iface->set_current_name = gtk_file_chooser_default_set_current_name;
++
++ /* these are only stubs */
++ iface->get_preview_path = gtk_file_chooser_default_get_preview_path;
+ iface->add_filter = gtk_file_chooser_default_add_filter;
+ iface->remove_filter = gtk_file_chooser_default_remove_filter;
+ iface->list_filters = gtk_file_chooser_default_list_filters;
+ iface->add_shortcut_folder = gtk_file_chooser_default_add_shortcut_folder;
+ iface->remove_shortcut_folder = gtk_file_chooser_default_remove_shortcut_folder;
+- iface->list_shortcut_folders = gtk_file_chooser_default_list_shortcut_folders;
++
+ }
+
+ static void
+@@ -659,71 +525,22 @@
+ gtk_file_chooser_default_init (GtkFileChooserDefault *impl)
+ {
+ impl->local_only = TRUE;
+- impl->preview_widget_active = TRUE;
+- impl->use_preview_label = TRUE;
+ impl->select_multiple = FALSE;
+ impl->show_hidden = FALSE;
+ impl->icon_size = FALLBACK_ICON_SIZE;
+ impl->load_state = LOAD_EMPTY;
+ impl->pending_select_paths = NULL;
+-
++ impl->path_history = NULL;
++
+ gtk_widget_set_redraw_on_allocate (GTK_WIDGET (impl), TRUE);
+- gtk_box_set_spacing (GTK_BOX (impl), 12);
++ gtk_box_set_spacing (GTK_BOX (impl), DEFAULT_SPACING);
+
+ impl->tooltips = gtk_tooltips_new ();
+ g_object_ref (impl->tooltips);
+ gtk_object_sink (GTK_OBJECT (impl->tooltips));
+-}
+-
+-/* Frees the data columns for the specified iter in the shortcuts model*/
+-static void
+-shortcuts_free_row_data (GtkFileChooserDefault *impl,
+- GtkTreeIter *iter)
+-{
+- gpointer col_data;
+- gboolean is_volume;
+-
+- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), iter,
+- SHORTCUTS_COL_DATA, &col_data,
+- SHORTCUTS_COL_IS_VOLUME, &is_volume,
+- -1);
+- if (!col_data)
+- return;
+-
+- if (is_volume)
+- {
+- GtkFileSystemVolume *volume;
+-
+- volume = col_data;
+- gtk_file_system_volume_free (impl->file_system, volume);
+- }
+- else
+- {
+- GtkFilePath *path;
+-
+- path = col_data;
+- gtk_file_path_free (path);
+- }
+-}
+-
+-/* Frees all the data columns in the shortcuts model */
+-static void
+-shortcuts_free (GtkFileChooserDefault *impl)
+-{
+- GtkTreeIter iter;
+-
+- if (!impl->shortcuts_model)
+- return;
+-
+- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
+- do
+- {
+- shortcuts_free_row_data (impl, &iter);
+- }
+- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter));
+
+- g_object_unref (impl->shortcuts_model);
+- impl->shortcuts_model = NULL;
++ if (!impl->root_folder)
++ impl->root_folder = g_strdup ("/");
+ }
+
+ static void
+@@ -743,6 +560,7 @@
+ impl->pending_select_paths = NULL;
+ }
+
++
+ static void
+ pending_select_paths_add (GtkFileChooserDefault *impl,
+ const GtkFilePath *path)
+@@ -782,45 +600,40 @@
+ }
+
+ static void
+-gtk_file_chooser_default_finalize (GObject *object)
++path_history_free (GtkFileChooserDefault *impl)
+ {
+- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object);
+ GSList *l;
+
+- if (impl->shortcuts_filter_model)
+- g_object_unref (impl->shortcuts_filter_model);
++ for (l = impl->path_history; l; l = l->next)
++ {
++ GtkFilePath *path;
++
++ path = l->data;
++ gtk_file_path_free (path);
++ }
++
++ g_slist_free (impl->path_history);
++ impl->path_history = NULL;
++}
+
+- shortcuts_free (impl);
++static void
++gtk_file_chooser_default_finalize (GObject *object)
++{
++ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object);
+
+ g_signal_handler_disconnect (impl->file_system, impl->volumes_changed_id);
+ impl->volumes_changed_id = 0;
+- g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id);
+- impl->bookmarks_changed_id = 0;
+ g_object_unref (impl->file_system);
+
+- for (l = impl->filters; l; l = l->next)
+- {
+- GtkFileFilter *filter;
+-
+- filter = GTK_FILE_FILTER (l->data);
+- g_object_unref (filter);
+- }
+- g_slist_free (impl->filters);
+-
+- if (impl->current_filter)
+- g_object_unref (impl->current_filter);
+-
+ if (impl->current_volume_path)
+ gtk_file_path_free (impl->current_volume_path);
+
+ if (impl->current_folder)
+ gtk_file_path_free (impl->current_folder);
+
+- if (impl->preview_path)
+- gtk_file_path_free (impl->preview_path);
+-
+ pending_select_paths_free (impl);
+-
++ path_history_free (impl);
++
+ load_remove_timer (impl);
+
+ /* Free all the Models we have */
+@@ -830,12 +643,12 @@
+ if (impl->sort_model)
+ g_object_unref (impl->sort_model);
+
+- g_free (impl->preview_display_name);
+-
+ g_free (impl->edited_new_text);
+
+ g_object_unref (impl->tooltips);
+
++ g_free (impl->root_folder);
++
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+ }
+
+@@ -916,28 +729,6 @@
+ path, error);
+ }
+
+-/* Shows an error dialog about not being able to add a bookmark */
+-static void
+-error_adding_bookmark_dialog (GtkFileChooserDefault *impl,
+- const GtkFilePath *path,
+- GError *error)
+-{
+- error_dialog (impl,
+- _("Could not add a bookmark"),
+- path, error);
+-}
+-
+-/* Shows an error dialog about not being able to remove a bookmark */
+-static void
+-error_removing_bookmark_dialog (GtkFileChooserDefault *impl,
+- const GtkFilePath *path,
+- GError *error)
+-{
+- error_dialog (impl,
+- _("Could not remove bookmark"),
+- path, error);
+-}
+-
+ /* Shows an error dialog about not being able to create a folder */
+ static void
+ error_creating_folder_dialog (GtkFileChooserDefault *impl,
+@@ -949,21 +740,6 @@
+ path, error);
+ }
+
+-/* Shows an error about not being able to create a folder because a file with
+- * the same name is already there.
+- */
+-static void
+-error_creating_folder_over_existing_file_dialog (GtkFileChooserDefault *impl,
+- const GtkFilePath *path,
+- GError *error)
+-{
+- error_dialog (impl,
+- _("The folder could not be created, as a file with the same name "
+- "already exists. Try using a different name for the folder, "
+- "or rename the file first."),
+- path, error);
+-}
+-
+ /* Shows an error dialog about not being able to create a filename */
+ static void
+ error_building_filename_dialog (GtkFileChooserDefault *impl,
+@@ -993,6 +769,7 @@
+ GError *error;
+ gboolean result;
+ GtkFilePath *path_copy;
++ gchar * file_name;
+
+ /* We copy the path because of this case:
+ *
+@@ -1005,6 +782,29 @@
+
+ path_copy = gtk_file_path_copy (path);
+
++ file_name = gtk_file_system_path_to_filename (impl->file_system, path_copy);
++
++ /* refuse to change below the root */
++ if (file_name && impl->root_folder &&
++ strcmp (file_name, impl->root_folder) &&
++ !strncmp (file_name, impl->root_folder, strlen (file_name)))
++ {
++
++ gtk_file_path_free (path_copy);
++ g_free (file_name);
++ return 0;
++ }
++ else if (file_name && impl->root_folder &&
++ !strcmp (file_name, impl->root_folder))
++ {
++ gtk_widget_set_sensitive (impl->up_button, FALSE);
++ }
++ else
++ {
++ gtk_widget_set_sensitive (impl->up_button, TRUE);
++ }
++
++
+ error = NULL;
+ result = _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (impl), path_copy, &error);
+
+@@ -1012,2009 +812,234 @@
+ error_changing_folder_dialog (impl, path_copy, error);
+
+ gtk_file_path_free (path_copy);
+-
++ g_free (file_name);
++
+ return result;
+ }
+
+-static void
+-update_preview_widget_visibility (GtkFileChooserDefault *impl)
+-{
+- if (impl->use_preview_label)
+- {
+- if (!impl->preview_label)
+- {
+- impl->preview_label = gtk_label_new (impl->preview_display_name);
+- gtk_box_pack_start (GTK_BOX (impl->preview_box), impl->preview_label, FALSE, FALSE, 0);
+- gtk_box_reorder_child (GTK_BOX (impl->preview_box), impl->preview_label, 0);
+- gtk_label_set_ellipsize (GTK_LABEL (impl->preview_label), PANGO_ELLIPSIZE_MIDDLE);
+- gtk_widget_show (impl->preview_label);
+- }
+- }
+- else
+- {
+- if (impl->preview_label)
+- {
+- gtk_widget_destroy (impl->preview_label);
+- impl->preview_label = NULL;
+- }
+- }
+-
+- if (impl->preview_widget_active && impl->preview_widget)
+- gtk_widget_show (impl->preview_box);
+- else
+- gtk_widget_hide (impl->preview_box);
+-
+- g_signal_emit_by_name (impl, "default-size-changed");
+-}
+
+-static void
+-set_preview_widget (GtkFileChooserDefault *impl,
+- GtkWidget *preview_widget)
++/* Returns whether a path is a folder */
++static gboolean
++check_is_folder (GtkFileSystem *file_system,
++ const GtkFilePath *path,
++ GError **error)
+ {
+- if (preview_widget == impl->preview_widget)
+- return;
+-
+- if (impl->preview_widget)
+- gtk_container_remove (GTK_CONTAINER (impl->preview_box),
+- impl->preview_widget);
+-
+- impl->preview_widget = preview_widget;
+- if (impl->preview_widget)
+- {
+- gtk_widget_show (impl->preview_widget);
+- gtk_box_pack_start (GTK_BOX (impl->preview_box), impl->preview_widget, TRUE, TRUE, 0);
+- gtk_box_reorder_child (GTK_BOX (impl->preview_box),
+- impl->preview_widget,
+- (impl->use_preview_label && impl->preview_label) ? 1 : 0);
+- }
++ GtkFileFolder *folder;
++#ifdef GTK26
++ folder = gtk_file_system_get_folder (file_system, path, 0, error);
++#else
++ folder = gtk_file_system_get_folder (file_system, path, 0, NULL, NULL);
++#endif
++ if (!folder)
++ return FALSE;
+
+- update_preview_widget_visibility (impl);
++ g_object_unref (folder);
++ return TRUE;
+ }
+
+-/* Re-reads all the icons for the shortcuts, used when the theme changes */
++
++/* Callback used when the "New Folder" button is clicked */
+ static void
+-shortcuts_reload_icons (GtkFileChooserDefault *impl)
++new_folder_button_clicked (GtkButton *button,
++ GtkFileChooserDefault *impl)
+ {
+ GtkTreeIter iter;
++ GtkTreePath *path;
+
+- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
+- return;
++ if (!impl->browse_files_model)
++ return; /* FIXME: this sucks. Disable the New Folder button or something. */
+
+- do {
+- gpointer data;
+- gboolean is_volume;
+- gboolean pixbuf_visible;
+- GdkPixbuf *pixbuf;
+-
+- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
+- SHORTCUTS_COL_DATA, &data,
+- SHORTCUTS_COL_IS_VOLUME, &is_volume,
+- SHORTCUTS_COL_PIXBUF_VISIBLE, &pixbuf_visible,
+- -1);
++ /* Prevent button from being clicked twice */
++ gtk_widget_set_sensitive (impl->browse_new_folder_button, FALSE);
+
+- if (pixbuf_visible && data)
+- {
+- if (is_volume)
+- {
+- GtkFileSystemVolume *volume;
++ _gtk_file_system_model_add_editable (impl->browse_files_model, &iter);
+
+- volume = data;
+- pixbuf = gtk_file_system_volume_render_icon (impl->file_system, volume, GTK_WIDGET (impl),
+- impl->icon_size, NULL);
+- }
+- else
+- {
+- const GtkFilePath *path;
++ path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->browse_files_model), &iter);
++ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->browse_files_tree_view),
++ path, impl->list_name_column,
++ FALSE, 0.0, 0.0);
+
+- path = data;
+- pixbuf = gtk_file_system_render_icon (impl->file_system, path, GTK_WIDGET (impl),
+- impl->icon_size, NULL);
+- }
++ g_object_set (impl->list_name_renderer, "editable", TRUE, NULL);
++ gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view),
++ path,
++ impl->list_name_column,
++ TRUE);
+
+- gtk_list_store_set (impl->shortcuts_model, &iter,
+- SHORTCUTS_COL_PIXBUF, pixbuf,
+- -1);
+- if (pixbuf)
+- g_object_unref (pixbuf);
+- }
+- } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model),&iter));
++ gtk_tree_path_free (path);
+ }
+
+-static void
+-shortcuts_find_folder (GtkFileChooserDefault *impl,
+- GtkFilePath *folder)
++/* Idle handler for creating a new folder after editing its name cell, or for
++ * canceling the editing.
++ */
++static gboolean
++edited_idle_cb (GtkFileChooserDefault *impl)
+ {
+- GtkTreeSelection *selection;
+- int pos;
+- GtkTreePath *path;
++ GDK_THREADS_ENTER ();
++
++ g_source_destroy (impl->edited_idle);
++ impl->edited_idle = NULL;
++
++ _gtk_file_system_model_remove_editable (impl->browse_files_model);
++ g_object_set (impl->list_name_renderer, "editable", FALSE, NULL);
+
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
++ gtk_widget_set_sensitive (impl->browse_new_folder_button, TRUE);
+
+- g_assert (folder != NULL);
+- pos = shortcut_find_position (impl, folder);
+- if (pos == -1)
++ if (impl->edited_new_text) /* not cancelled? */
+ {
+- gtk_tree_selection_unselect_all (selection);
+- return;
+- }
+-
+- path = gtk_tree_path_new_from_indices (pos, -1);
+- gtk_tree_selection_select_path (selection, path);
+- gtk_tree_path_free (path);
+-}
++ GError *error;
++ GtkFilePath *file_path;
+
+-/* If a shortcut corresponds to the current folder, selects it */
+-static void
+-shortcuts_find_current_folder (GtkFileChooserDefault *impl)
+-{
+- shortcuts_find_folder (impl, impl->current_folder);
+-}
++ error = NULL;
++ file_path = gtk_file_system_make_path (impl->file_system, impl->current_folder, impl->edited_new_text,
++ &error);
++ if (file_path)
++ {
++ error = NULL;
++#ifdef GTK26
++ if (gtk_file_system_create_folder (impl->file_system, file_path, &error))
++#else
++ if (gtk_file_system_create_folder (impl->file_system, file_path, NULL, NULL))
++#endif
++ change_folder_and_display_error (impl, file_path);
++ else
++ error_creating_folder_dialog (impl, file_path, error);
+
+-/* Convenience function to get the display name and icon info for a path */
+-static GtkFileInfo *
+-get_file_info (GtkFileSystem *file_system,
+- const GtkFilePath *path,
+- gboolean name_only,
+- GError **error)
+-{
+- GtkFilePath *parent_path;
+- GtkFileFolder *parent_folder;
+- GtkFileInfo *info;
+- GError *tmp = NULL;
+-
+- parent_path = NULL;
+- info = NULL;
+-
+- if (!gtk_file_system_get_parent (file_system, path, &parent_path, &tmp))
+- goto out;
+-
+- parent_folder = gtk_file_system_get_folder (file_system, parent_path ? parent_path : path,
+- GTK_FILE_INFO_DISPLAY_NAME
+- | (name_only ? 0 : GTK_FILE_INFO_IS_FOLDER),
+- &tmp);
+- if (!parent_folder)
+- goto out;
+-
+- info = gtk_file_folder_get_info (parent_folder, parent_path ? path : NULL, &tmp);
+- g_object_unref (parent_folder);
+-
+- out:
+- if (parent_path)
+- gtk_file_path_free (parent_path);
++ gtk_file_path_free (file_path);
++ }
++ else
++ error_creating_folder_dialog (impl, file_path, error);
+
+- if (tmp)
+- {
+- g_set_error (error,
+- GTK_FILE_CHOOSER_ERROR,
+- GTK_FILE_CHOOSER_ERROR_BAD_FILENAME,
+- _("Could not get information about '%s': %s"),
+- gtk_file_path_get_string (path),
+- tmp->message);
+- g_error_free (tmp);
++ g_free (impl->edited_new_text);
++ impl->edited_new_text = NULL;
+ }
+
+- return info;
++ GDK_THREADS_LEAVE ();
++
++ return FALSE;
+ }
+
+-/* Returns whether a path is a folder */
+-static gboolean
+-check_is_folder (GtkFileSystem *file_system,
+- const GtkFilePath *path,
+- GError **error)
+-{
+- GtkFileFolder *folder;
+-
+- folder = gtk_file_system_get_folder (file_system, path, 0, error);
+- if (!folder)
+- return FALSE;
+-
+- g_object_unref (folder);
+- return TRUE;
+-}
+-
+-/* Inserts a path in the shortcuts tree, making a copy of it; alternatively,
+- * inserts a volume. A position of -1 indicates the end of the tree.
+- */
+-static gboolean
+-shortcuts_insert_path (GtkFileChooserDefault *impl,
+- int pos,
+- gboolean is_volume,
+- GtkFileSystemVolume *volume,
+- const GtkFilePath *path,
+- const char *label,
+- gboolean removable,
+- GError **error)
+-{
+- char *label_copy;
+- GdkPixbuf *pixbuf;
+- gpointer data;
+- GtkTreeIter iter;
+-
+- if (is_volume)
+- {
+- data = volume;
+- label_copy = gtk_file_system_volume_get_display_name (impl->file_system, volume);
+- pixbuf = gtk_file_system_volume_render_icon (impl->file_system, volume, GTK_WIDGET (impl),
+- impl->icon_size, NULL);
+- }
+- else
+- {
+- if (!check_is_folder (impl->file_system, path, error))
+- return FALSE;
+-
+- if (label)
+- label_copy = g_strdup (label);
+- else
+- {
+- GtkFileInfo *info = get_file_info (impl->file_system, path, TRUE, error);
+-
+- if (!info)
+- return FALSE;
+-
+- label_copy = g_strdup (gtk_file_info_get_display_name (info));
+- gtk_file_info_free (info);
+- }
+-
+- data = gtk_file_path_copy (path);
+- pixbuf = gtk_file_system_render_icon (impl->file_system, path, GTK_WIDGET (impl),
+- impl->icon_size, NULL);
+- }
+-
+- if (pos == -1)
+- gtk_list_store_append (impl->shortcuts_model, &iter);
+- else
+- gtk_list_store_insert (impl->shortcuts_model, &iter, pos);
+-
+- gtk_list_store_set (impl->shortcuts_model, &iter,
+- SHORTCUTS_COL_PIXBUF, pixbuf,
+- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
+- SHORTCUTS_COL_NAME, label_copy,
+- SHORTCUTS_COL_DATA, data,
+- SHORTCUTS_COL_IS_VOLUME, is_volume,
+- SHORTCUTS_COL_REMOVABLE, removable,
+- -1);
+-
+- g_free (label_copy);
+-
+- if (pixbuf)
+- g_object_unref (pixbuf);
+-
+- return TRUE;
+-}
+-
+-/* Appends an item for the user's home directory to the shortcuts model */
+-static void
+-shortcuts_append_home (GtkFileChooserDefault *impl)
+-{
+- const char *home;
+- GtkFilePath *home_path;
+- GError *error;
+-
+- home = g_get_home_dir ();
+- if (home == NULL)
+- return;
+-
+- home_path = gtk_file_system_filename_to_path (impl->file_system, home);
+-
+- error = NULL;
+- impl->has_home = shortcuts_insert_path (impl, -1, FALSE, NULL, home_path, _("Home"), FALSE, &error);
+- if (!impl->has_home)
+- error_getting_info_dialog (impl, home_path, error);
+-
+- gtk_file_path_free (home_path);
+-}
+-
+-/* Appends the ~/Desktop directory to the shortcuts model */
+-static void
+-shortcuts_append_desktop (GtkFileChooserDefault *impl)
+-{
+- char *name;
+- GtkFilePath *path;
+-
+-#ifdef G_OS_WIN32
+- name = _gtk_file_system_win32_get_desktop ();
+-#else
+- const char *home = g_get_home_dir ();
+- if (home == NULL)
+- return;
+-
+- name = g_build_filename (home, "Desktop", NULL);
+-#endif
+-
+- path = gtk_file_system_filename_to_path (impl->file_system, name);
+- g_free (name);
+-
+- impl->has_desktop = shortcuts_insert_path (impl, -1, FALSE, NULL, path, _("Desktop"), FALSE, NULL);
+- /* We do not actually pop up an error dialog if there is no desktop directory
+- * because some people may really not want to have one.
+- */
+-
+- gtk_file_path_free (path);
+-}
+-
+-/* Appends a list of GtkFilePath to the shortcuts model; returns how many were inserted */
+-static int
+-shortcuts_append_paths (GtkFileChooserDefault *impl,
+- GSList *paths)
+-{
+- int start_row;
+- int num_inserted;
+-
+- /* As there is no separator now, we want to start there.
+- */
+- start_row = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR);
+- num_inserted = 0;
+-
+- for (; paths; paths = paths->next)
+- {
+- GtkFilePath *path;
+- GError *error;
+-
+- path = paths->data;
+- error = NULL;
+-
+- if (impl->local_only &&
+- !gtk_file_system_path_is_local (impl->file_system, path))
+- continue;
+-
+- /* NULL GError, but we don't really want to show error boxes here */
+- if (shortcuts_insert_path (impl, start_row + num_inserted, FALSE, NULL, path, NULL, TRUE, NULL))
+- num_inserted++;
+- }
+-
+- return num_inserted;
+-}
+-
+-/* Returns the index for the corresponding item in the shortcuts bar */
+-static int
+-shortcuts_get_index (GtkFileChooserDefault *impl,
+- ShortcutsIndex where)
+-{
+- int n;
+-
+- n = 0;
+-
+- if (where == SHORTCUTS_HOME)
+- goto out;
+-
+- n += impl->has_home ? 1 : 0;
+-
+- if (where == SHORTCUTS_DESKTOP)
+- goto out;
+-
+- n += impl->has_desktop ? 1 : 0;
+-
+- if (where == SHORTCUTS_VOLUMES)
+- goto out;
+-
+- n += impl->num_volumes;
+-
+- if (where == SHORTCUTS_SHORTCUTS)
+- goto out;
+-
+- n += impl->num_shortcuts;
+-
+- if (where == SHORTCUTS_BOOKMARKS_SEPARATOR)
+- goto out;
+-
+- /* If there are no bookmarks there won't be a separator */
+- n += (impl->num_bookmarks > 0) ? 1 : 0;
+-
+- if (where == SHORTCUTS_BOOKMARKS)
+- goto out;
+-
+- n += impl->num_bookmarks;
+-
+-