aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Stack <bgstack15@gmail.com>2023-03-25 13:45:21 -0400
committerB. Stack <bgstack15@gmail.com>2023-03-25 13:45:21 -0400
commit6486386e040320e64ae7cb0e5ceddd2371578bc4 (patch)
treea726dfeaaea1ff96a6ae47d4eb7aacbe402800f7
parenttry to suppress test errors again (diff)
downloadgtk3-classic-build-6486386e040320e64ae7cb0e5ceddd2371578bc4.tar.gz
gtk3-classic-build-6486386e040320e64ae7cb0e5ceddd2371578bc4.tar.bz2
gtk3-classic-build-6486386e040320e64ae7cb0e5ceddd2371578bc4.zip
3.24.27 and add filechooser-icon-view patch
-rwxr-xr-xgtk-classic-build-deb.sh9
-rw-r--r--gtk3-filechooser-icon-view.patch2427
-rw-r--r--gtk3-filechooser-icon-view.patch.diff1055
3 files changed, 3490 insertions, 1 deletions
diff --git a/gtk-classic-build-deb.sh b/gtk-classic-build-deb.sh
index 8ecad9a..b79c904 100755
--- a/gtk-classic-build-deb.sh
+++ b/gtk-classic-build-deb.sh
@@ -88,9 +88,10 @@ cd "${WORKDIR}/gtk+-${raw_version}"
tar -Jxf "${WORKDIR}/gtk+3.0_${deb_version}.debian.tar.xz"
mv debian/changelog debian/changelog.orig
{
- echo "gtk+3.0 (${raw_version}-100+stackrpms) obs; urgency=medium"
+ echo "gtk+3.0 (${raw_version}-101+stackrpms) obs; urgency=medium"
echo ""
echo " * Rebuild gtk3 with gtk3-classic patches"
+ echo " * Add filechooser-icon-view from dudemanguy"
echo ""
echo " -- B. Stack <bgstack15@gmail.com> $( date "+%a, %d %b %+4Y %T %z" )"
echo ""
@@ -100,6 +101,12 @@ rm debian.changelog
cp -p "${WORKDIR}/gtk3classic/"*.patch debian/patches/
cp -p "${WORKDIR}/gtk3classic/"*.css debian/patches/
cat "${WORKDIR}/gtk3classic/series" >> debian/patches/series
+
+#### Fetch gtk3-filechooser-icon-view.patch
+# from wget https://gist.github.com/Dudemanguy/c172394e30e1e7d0f477ad15c719bc71/raw/8f2e9fb36d736b600030a2db24a26304654f5e17/gtk3-filechooser-icon-view.patch --output-document="${WORKDIR}/gtk3classic/gtk3-filechooser-icon-view.patch"
+cp -p "${WORKDIR}/gtk3-filechooser-icon-view.patch" debian/patches/
+echo "gtk3-filechooser-icon-view.patch" >> debian/patches/series
+
sed -i -r debian/rules \
-e 's/env -u LD_PRELOAD xvfb-run -a dh_auto_test/#env -u LD_PRELOAD xvfb-run -a dh_auto_test/' \
-e '/NOMATCHFINDABLE/s/abcdefg/# added for 3.24.34 because LD_PRELOAD statement does nothing now/;' \
diff --git a/gtk3-filechooser-icon-view.patch b/gtk3-filechooser-icon-view.patch
new file mode 100644
index 0000000..52edecb
--- /dev/null
+++ b/gtk3-filechooser-icon-view.patch
@@ -0,0 +1,2427 @@
+Last-modified: 2023-03-24
+Authors: dudemanguy, bgstack15
+Applicable-to: [gtk3-classic](https://github.com/lah7/gtk3-classic)
+Message: Adapted by bgstack15 from [dudemanguy/gtk3-filechooser-icon-view.patch](https://gist.github.com/Dudemanguy/c172394e30e1e7d0f477ad15c719bc71) for after the lah7/gtk3-classic patches
+Version: 3.24.37
+--- a/gtk/gtkfilechooserprivate.h
++++ b/gtk/gtkfilechooserprivate.h
+@@ -32,10 +32,14 @@
+ #include "gtktreestore.h"
+ #include "gtktreeview.h"
+ #include "gtkbox.h"
++#include "gtkiconview.h"
++#include "gtkscale.h"
+
+ G_BEGIN_DECLS
+
+ #define SETTINGS_KEY_LOCATION_MODE "location-mode"
++#define SETTINGS_KEY_VIEW_MODE "view-mode"
++#define SETTINGS_KEY_ICON_VIEW_SCALE "icon-view-scale"
+ #define SETTINGS_KEY_SHOW_HIDDEN "show-hidden"
+ #define SETTINGS_KEY_SHOW_SIZE_COLUMN "show-size-column"
+ #define SETTINGS_KEY_SHOW_TYPE_COLUMN "show-type-column"
+@@ -60,34 +64,34 @@ struct _GtkFileChooserIface
+
+ /* Methods
+ */
+- gboolean (*set_current_folder) (GtkFileChooser *chooser,
+- GFile *file,
+- GError **error);
+- GFile * (*get_current_folder) (GtkFileChooser *chooser);
+- void (*set_current_name) (GtkFileChooser *chooser,
+- const gchar *name);
++ gboolean (*set_current_folder) (GtkFileChooser *chooser,
++ GFile *file,
++ GError **error);
++ GFile * (*get_current_folder) (GtkFileChooser *chooser);
++ void (*set_current_name) (GtkFileChooser *chooser,
++ const gchar *name);
+ gchar * (*get_current_name) (GtkFileChooser *chooser);
+- gboolean (*select_file) (GtkFileChooser *chooser,
+- GFile *file,
+- GError **error);
+- void (*unselect_file) (GtkFileChooser *chooser,
+- GFile *file);
+- void (*select_all) (GtkFileChooser *chooser);
+- void (*unselect_all) (GtkFileChooser *chooser);
+- GSList * (*get_files) (GtkFileChooser *chooser);
+- GFile * (*get_preview_file) (GtkFileChooser *chooser);
+- GtkFileSystem *(*get_file_system) (GtkFileChooser *chooser);
+- void (*add_filter) (GtkFileChooser *chooser,
+- GtkFileFilter *filter);
+- void (*remove_filter) (GtkFileChooser *chooser,
+- GtkFileFilter *filter);
+- GSList * (*list_filters) (GtkFileChooser *chooser);
++ gboolean (*select_file) (GtkFileChooser *chooser,
++ GFile *file,
++ GError **error);
++ void (*unselect_file) (GtkFileChooser *chooser,
++ GFile *file);
++ void (*select_all) (GtkFileChooser *chooser);
++ void (*unselect_all) (GtkFileChooser *chooser);
++ GSList * (*get_files) (GtkFileChooser *chooser);
++ GFile * (*get_preview_file) (GtkFileChooser *chooser);
++ GtkFileSystem *(*get_file_system) (GtkFileChooser *chooser);
++ void (*add_filter) (GtkFileChooser *chooser,
++ GtkFileFilter *filter);
++ void (*remove_filter) (GtkFileChooser *chooser,
++ GtkFileFilter *filter);
++ GSList * (*list_filters) (GtkFileChooser *chooser);
+ gboolean (*add_shortcut_folder) (GtkFileChooser *chooser,
+- GFile *file,
+- GError **error);
++ GFile *file,
++ GError **error);
+ gboolean (*remove_shortcut_folder) (GtkFileChooser *chooser,
+- GFile *file,
+- GError **error);
++ GFile *file,
++ GError **error);
+ GSList * (*list_shortcut_folders) (GtkFileChooser *chooser);
+
+ /* Signals
+@@ -115,11 +119,11 @@ struct _GtkFileChooserIface
+
+ GtkFileSystem *_gtk_file_chooser_get_file_system (GtkFileChooser *chooser);
+ gboolean _gtk_file_chooser_add_shortcut_folder (GtkFileChooser *chooser,
+- GFile *folder,
+- GError **error);
++ GFile *folder,
++ GError **error);
+ gboolean _gtk_file_chooser_remove_shortcut_folder (GtkFileChooser *chooser,
+- GFile *folder,
+- GError **error);
++ GFile *folder,
++ GError **error);
+ GSList * _gtk_file_chooser_list_shortcut_folder_files (GtkFileChooser *chooser);
+
+
+--- a/gtk/gtkfilechooserwidget.c
++++ b/gtk/gtkfilechooserwidget.c
+@@ -45,10 +45,12 @@
+ #include "gtkfilesystemmodel.h"
+ #include "gtkgrid.h"
+ #include "gtkicontheme.h"
++#include "gtkiconview.h"
+ #include "gtklabel.h"
+ #include "gtkmarshalers.h"
+ #include "gtkmessagedialog.h"
+ #include "gtkmountoperation.h"
++#include "gtknotebook.h"
+ #include "gtkpaned.h"
+ #include "gtkpathbar.h"
+ #include "gtkplacessidebar.h"
+@@ -84,6 +86,7 @@
+ #include "gtkcssprovider.h"
+
+ #include <cairo-gobject.h>
++#include <math.h>
+
+ #ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+@@ -202,6 +205,11 @@ typedef enum {
+ } StartupMode;
+
+ typedef enum {
++ VIEW_MODE_LIST,
++ VIEW_MODE_ICON,
++} ViewMode;
++
++typedef enum {
+ CLOCK_FORMAT_24,
+ CLOCK_FORMAT_12
+ } ClockFormat;
+@@ -231,8 +239,12 @@ struct _GtkFileChooserWidgetPrivate {
+ GtkWidget *browse_header_revealer;
+ GtkWidget *browse_header_stack;
+ GtkWidget *browse_files_stack;
+- GtkWidget *browse_files_swin;
++ GtkNotebook *view_notebook;
++ GtkWidget *browse_files_list_swin;
++ GtkWidget *browse_files_icon_swin;
++ GtkWidget *browse_files_current_view;
+ GtkWidget *browse_files_tree_view;
++ GtkWidget *browse_files_icon_view;
+ GtkWidget *remote_warning_bar;
+
+ GtkWidget *browse_files_popover;
+@@ -248,6 +260,12 @@ struct _GtkFileChooserWidgetPrivate {
+ GtkWidget *delete_file_item;
+ GtkWidget *sort_directories_item;
+ GtkWidget *show_time_item;
++ GtkWidget *arrange_item;
++ GtkWidget *sort_by_name_item;
++ GtkWidget *sort_by_size_item;
++ GtkWidget *sort_by_time_item;
++ GtkWidget *ascending_item;
++ GtkWidget *descending_item;
+
+ GtkWidget *browse_new_folder_button;
+ GtkSizeGroup *browse_path_bar_size_group;
+@@ -264,6 +282,7 @@ struct _GtkFileChooserWidgetPrivate {
+
+ GtkGesture *long_press_gesture;
+
++ GtkTreeModel *current_model;
+ GtkFileSystemModel *browse_files_model;
+ char *browse_files_last_selected_name;
+
+@@ -351,10 +370,17 @@ struct _GtkFileChooserWidgetPrivate {
+ guint location_changed_id;
+
+ gulong settings_signal_id;
+- int icon_size;
++ gint list_view_icon_size;
++ gint icon_view_icon_size;
+
+ GSource *focus_entry_idle;
+
++ GtkWidget *view_mode_combo_box;
++ GtkWidget *icon_view_scale;
++ ViewMode view_mode;
++
++ GtkCellRenderer *list_icon_renderer;
++
+ gulong toplevel_set_focus_id;
+ GtkWidget *toplevel_last_focus_widget;
+
+@@ -422,7 +448,8 @@ enum {
+ MODEL_COL_NAME_COLLATED,
+ MODEL_COL_IS_FOLDER,
+ MODEL_COL_IS_SENSITIVE,
+- MODEL_COL_SURFACE,
++ MODEL_COL_LIST_SURFACE,
++ MODEL_COL_ICON_PIXBUF,
+ MODEL_COL_SIZE_TEXT,
+ MODEL_COL_DATE_TEXT,
+ MODEL_COL_TIME_TEXT,
+@@ -442,7 +469,8 @@ enum {
+ G_TYPE_STRING, /* MODEL_COL_NAME_COLLATED */ \
+ G_TYPE_BOOLEAN, /* MODEL_COL_IS_FOLDER */ \
+ G_TYPE_BOOLEAN, /* MODEL_COL_IS_SENSITIVE */ \
+- CAIRO_GOBJECT_TYPE_SURFACE, /* MODEL_COL_SURFACE */ \
++ CAIRO_GOBJECT_TYPE_SURFACE, /* MODEL_COL_LIST_SURFACE */ \
++ GDK_TYPE_PIXBUF, /* MODEL_COL_ICON_PIXBUF */ \
+ G_TYPE_STRING, /* MODEL_COL_SIZE_TEXT */ \
+ G_TYPE_STRING, /* MODEL_COL_DATE_TEXT */ \
+ G_TYPE_STRING, /* MODEL_COL_TIME_TEXT */ \
+@@ -452,7 +480,10 @@ enum {
+ #define DEFAULT_RECENT_FILES_LIMIT 50
+
+ /* Icon size for if we can't get it from the theme */
+-#define FALLBACK_ICON_SIZE 16
++#define FALLBACK_LIST_VIEW_ICON_SIZE 16
++#define FALLBACK_ICON_VIEW_ICON_SIZE 48
++
++#define ICON_VIEW_ITEM_WIDTH 128
+
+ #define PREVIEW_HBOX_SPACING 12
+ #define NUM_LINES 45
+@@ -573,7 +604,7 @@ static gboolean list_select_func (GtkT
+ gboolean path_currently_selected,
+ gpointer data);
+
+-static void list_selection_changed (GtkTreeSelection *tree_selection,
++static void list_selection_changed (void *selection,
+ GtkFileChooserWidget *impl);
+ static void list_row_activated (GtkTreeView *tree_view,
+ GtkTreePath *path,
+@@ -581,6 +612,13 @@ static void list_row_activated (
+ GtkFileChooserWidget *impl);
+ static void list_cursor_changed (GtkTreeView *treeview,
+ GtkFileChooserWidget *impl);
++static void icon_item_activated (GtkIconView *icon_view,
++ GtkTreePath *path,
++ GtkFileChooserWidget *impl);
++static void item_activated (GtkTreeModel *model,
++ GtkTreePath *path,
++ GtkFileChooserWidget *impl);
++
+
+ static void path_bar_clicked (GtkPathBar *path_bar,
+ GFile *file,
+@@ -593,6 +631,13 @@ static void update_cell_renderer_attribu
+ static void load_remove_timer (GtkFileChooserWidget *impl, LoadState new_load_state);
+ static void browse_files_center_selected_row (GtkFileChooserWidget *impl);
+
++static void icon_view_scale_value_changed_cb (GtkRange *range,
++ GtkFileChooserWidget *impl);
++
++static void view_mode_set (GtkFileChooserWidget *impl, ViewMode view_mode);
++static void view_mode_combo_box_changed_cb (GtkComboBox *combo,
++ GtkFileChooserWidget *impl);
++
+ static void location_switch_to_path_bar (GtkFileChooserWidget *impl);
+
+ static void stop_loading_and_clear_list_model (GtkFileChooserWidget *impl,
+@@ -622,6 +667,26 @@ static gboolean recent_should_respond
+ static void set_file_system_backend (GtkFileChooserWidget *impl);
+ static void unset_file_system_backend (GtkFileChooserWidget *impl);
+
++static gboolean get_selected_tree_iter_from_icon_view (GtkFileChooserWidget *impl,
++ GtkTreeIter *iter_out);
++static void current_selection_selected_foreach (GtkFileChooserWidget *impl,
++ GtkTreeSelectionForeachFunc func,
++ gpointer data);
++static guint current_selection_count_selected_rows (GtkFileChooserWidget *impl);
++static void current_selection_select_iter (GtkFileChooserWidget *impl,
++ GtkTreeIter *iter);
++static void copy_old_selection_to_current_view (GtkFileChooserWidget *impl,
++ ViewMode old_view_mode);
++static void current_selection_unselect_iter (GtkFileChooserWidget *impl,
++ GtkTreeIter *iter);
++static void current_selection_unselect_all (GtkFileChooserWidget *impl);
++static void current_view_set_file_model (GtkFileChooserWidget *impl,
++ GtkTreeModel *model);
++static void current_view_set_cursor (GtkFileChooserWidget *impl,
++ GtkTreePath *path);
++static void current_view_set_select_multiple (GtkFileChooserWidget *impl,
++ gboolean select_multiple);
++
+ static void clear_model_cache (GtkFileChooserWidget *impl,
+ gint column);
+ static void set_model_filter (GtkFileChooserWidget *impl,
+@@ -959,7 +1024,7 @@ update_preview_widget_visibility (GtkFil
+ }
+ }
+
+- if (priv->preview_widget_active && priv->preview_widget)
++ if (priv->preview_widget_active && priv->preview_widget && priv->view_mode == VIEW_MODE_LIST)
+ gtk_widget_show (priv->preview_box);
+ else
+ gtk_widget_hide (priv->preview_box);
+@@ -1227,19 +1292,16 @@ selection_check (GtkFileChooserWidget *i
+ gboolean *all_files,
+ gboolean *all_folders)
+ {
+- GtkFileChooserWidgetPrivate *priv = impl->priv;
+ struct selection_check_closure closure;
+- GtkTreeSelection *selection;
+
+ closure.impl = impl;
+ closure.num_selected = 0;
+ closure.all_files = TRUE;
+ closure.all_folders = TRUE;
+
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- gtk_tree_selection_selected_foreach (selection,
+- selection_check_foreach_cb,
+- &closure);
++ current_selection_selected_foreach (impl,
++ selection_check_foreach_cb,
++ &closure);
+
+ g_assert (closure.num_selected == 0 || !(closure.all_files && closure.all_folders));
+
+@@ -1367,7 +1429,7 @@ browse_files_key_press_event_cb (GtkWidg
+ return TRUE;
+ }
+
+- if (key_is_left_or_right (event))
++ if (priv->view_mode == VIEW_MODE_LIST && key_is_left_or_right (event))
+ {
+ if (gtk_widget_child_focus (priv->places_sidebar, GTK_DIR_LEFT))
+ return TRUE;
+@@ -1470,12 +1532,8 @@ add_to_shortcuts_cb (GSimpleAction *acti
+ gpointer data)
+ {
+ GtkFileChooserWidget *impl = data;
+- GtkFileChooserWidgetPrivate *priv = impl->priv;
+- GtkTreeSelection *selection;
+-
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+
+- gtk_tree_selection_selected_foreach (selection,
++ current_selection_selected_foreach (impl,
+ add_bookmark_foreach_cb,
+ impl);
+ }
+@@ -1848,6 +1906,86 @@ open_folder_cb (GSimpleAction *action,
+ }
+ G_GNUC_END_IGNORE_DEPRECATIONS
+
++/* callback used when "Sort by Name" menu item is activated */
++static void
++sort_by_name_cb (GSimpleAction *action,
++ GVariant *parameter,
++ gpointer data)
++{
++ GtkFileChooserWidget *impl = data;
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ GtkTreeSortable *sortable;
++
++ sortable = GTK_TREE_SORTABLE (priv->browse_files_model);
++ gtk_tree_sortable_set_sort_column_id (sortable,
++ priv->sort_column=MODEL_COL_NAME,
++ priv->sort_order);
++}
++
++/* callback used when "Sort by Size" menu item is activated */
++static void
++sort_by_size_cb (GSimpleAction *action,
++ GVariant *parameter,
++ gpointer data)
++{
++ GtkFileChooserWidget *impl = data;
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ GtkTreeSortable *sortable;
++
++ sortable = GTK_TREE_SORTABLE (priv->browse_files_model);
++ gtk_tree_sortable_set_sort_column_id (sortable,
++ priv->sort_column=MODEL_COL_SIZE,
++ priv->sort_order);
++}
++
++/* callback used when "Sort by Time" menu item is activated */
++static void
++sort_by_time_cb (GSimpleAction *action,
++ GVariant *parameter,
++ gpointer data)
++{
++ GtkFileChooserWidget *impl = data;
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ GtkTreeSortable *sortable;
++
++ sortable = GTK_TREE_SORTABLE (priv->browse_files_model);
++ gtk_tree_sortable_set_sort_column_id (sortable,
++ priv->sort_column=MODEL_COL_TIME,
++ priv->sort_order);
++}
++
++/* callback used when "Ascending" menu item is activated */
++static void
++ascending_cb (GSimpleAction *action,
++ GVariant *parameter,
++ gpointer data)
++{
++ GtkFileChooserWidget *impl = data;
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ GtkTreeSortable *sortable;
++
++ sortable = GTK_TREE_SORTABLE (priv->browse_files_model);
++ gtk_tree_sortable_set_sort_column_id (sortable,
++ priv->sort_column,
++ priv->sort_order=GTK_SORT_ASCENDING);
++}
++
++/* callback used when "Descending" menu item is activated */
++static void
++descending_cb (GSimpleAction *action,
++ GVariant *parameter,
++ gpointer data)
++{
++ GtkFileChooserWidget *impl = data;
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ GtkTreeSortable *sortable;
++
++ sortable = GTK_TREE_SORTABLE (priv->browse_files_model);
++ gtk_tree_sortable_set_sort_column_id (sortable,
++ priv->sort_column,
++ priv->sort_order=GTK_SORT_DESCENDING);
++}
++
+ /* callback used when the "Show Hidden Files" menu item is toggled */
+ static void
+ change_show_hidden_state (GSimpleAction *action,
+@@ -2175,6 +2313,7 @@ check_file_list_popover_sensitivity (Gtk
+ gboolean all_files;
+ gboolean all_folders;
+ gboolean active;
++ gboolean always_active;
+ GActionGroup *actions;
+ GAction *action, *action2;
+
+@@ -2183,6 +2322,7 @@ check_file_list_popover_sensitivity (Gtk
+ selection_check (impl, &num_selected, &all_files, &all_folders);
+
+ active = (num_selected != 0);
++ always_active = (num_selected >= 0);
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "copy-location");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), active);
+@@ -2196,6 +2336,21 @@ check_file_list_popover_sensitivity (Gtk
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "open");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), (num_selected == 1) && all_folders);
+
++ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "sort-by-name");
++ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), always_active);
++
++ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "sort-by-size");
++ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), always_active);
++
++ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "sort-by-time");
++ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), always_active);
++
++ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "ascending");
++ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), always_active);
++
++ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "descending");
++ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), always_active);
++
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "rename");
+ if (num_selected == 1)
+ {
+@@ -2261,6 +2416,11 @@ static GActionEntry entries[] = {
+ { "rename", rename_file_cb, NULL, NULL, NULL },
+ { "delete", delete_file_cb, NULL, NULL, NULL },
+ { "trash", trash_file_cb, NULL, NULL, NULL },
++ { "sort-by-name", sort_by_name_cb, NULL, NULL, NULL },
++ { "sort-by-size", sort_by_size_cb, NULL, NULL, NULL },
++ { "sort-by-time", sort_by_time_cb, NULL, NULL, NULL },
++ { "ascending", ascending_cb, NULL, NULL, NULL },
++ { "descending", descending_cb, NULL, NULL, NULL },
+ { "toggle-show-hidden", NULL, NULL, "false", change_show_hidden_state },
+ { "toggle-show-size", NULL, NULL, "false", change_show_size_state },
+ { "toggle-show-type", NULL, NULL, "false", change_show_type_state },
+@@ -2290,17 +2450,6 @@ append_separator (GtkWidget *box)
+ gtk_widget_set_visible (GTK_WIDGET (separator), TRUE);
+ gtk_menu_shell_append (GTK_MENU_SHELL (box), separator);
+ return separator;
+- separator = g_object_new (GTK_TYPE_SEPARATOR,
+- "orientation", GTK_ORIENTATION_HORIZONTAL,
+- "visible", TRUE,
+- "margin-start", 12,
+- "margin-end", 12,
+- "margin-top", 6,
+- "margin-bottom", 6,
+- NULL);
+- gtk_container_add (GTK_CONTAINER (box), separator);
+-
+- return separator;
+ }
+
+ /* Constructs the popup menu for the file list if needed */
+@@ -2319,14 +2468,6 @@ add_button (GtkWidget *box,
+ gtk_widget_set_visible (GTK_WIDGET (item), TRUE);
+ gtk_menu_shell_append (GTK_MENU_SHELL (box), item);
+ return item;
+- item = g_object_new (GTK_TYPE_MODEL_BUTTON,
+- "visible", TRUE,
+- "action-name", action,
+- "text", label,
+- NULL);
+- gtk_container_add (GTK_CONTAINER (box), item);
+-
+- return item;
+ }
+
+ static void
+@@ -2338,11 +2479,6 @@ file_list_build_popover (GtkFileChooserW
+ if (priv->browse_files_popover)
+ return;
+
+- priv->browse_files_popover = gtk_popover_new (priv->browse_files_tree_view);
+- box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+- g_object_set (box, "margin", 10, NULL);
+- gtk_widget_show (box);
+- gtk_container_add (GTK_CONTAINER (priv->browse_files_popover), box);
+ priv->browse_files_popover = gtk_menu_new ();
+ gtk_menu_attach_to_widget (GTK_MENU (priv->browse_files_popover), GTK_WIDGET (priv->browse_files_tree_view), NULL);
+ box = priv->browse_files_popover;
+@@ -2357,11 +2493,29 @@ file_list_build_popover (GtkFileChooserW
+
+ append_separator (box);
+
+- priv->hidden_files_item = add_button (box, _("Show _Hidden Files"), "item.toggle-show-hidden");
+- priv->size_column_item = add_button (box, _("Show _Size Column"), "item.toggle-show-size");
+- priv->type_column_item = add_button (box, _("Show T_ype Column"), "item.toggle-show-type");
+- priv->show_time_item = add_button (box, _("Show _Time"), "item.toggle-show-time");
+- priv->sort_directories_item = add_button (box, _("Sort _Folders before Files"), "item.toggle-sort-dirs-first");
++ if (priv->view_mode == VIEW_MODE_LIST)
++ {
++ priv->hidden_files_item = add_button (box, _("Show _Hidden Files"), "item.toggle-show-hidden");
++ priv->size_column_item = add_button (box, _("Show _Size Column"), "item.toggle-show-size");
++ priv->type_column_item = add_button (box, _("Show T_ype Column"), "item.toggle-show-type");
++ priv->show_time_item = add_button (box, _("Show _Time"), "item.toggle-show-time");
++ priv->sort_directories_item = add_button (box, _("Sort _Folders before Files"), "item.toggle-sort-dirs-first");
++ }
++ if (priv->view_mode == VIEW_MODE_ICON)
++ {
++ GtkWidget *menu;
++ priv->arrange_item = add_button (box, _("Arrange Items"), NULL);
++ menu = gtk_menu_new ();
++ gtk_menu_item_set_submenu (GTK_MENU_ITEM (priv->arrange_item), menu);
++ priv->sort_by_name_item = add_button (menu, _("Sort _by Name"), "item.sort-by-name");
++ priv->sort_by_size_item = add_button (menu, _("Sort _by Size"), "item.sort-by-size");
++ priv->sort_by_time_item = add_button (menu, _("Sort _by Time"), "item.sort-by-time");
++ append_separator (menu);
++ priv->ascending_item = add_button (menu, _("Ascending"), "item.ascending");
++ priv->descending_item = add_button (menu, _("Descending"), "item.descending");
++ priv->hidden_files_item = add_button (box, _("Show _Hidden Files"), "item.toggle-show-hidden");
++ priv->sort_directories_item = add_button (box, _("Sort _Folders before Files"), "item.toggle-sort-dirs-first");
++ }
+ g_object_set (priv->visit_file_item, "image", gtk_image_new_from_icon_name ("gtk-jump-to", GTK_ICON_SIZE_MENU), NULL);
+ g_object_set (priv->open_folder_item, "image", gtk_image_new_from_icon_name ("gtk-open", GTK_ICON_SIZE_MENU), NULL);
+ g_object_set (priv->copy_file_location_item, "image", gtk_image_new_from_icon_name ("gtk-copy", GTK_ICON_SIZE_MENU), NULL);
+@@ -2419,41 +2573,10 @@ file_list_show_popover (GtkFileChooserWi
+ gdouble y)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+- GdkRectangle rect;
+- GtkTreeSelection *selection;
+- GtkTreeModel *model;
+- GList *list;
+- GtkTreePath *path;
+-
+
+ file_list_update_popover (impl);
+ gtk_menu_popup_at_pointer (GTK_MENU (priv->browse_files_popover), NULL);
+ return;
+-
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- list = gtk_tree_selection_get_selected_rows (selection, &model);
+- if (list)
+- {
+- path = list->data;
+- gtk_tree_view_get_cell_area (GTK_TREE_VIEW (priv->browse_files_tree_view), path, NULL, &rect);
+- gtk_tree_view_convert_bin_window_to_widget_coords (GTK_TREE_VIEW (priv->browse_files_tree_view),
+- rect.x, rect.y, &rect.x, &rect.y);
+-
+- rect.x = CLAMP (x - 20, 0, gtk_widget_get_allocated_width (priv->browse_files_tree_view) - 40);
+- rect.width = 40;
+-
+- g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+- }
+- else
+- {
+- rect.x = x;
+- rect.y = y;
+- rect.width = 1;
+- rect.height = 1;
+- }
+-
+- gtk_popover_set_pointing_to (GTK_POPOVER (priv->browse_files_popover), &rect);
+- gtk_popover_popup (GTK_POPOVER (priv->browse_files_popover));
+ }
+
+ /* Callback used for the GtkWidget::popup-menu signal of the file list */
+@@ -2490,7 +2613,7 @@ list_button_press_event_cb (GtkWidget
+ return FALSE;
+
+ in_press = TRUE;
+- gtk_widget_event (priv->browse_files_tree_view, (GdkEvent *) event);
++ gtk_widget_event (widget, (GdkEvent *) event);
+ in_press = FALSE;
+
+ file_list_show_popover (impl, event->x, event->y);
+@@ -2521,13 +2644,16 @@ file_list_set_sort_column_ids (GtkFileCh
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+
+- gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), 0);
++ if (priv->view_mode == VIEW_MODE_LIST)
++ {
++ gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), 0);
+
+- gtk_tree_view_column_set_sort_column_id (priv->list_name_column, MODEL_COL_NAME);
+- gtk_tree_view_column_set_sort_column_id (priv->list_time_column, MODEL_COL_TIME);
+- gtk_tree_view_column_set_sort_column_id (priv->list_size_column, MODEL_COL_SIZE);
+- gtk_tree_view_column_set_sort_column_id (priv->list_type_column, MODEL_COL_TYPE);
+- gtk_tree_view_column_set_sort_column_id (priv->list_location_column, MODEL_COL_LOCATION_TEXT);
++ gtk_tree_view_column_set_sort_column_id (priv->list_name_column, MODEL_COL_NAME);
++ gtk_tree_view_column_set_sort_column_id (priv->list_time_column, MODEL_COL_TIME);
++ gtk_tree_view_column_set_sort_column_id (priv->list_size_column, MODEL_COL_SIZE);
++ gtk_tree_view_column_set_sort_column_id (priv->list_type_column, MODEL_COL_TYPE);
++ gtk_tree_view_column_set_sort_column_id (priv->list_location_column, MODEL_COL_LOCATION_TEXT);
++ }
+ }
+
+ static gboolean
+@@ -2550,11 +2676,22 @@ file_list_query_tooltip_cb (GtkWidget *
+ return FALSE;
+
+
+- if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (priv->browse_files_tree_view),
+- &x, &y,
+- keyboard_tip,
+- &model, &path, &iter))
+- return FALSE;
++ if (priv->view_mode == VIEW_MODE_LIST)
++ {
++ if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (priv->browse_files_tree_view),
++ &x, &y,
++ keyboard_tip,
++ &model, &path, &iter))
++ return FALSE;
++ }
++ else if(priv->view_mode == VIEW_MODE_ICON)
++ {
++ if (!gtk_icon_view_get_tooltip_context (GTK_ICON_VIEW (priv->browse_files_icon_view),
++ &x, &y,
++ keyboard_tip,
++ &model, &path, &iter))
++ return FALSE;
++ }
+
+ gtk_tree_model_get (model, &iter,
+ MODEL_COL_FILE, &file,
+@@ -2568,10 +2705,18 @@ file_list_query_tooltip_cb (GtkWidget *
+
+ filename = g_file_get_path (file);
+ gtk_tooltip_set_text (tooltip, filename);
+- gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (priv->browse_files_tree_view),
+- tooltip,
+- path);
+-
++ if (priv->view_mode == VIEW_MODE_LIST)
++ {
++ gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (priv->browse_files_tree_view),
++ tooltip,
++ path);
++ }
++ else if(priv->view_mode == VIEW_MODE_ICON)
++ {
++ gtk_icon_view_set_tooltip_item (GTK_ICON_VIEW (priv->browse_files_icon_view),
++ tooltip,
++ path);
++ }
+ g_free (filename);
+ g_object_unref (file);
+ gtk_tree_path_free (path);
+@@ -2587,8 +2732,8 @@ set_icon_cell_renderer_fixed_size (GtkFi
+
+ gtk_cell_renderer_get_padding (priv->list_pixbuf_renderer, &xpad, &ypad);
+ gtk_cell_renderer_set_fixed_size (priv->list_pixbuf_renderer,
+- xpad * 2 + priv->icon_size,
+- ypad * 2 + priv->icon_size);
++ xpad * 2 + priv->list_view_icon_size,
++ ypad * 2 + priv->list_view_icon_size);
+ }
+
+ static gboolean
+@@ -2872,7 +3017,7 @@ location_mode_set (GtkFileChooserWidget
+ location_switch_to_path_bar (impl);
+
+ if (switch_to_file_list)
+- gtk_widget_grab_focus (priv->browse_files_tree_view);
++ gtk_widget_grab_focus (priv->browse_files_current_view);
+
+ break;
+
+@@ -2943,6 +3088,119 @@ location_toggle_popup_handler (GtkFileCh
+ }
+ }
+
++/* Creates icon view (alternative for the list view) */
++static GtkWidget *
++create_browse_files_icon_view (GtkFileChooserWidget *impl)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++
++ gtk_icon_view_set_text_column (GTK_ICON_VIEW (priv->browse_files_icon_view),
++ MODEL_COL_NAME);
++ gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (priv->browse_files_icon_view),
++ MODEL_COL_ICON_PIXBUF);
++ gtk_icon_view_set_item_width (GTK_ICON_VIEW (priv->browse_files_icon_view),
++ ICON_VIEW_ITEM_WIDTH);
++
++ return priv->browse_files_icon_view;
++}
++
++static void
++view_mode_set (GtkFileChooserWidget *impl, ViewMode view_mode)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ GtkWidget *old_view = NULL;
++ ViewMode old_view_mode = priv->view_mode;
++ priv->browse_files_popover = NULL;
++
++ if (old_view_mode == view_mode)
++ return;
++
++ g_debug("GtkFileChooserWidget::view_mode_set %d", view_mode);
++
++ priv->view_mode = view_mode;
++ gtk_combo_box_set_active (GTK_COMBO_BOX (priv->view_mode_combo_box),
++ view_mode);
++
++ /* Creating the target view */
++ if (view_mode == VIEW_MODE_ICON)
++ {
++ priv->browse_files_current_view = priv->browse_files_icon_view;
++ old_view = priv->browse_files_tree_view;
++ gtk_widget_show (priv->icon_view_scale);
++ }
++ else if (view_mode == VIEW_MODE_LIST)
++ {
++ priv->browse_files_current_view = priv->browse_files_tree_view;
++ old_view = priv->browse_files_icon_view;
++ gtk_widget_hide (priv->icon_view_scale);
++ }
++ else
++ g_assert_not_reached ();
++
++ /* Set model and selection */
++ current_view_set_file_model (impl, priv->current_model);
++ current_view_set_select_multiple (impl, priv->select_multiple);
++ copy_old_selection_to_current_view (impl, old_view_mode);
++
++ /* Hide the old view */
++ g_object_set (old_view, "model", NULL, NULL);
++ gtk_widget_hide (old_view);
++
++ /* Show the new view */
++ gtk_widget_show (priv->browse_files_current_view);
++ gtk_notebook_set_current_page(priv->view_notebook, view_mode);
++}
++
++/* Callback used when view mode combo box active item is changed */
++static void
++view_mode_combo_box_changed_cb (GtkComboBox *combo,
++ GtkFileChooserWidget *impl)
++{
++ ViewMode target = gtk_combo_box_get_active (combo);
++
++ view_mode_set (impl, target);
++}
++
++/* Callback used when view mode is changed */
++gboolean
++view_notebook_switch_page_cb (GtkNotebook *notebook,
++ GtkWidget *page,
++ guint page_num,
++ gpointer user_data)
++{
++ GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (user_data);
++ view_mode_set (impl, page_num);
++ return TRUE;
++}
++
++static void
++icon_view_scale_value_changed_cb (GtkRange *range,
++ GtkFileChooserWidget *impl)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ gdouble value = gtk_range_get_value (range);
++ value = round (value / 16) * 16;
++
++ if (priv->icon_view_icon_size == (gint)value)
++ return;
++
++ priv->icon_view_icon_size = (gint)value;
++
++ if (priv->view_mode != VIEW_MODE_ICON)
++ return;
++
++ set_icon_cell_renderer_fixed_size (impl);
++
++ if (priv->browse_files_model)
++ _gtk_file_system_model_clear_cache (priv->browse_files_model, MODEL_COL_ICON_PIXBUF);
++ if (priv->search_model)
++ _gtk_file_system_model_clear_cache (priv->search_model, MODEL_COL_ICON_PIXBUF);
++ if (priv->recent_model)
++ _gtk_file_system_model_clear_cache (priv->recent_model, MODEL_COL_ICON_PIXBUF);
++
++ gtk_widget_queue_resize (priv->browse_files_current_view);
++}
++
+ static void
+ gtk_file_chooser_widget_constructed (GObject *object)
+ {
+@@ -3051,18 +3309,11 @@ set_select_multiple (GtkFileChooserWidge
+ gboolean property_notify)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+- GtkTreeSelection *selection;
+- GtkSelectionMode mode;
+
+ if (select_multiple == priv->select_multiple)
+ return;
+
+- mode = select_multiple ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE;
+-
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- gtk_tree_selection_set_mode (selection, mode);
+-
+- gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (priv->browse_files_tree_view), select_multiple);
++ current_view_set_select_multiple (impl, select_multiple);
+
+ priv->select_multiple = select_multiple;
+ g_object_notify (G_OBJECT (impl), "select-multiple");
+@@ -3189,6 +3440,7 @@ operation_mode_set_enter_location (GtkFi
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_header_stack), "location");
+ gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), TRUE);
+ location_bar_update (impl);
++ gtk_tree_view_column_set_visible (priv->list_location_column, FALSE);
+ gtk_widget_set_sensitive (priv->filter_combo, TRUE);
+ location_mode_set (impl, LOCATION_MODE_FILENAME_ENTRY);
+ }
+@@ -3218,7 +3470,7 @@ operation_mode_set_search (GtkFileChoose
+ visible_widget = gtk_stack_get_visible_child (GTK_STACK (priv->browse_files_stack));
+
+ if (visible_widget != priv->places_view &&
+- visible_widget != priv->browse_files_swin)
++ visible_widget != priv->browse_files_list_swin)
+ {
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_files_stack), "list");
+ }
+@@ -3343,6 +3595,12 @@ update_appearance (GtkFileChooserWidget
+ location_mode_set (impl, priv->location_mode);
+ }
+
++ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
++ priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
++ gtk_widget_show (priv->view_mode_combo_box);
++ else
++ gtk_widget_hide (priv->view_mode_combo_box);
++
+ if (priv->location_entry)
+ _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->action);
+
+@@ -3351,7 +3609,7 @@ update_appearance (GtkFileChooserWidget
+ /* This *is* needed; we need to redraw the file list because the "sensitivity"
+ * of files may change depending whether we are in a file or folder-only mode.
+ */
+- gtk_widget_queue_draw (priv->browse_files_tree_view);
++ gtk_widget_queue_draw (priv->browse_files_current_view);
+
+ emit_default_size_changed (impl);
+ }
+@@ -3781,14 +4039,27 @@ change_icon_theme (GtkFileChooserWidget
+ profile_start ("start", NULL);
+
+ if (gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height))
+- priv->icon_size = MAX (width, height);
++ priv->list_view_icon_size = MAX (width, height);
+ else
+- priv->icon_size = FALLBACK_ICON_SIZE;
++ priv->list_view_icon_size = FALLBACK_LIST_VIEW_ICON_SIZE;
+
+- /* the first cell in the first column is the icon column, and we have a fixed size there */
+- set_icon_cell_renderer_fixed_size (impl);
++ if (gtk_icon_size_lookup (GTK_ICON_SIZE_DIALOG, &width, &height))
++ {
++ priv->icon_view_icon_size = MAX (width, height);
++ }
++ else
++ priv->list_view_icon_size = FALLBACK_LIST_VIEW_ICON_SIZE;
+
+- clear_model_cache (impl, MODEL_COL_SURFACE);
++ /* the first cell in the first column is the icon column, and we have a fixed size there */
++ if (priv->view_mode == VIEW_MODE_LIST)
++ {
++ set_icon_cell_renderer_fixed_size (impl);
++ }
++ if (priv->browse_files_model)
++ {
++ clear_model_cache (impl, MODEL_COL_LIST_SURFACE);
++ clear_model_cache (impl, MODEL_COL_ICON_PIXBUF);
++ }
+ gtk_widget_queue_resize (priv->browse_files_tree_view);
+
+ profile_end ("end", NULL);
+@@ -3889,7 +4160,7 @@ set_sort_column (GtkFileChooserWidget *i
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+ GtkTreeSortable *sortable;
+
+- sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->browse_files_tree_view)));
++ sortable = GTK_TREE_SORTABLE (priv->current_model);
+
+ /* can happen when we're still populating the model */
+ if (sortable == NULL)
+@@ -3904,6 +4175,7 @@ static void
+ settings_load (GtkFileChooserWidget *impl)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ ViewMode view_mode;
+ gboolean show_hidden;
+ gboolean show_size_column;
+ gboolean show_type_column;
+@@ -3911,6 +4183,7 @@ settings_load (GtkFileChooserWidget *imp
+ DateFormat date_format;
+ TypeFormat type_format;
+ gint sort_column;
++ gint icon_view_scale;
+ GtkSortType sort_order;
+ StartupMode startup_mode;
+ gint sidebar_width;
+@@ -3918,6 +4191,8 @@ settings_load (GtkFileChooserWidget *imp
+
+ settings = _gtk_file_chooser_get_settings_for_widget (GTK_WIDGET (impl));
+
++ view_mode = g_settings_get_enum (settings, SETTINGS_KEY_VIEW_MODE);
++ icon_view_scale = g_settings_get_int (settings, SETTINGS_KEY_ICON_VIEW_SCALE);
+ show_hidden = g_settings_get_boolean (settings, SETTINGS_KEY_SHOW_HIDDEN);
+ show_size_column = g_settings_get_boolean (settings, SETTINGS_KEY_SHOW_SIZE_COLUMN);
+ show_type_column = g_settings_get_boolean (settings, SETTINGS_KEY_SHOW_TYPE_COLUMN);
+@@ -3929,12 +4204,20 @@ settings_load (GtkFileChooserWidget *imp
+ date_format = g_settings_get_enum (settings, SETTINGS_KEY_DATE_FORMAT);
+ type_format = g_settings_get_enum (settings, SETTINGS_KEY_TYPE_FORMAT);
+
++ gtk_range_set_value (GTK_RANGE (priv->icon_view_scale), icon_view_scale);
++ priv->icon_view_icon_size = icon_view_scale;
++
++ view_mode_set (impl, view_mode);
++
+ if (!priv->show_hidden_set)
+ set_show_hidden (impl, show_hidden);
+ priv->show_size_column = show_size_column;
+- gtk_tree_view_column_set_visible (priv->list_size_column, show_size_column);
+- priv->show_type_column = show_type_column;
+- gtk_tree_view_column_set_visible (priv->list_type_column, show_type_column);
++
++ if (priv->list_size_column) {
++ gtk_tree_view_column_set_visible (priv->list_size_column, show_size_column);
++ priv->show_type_column = show_type_column;
++ gtk_tree_view_column_set_visible (priv->list_type_column, show_type_column);
++ }
+
+ priv->sort_column = sort_column;
+ priv->sort_order = sort_order;
+@@ -3963,6 +4246,8 @@ settings_save (GtkFileChooserWidget *imp
+ /* All the other state */
+
+ g_settings_set_enum (settings, SETTINGS_KEY_LOCATION_MODE, priv->location_mode);
++ g_settings_set_enum (settings, SETTINGS_KEY_VIEW_MODE, priv->view_mode);
++ g_settings_set_int (settings, SETTINGS_KEY_ICON_VIEW_SCALE, priv->icon_view_icon_size);
+ g_settings_set_boolean (settings, SETTINGS_KEY_SHOW_HIDDEN,
+ gtk_file_chooser_get_show_hidden (GTK_FILE_CHOOSER (impl)));
+ g_settings_set_boolean (settings, SETTINGS_KEY_SHOW_SIZE_COLUMN, priv->show_size_column);
+@@ -4474,10 +4759,14 @@ load_set_model (GtkFileChooserWidget *im
+ g_assert (priv->browse_files_model != NULL);
+
+ profile_msg (" gtk_tree_view_set_model start", NULL);
+- gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view),
+- GTK_TREE_MODEL (priv->browse_files_model));
+- update_columns (impl, FALSE, _("Modified"));
+- file_list_set_sort_column_ids (impl);
++ current_view_set_file_model (impl, GTK_TREE_MODEL (priv->browse_files_model));
++ if (priv->view_mode == VIEW_MODE_LIST)
++ {
++ gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view),
++ GTK_TREE_MODEL (priv->browse_files_model));
++ update_columns (impl, FALSE, _("Modified"));
++ file_list_set_sort_column_ids (impl);
++ }
+ set_sort_column (impl);
+ profile_msg (" gtk_tree_view_set_model end", NULL);
+ priv->list_sort_ascending = TRUE;
+@@ -4557,7 +4846,7 @@ browse_files_select_first_row (GtkFileCh
+ GtkTreeIter dummy_iter;
+ GtkTreeModel *tree_model;
+
+- tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->browse_files_tree_view));
++ tree_model = priv->current_model;
+
+ if (!tree_model)
+ return;
+@@ -4576,8 +4865,7 @@ browse_files_select_first_row (GtkFileCh
+ */
+ priv->auto_selecting_first_row = TRUE;
+
+- gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->browse_files_tree_view), path, NULL, FALSE);
+-
++ current_view_set_cursor (impl, path);
+ priv->auto_selecting_first_row = FALSE;
+ }
+ gtk_tree_path_free (path);
+@@ -4603,7 +4891,13 @@ center_selected_row_foreach_cb (GtkTreeM
+ if (closure->already_centered)
+ return;
+
+- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (closure->impl->priv->browse_files_tree_view), path, NULL, TRUE, 0.5, 0.0);
++ if (closure->impl->priv->view_mode == VIEW_MODE_LIST)
++ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (closure->impl->priv->browse_files_tree_view), path, NULL, TRUE, 0.5, 0.0);
++ else if (closure->impl->priv->view_mode == VIEW_MODE_ICON)
++ gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (closure->impl->priv->browse_files_icon_view), path, TRUE, 0.5, 0.0);
++ else
++ g_assert_not_reached ();
++
+ closure->already_centered = TRUE;
+ }
+
+@@ -4611,15 +4905,11 @@ center_selected_row_foreach_cb (GtkTreeM
+ static void
+ browse_files_center_selected_row (GtkFileChooserWidget *impl)
+ {
+- GtkFileChooserWidgetPrivate *priv = impl->priv;
+ struct center_selected_row_closure closure;
+- GtkTreeSelection *selection;
+-
+ closure.impl = impl;
+ closure.already_centered = FALSE;
+
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- gtk_tree_selection_selected_foreach (selection, center_selected_row_foreach_cb, &closure);
++ current_selection_selected_foreach(impl, center_selected_row_foreach_cb, &closure);
+ }
+
+ static gboolean
+@@ -4627,7 +4917,6 @@ show_and_select_files (GtkFileChooserWid
+ GSList *files)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+- GtkTreeSelection *selection;
+ GtkFileSystemModel *fsmodel;
+ gboolean enabled_hidden, removed_filters;
+ gboolean selected_a_file;
+@@ -4636,8 +4925,7 @@ show_and_select_files (GtkFileChooserWid
+ g_assert (priv->load_state == LOAD_FINISHED);
+ g_assert (priv->browse_files_model != NULL);
+
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- fsmodel = GTK_FILE_SYSTEM_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->browse_files_tree_view)));
++ fsmodel = GTK_FILE_SYSTEM_MODEL (priv->current_model);
+
+ g_assert (fsmodel == priv->browse_files_model);
+
+@@ -4692,11 +4980,10 @@ show_and_select_files (GtkFileChooserWid
+ {
+ GtkTreePath *path;
+
+- gtk_tree_selection_select_iter (selection, &iter);
++ current_selection_select_iter (impl, &iter);
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (fsmodel), &iter);
+- gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->browse_files_tree_view),
+- path, NULL, FALSE);
++ current_view_set_cursor (impl, path);
+ gtk_tree_path_free (path);
+
+ selected_a_file = TRUE;
+@@ -4847,12 +5134,15 @@ stop_loading_and_clear_list_model (GtkFi
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+
++ if (priv->current_model == GTK_TREE_MODEL (priv->browse_files_model))
++ priv->current_model = NULL;
++
+ load_remove_timer (impl, LOAD_EMPTY);
+
+ g_set_object (&priv->browse_files_model, NULL);
+
+ if (remove)
+- gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view), NULL);
++ current_view_set_file_model (impl, NULL);
+ }
+
+ /* Replace 'target' with 'replacement' in the input string. */
+@@ -5123,6 +5413,18 @@ end:
+ }
+
+ static gboolean
++get_visible_range (GtkTreePath **start, GtkTreePath **end,
++ GtkFileChooserWidget *impl)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ if (priv->view_mode == VIEW_MODE_LIST)
++ return gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->browse_files_tree_view), start, end);
++ if (priv->view_mode == VIEW_MODE_ICON)
++ return gtk_icon_view_get_visible_range (GTK_ICON_VIEW (priv->browse_files_icon_view), start, end);
++ g_assert_not_reached ();
++}
++
++static gboolean
+ file_system_model_set (GtkFileSystemModel *model,
+ GFile *file,
+ GFileInfo *info,
+@@ -5181,12 +5483,15 @@ file_system_model_set (GtkFileSystemMode
+ else
+ g_value_set_boolean (value, TRUE);
+ break;
+- case MODEL_COL_SURFACE:
++ case MODEL_COL_LIST_SURFACE:
++ /* don't load list view icons in other view modes */
++ if(priv->view_mode != VIEW_MODE_LIST)
++ return FALSE;
+ if (info)
+ {
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ICON))
+ {
+- g_value_take_boxed (value, _gtk_file_info_render_icon (info, GTK_WIDGET (impl), priv->icon_size));
++ g_value_take_boxed (value, _gtk_file_info_render_icon (info, GTK_WIDGET (impl), priv->list_view_icon_size));
+ }
+ else
+ {
+@@ -5240,6 +5545,76 @@ file_system_model_set (GtkFileSystemMode
+ else
+ g_value_set_boxed (value, NULL);
+ break;
++ case MODEL_COL_ICON_PIXBUF:
++ if (info)
++ {
++ GtkTreeModel *tree_model;
++ GtkTreePath *path, *start, *end;
++ GtkTreeIter iter;
++ int icon_size;
++ gboolean file_visible;
++
++ tree_model = priv->current_model;
++ if (tree_model != GTK_TREE_MODEL (model))
++ return FALSE;
++
++ /* #1 use standard icon if it is loaded */
++ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ICON))
++ {
++ icon_size = priv->icon_view_icon_size;
++
++ cairo_surface_t *icon_surface = _gtk_file_info_render_icon (info, GTK_WIDGET (impl), icon_size);
++ GdkPixbuf *icon_pixbuf = gdk_pixbuf_get_from_surface(icon_surface,
++ 0, 0,
++ cairo_image_surface_get_width(icon_surface),
++ cairo_image_surface_get_height(icon_surface));
++ cairo_surface_destroy(icon_surface);
++
++ g_value_take_object (value, icon_pixbuf);
++ return TRUE;
++ }
++
++ if (!get_visible_range (&start, &end, impl))
++ return FALSE;
++
++ if (!_gtk_file_system_model_get_iter_for_file (model,
++ &iter,
++ file))
++ g_assert_not_reached ();
++
++ path = gtk_tree_model_get_path (tree_model, &iter);
++ file_visible = (gtk_tree_path_compare (start, path) != 1 &&
++ gtk_tree_path_compare (path, end) != 1);
++
++ gtk_tree_path_free (path);
++ gtk_tree_path_free (start);
++ gtk_tree_path_free (end);
++
++ if (file_visible)
++ {
++ /* #2 start loading standard icon (callback will be handled by #1) */
++ if (!g_file_info_has_attribute (info, "filechooser::icon_queried"))
++ {
++ g_file_info_set_attribute_boolean (info, "filechooser::icon_queried", TRUE);
++ g_file_query_info_async (file,
++ G_FILE_ATTRIBUTE_THUMBNAIL_PATH ","
++ G_FILE_ATTRIBUTE_THUMBNAILING_FAILED ","
++ G_FILE_ATTRIBUTE_STANDARD_ICON,
++ G_FILE_QUERY_INFO_NONE,
++ G_PRIORITY_DEFAULT,
++ _gtk_file_system_model_get_cancellable (model),
++ file_system_model_got_thumbnail,
++ model);
++ }
++
++ }
++ return FALSE;
++ }
++ else
++ {
++ g_value_set_object (value, NULL);
++ }
++ break;
+ case MODEL_COL_SIZE:
+ g_value_set_int64 (value, info ? g_file_info_get_size (info) : 0);
+ break;
+@@ -5432,7 +5807,6 @@ static void
+ update_chooser_entry (GtkFileChooserWidget *impl)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+- GtkTreeSelection *selection;
+ struct update_chooser_entry_selected_foreach_closure closure;
+
+ /* no need to update the file chooser's entry if there's no entry */
+@@ -5449,9 +5823,8 @@ update_chooser_entry (GtkFileChooserWidg
+
+ g_assert (priv->location_entry != NULL);
+
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+ closure.num_selected = 0;
+- gtk_tree_selection_selected_foreach (selection, update_chooser_entry_selected_foreach, &closure);
++ current_selection_selected_foreach (impl, update_chooser_entry_selected_foreach, &closure);
+
+ if (closure.num_selected == 0)
+ {
+@@ -5948,19 +6321,15 @@ gtk_file_chooser_widget_unselect_file (G
+ {
+ GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+- GtkTreeView *tree_view;
+- GtkTreeModel *model;
+ GtkTreeIter iter;
+
+- tree_view = GTK_TREE_VIEW (priv->browse_files_tree_view);
+- model = gtk_tree_view_get_model (tree_view);
+- if (!model)
++ if (!priv->current_model)
+ return;
+
+- if (!_gtk_file_system_model_get_iter_for_file (GTK_FILE_SYSTEM_MODEL (model), &iter, file))
++ if (!_gtk_file_system_model_get_iter_for_file (GTK_FILE_SYSTEM_MODEL (priv->current_model), &iter, file))
+ return;
+
+- gtk_tree_selection_unselect_iter (gtk_tree_view_get_selection (tree_view), &iter);
++ current_selection_unselect_iter (impl, &iter);
+ }
+
+ static gboolean
+@@ -5971,12 +6340,9 @@ maybe_select (GtkTreeModel *model,
+ {
+ GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (data);
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+- GtkTreeSelection *selection;
+ gboolean is_sensitive;
+ gboolean is_folder;
+
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+-
+ gtk_tree_model_get (model, iter,
+ MODEL_COL_IS_FOLDER, &is_folder,
+ MODEL_COL_IS_SENSITIVE, &is_sensitive,
+@@ -5985,9 +6351,9 @@ maybe_select (GtkTreeModel *model,
+ if (is_sensitive &&
+ ((is_folder && priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ||
+ (!is_folder && priv->action == GTK_FILE_CHOOSER_ACTION_OPEN)))
+- gtk_tree_selection_select_iter (selection, iter);
++ current_selection_select_iter (impl, iter);
+ else
+- gtk_tree_selection_unselect_iter (selection, iter);
++ current_selection_unselect_iter (impl, iter);
+
+ return FALSE;
+ }
+@@ -6003,8 +6369,15 @@ gtk_file_chooser_widget_select_all (GtkF
+ {
+ GtkTreeSelection *selection;
+
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- gtk_tree_selection_select_all (selection);
++ if (priv->view_mode == VIEW_MODE_LIST)
++ {
++ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
++ gtk_tree_selection_select_all (selection);
++ }
++ else if (priv->view_mode == VIEW_MODE_ICON)
++ gtk_icon_view_select_all (GTK_ICON_VIEW (priv->browse_files_icon_view));
++ else
++ g_assert_not_reached();
+ return;
+ }
+
+@@ -6017,10 +6390,7 @@ static void
+ gtk_file_chooser_widget_unselect_all (GtkFileChooser *chooser)
+ {
+ GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
+- GtkFileChooserWidgetPrivate *priv = impl->priv;
+- GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+-
+- gtk_tree_selection_unselect_all (selection);
++ current_selection_unselect_all (impl);
+ pending_select_files_free (impl);
+ }
+
+@@ -6176,15 +6546,13 @@ gtk_file_chooser_widget_get_files (GtkFi
+ current_focus = NULL;
+
+ file_list_seen = FALSE;
+- if (current_focus == priv->browse_files_tree_view)
++ if (current_focus == priv->browse_files_current_view)
+ {
+- GtkTreeSelection *selection;
+-
+ file_list:
+
+ file_list_seen = TRUE;
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- gtk_tree_selection_selected_foreach (selection, get_files_foreach, &info);
++
++ current_selection_selected_foreach (impl, get_files_foreach, &info);
+
+ /* If there is no selection in the file list, we probably have this situation:
+ *
+@@ -6218,7 +6586,7 @@ gtk_file_chooser_widget_get_files (GtkFi
+ else
+ return NULL;
+ }
+- else if (priv->toplevel_last_focus_widget == priv->browse_files_tree_view)
++ else if (priv->toplevel_last_focus_widget == priv->browse_files_current_view)
+ goto file_list;
+ else if (priv->location_entry && priv->toplevel_last_focus_widget == priv->location_entry)
+ goto file_entry;
+@@ -6496,8 +6864,6 @@ switch_folder_foreach_cb (GtkTreeModel *
+ static void
+ switch_to_selected_folder (GtkFileChooserWidget *impl)
+ {
+- GtkFileChooserWidgetPrivate *priv = impl->priv;
+- GtkTreeSelection *selection;
+ struct switch_folder_closure closure;
+
+ /* We do this with foreach() rather than get_selected() as we may be in
+@@ -6508,8 +6874,7 @@ switch_to_selected_folder (GtkFileChoose
+ closure.file = NULL;
+ closure.num_selected = 0;
+
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- gtk_tree_selection_selected_foreach (selection, switch_folder_foreach_cb, &closure);
++ current_selection_selected_foreach (impl, switch_folder_foreach_cb, &closure);
+
+ g_assert (closure.file && closure.num_selected == 1);
+
+@@ -6527,19 +6892,33 @@ get_selected_file_info_from_file_list (G
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GFileInfo *info;
+- GtkTreeModel *model;
+
+ g_assert (!priv->select_multiple);
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- if (!gtk_tree_selection_get_selected (selection, &model, &iter))
++
++ if (priv->view_mode == VIEW_MODE_LIST)
+ {
+- *had_selection = FALSE;
+- return NULL;
+- }
++ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
++ if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
++ {
++ *had_selection = FALSE;
++ return NULL;
++ }
+
+- *had_selection = TRUE;
++ *had_selection = TRUE;
++ }
++ else if (priv->view_mode == VIEW_MODE_ICON)
++ {
++ if (!get_selected_tree_iter_from_icon_view (impl, &iter))
++ {
++ *had_selection = FALSE;
++ return NULL;
++ }
++ *had_selection = TRUE;
++ }
++ else
++ g_assert_not_reached();
+
+- info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (model), &iter);
++ info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (priv->current_model), &iter);
+ return info;
+ }
+
+@@ -7036,7 +7415,7 @@ gtk_file_chooser_widget_should_respond (
+
+ current_focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
+
+- if (current_focus == priv->browse_files_tree_view)
++ if (current_focus == priv->browse_files_current_view)
+ {
+ /* The following array encodes what we do based on the priv->action and the
+ * number of files selected.
+@@ -7283,9 +7662,9 @@ gtk_file_chooser_widget_initial_focus (G
+ {
+ if (priv->location_mode == LOCATION_MODE_PATH_BAR
+ || priv->operation_mode == OPERATION_MODE_RECENT)
+- widget = priv->browse_files_tree_view;
++ widget = priv->browse_files_current_view;
+ else
+- widget = priv->location_entry;
++ widget = priv->location_entry;
+ }
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+@@ -7298,6 +7677,7 @@ gtk_file_chooser_widget_initial_focus (G
+
+ g_assert (widget != NULL);
+ gtk_widget_grab_focus (widget);
++ create_browse_files_icon_view (impl);
+ }
+
+ static void
+@@ -7321,45 +7701,23 @@ selected_foreach_get_file_cb (GtkTreeMod
+ static GSList *
+ get_selected_files (GtkFileChooserWidget *impl)
+ {
+- GtkFileChooserWidgetPrivate *priv = impl->priv;
+ GSList *result;
+- GtkTreeSelection *selection;
+-
+ result = NULL;
+
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- gtk_tree_selection_selected_foreach (selection, selected_foreach_get_file_cb, &result);
++ current_selection_selected_foreach (impl, selected_foreach_get_file_cb, &result);
+ result = g_slist_reverse (result);
+
+ return result;
+ }
+
+-static void
+-selected_foreach_get_info_cb (GtkTreeModel *model,
+- GtkTreePath *path,
+- GtkTreeIter *iter,
+- gpointer data)
+-{
+- GSList **list;
+- GFileInfo *info;
+-
+- list = data;
+-
+- info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (model), iter);
+- *list = g_slist_prepend (*list, g_object_ref (info));
+-}
+-
+ static GSList *
+ get_selected_infos (GtkFileChooserWidget *impl)
+ {
+- GtkFileChooserWidgetPrivate *priv = impl->priv;
+ GSList *result;
+- GtkTreeSelection *selection;
+
+ result = NULL;
+
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- gtk_tree_selection_selected_foreach (selection, selected_foreach_get_info_cb, &result);
++ current_selection_selected_foreach (impl, selected_foreach_get_file_cb, &result);
+ result = g_slist_reverse (result);
+
+ return result;
+@@ -7429,6 +7787,7 @@ search_engine_finished_cb (GtkSearchEngi
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_files_stack), "empty");
+ gtk_entry_grab_focus_without_selecting (GTK_ENTRY (priv->search_entry));
+ }
++ current_view_set_file_model (impl, GTK_TREE_MODEL (priv->search_model));
+ }
+
+ static void
+@@ -7454,7 +7813,7 @@ search_clear_model (GtkFileChooserWidget
+
+ if (remove &&
+ gtk_tree_view_get_model (GTK_TREE_VIEW (priv->browse_files_tree_view)) == GTK_TREE_MODEL (priv->search_model))
+- gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view), NULL);
++ current_view_set_file_model (impl, NULL);
+
+ g_clear_object (&priv->search_model);
+ }
+@@ -7664,7 +8023,7 @@ recent_clear_model (GtkFileChooserWidget
+ return;
+
+ if (remove)
+- gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view), NULL);
++ current_view_set_file_model (impl, NULL);
+
+ g_set_object (&priv->recent_model, NULL);
+ }
+@@ -7717,8 +8076,7 @@ recent_idle_cleanup (gpointer data)
+ GtkFileChooserWidget *impl = load_data->impl;
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+
+- gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view),
+- GTK_TREE_MODEL (priv->recent_model));
++ current_view_set_file_model (impl, GTK_TREE_MODEL (priv->recent_model));
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), 0);
+
+ gtk_tree_view_column_set_sort_column_id (priv->list_name_column, -1);
+@@ -7866,12 +8224,8 @@ static gboolean
+ recent_should_respond (GtkFileChooserWidget *impl)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+- GtkTreeSelection *selection;
+-
+ g_assert (priv->operation_mode == OPERATION_MODE_RECENT);
+-
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- return (gtk_tree_selection_count_selected_rows (selection) != 0);
++ return (current_selection_count_selected_rows (impl) != 0);
+ }
+
+ static void
+@@ -7931,29 +8285,40 @@ check_preview_change (GtkFileChooserWidg
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+
+- model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+- if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_SINGLE ||
+- gtk_tree_selection_get_mode (selection) == GTK_SELECTION_BROWSE)
++ model = priv->current_model;
++
++ if (priv->view_mode == VIEW_MODE_LIST)
+ {
+- GtkTreeIter iter;
++ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
++ if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_SINGLE ||
++ gtk_tree_selection_get_mode (selection) == GTK_SELECTION_BROWSE)
++ {
++ GtkTreeIter iter;
++
++ if (gtk_tree_selection_get_selected (selection, NULL, &iter))
++ path = gtk_tree_model_get_path (model, &iter);
++ else
++ path = NULL;
++ }
+
+- if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+- path = gtk_tree_model_get_path (model, &iter);
+ else
+- path = NULL;
+- }
+- else
+- {
+- gtk_tree_view_get_cursor (GTK_TREE_VIEW (priv->browse_files_tree_view), &path, NULL);
+- if (path && !gtk_tree_selection_path_is_selected (selection, path))
+ {
+- gtk_tree_path_free (path);
+- path = NULL;
++ gtk_tree_view_get_cursor (GTK_TREE_VIEW (priv->browse_files_tree_view), &path, NULL);
++ if (path && !gtk_tree_selection_path_is_selected (selection, path))
++ {
++ gtk_tree_path_free (path);
++ path = NULL;
++ }
+ }
+ }
++ else if (priv->view_mode == VIEW_MODE_ICON)
++ {
++ gtk_icon_view_get_cursor (GTK_ICON_VIEW (priv->browse_files_icon_view), &path, NULL);
++ }
++ else
++ g_assert_not_reached ();
+
+- if (path)
++ if (path && model)
+ {
+ GtkTreeIter iter;
+
+@@ -8037,15 +8402,13 @@ list_select_func (GtkTreeSelection *sele
+ return TRUE;
+ }
+
++/* GtkTreeSelection or GtkIconView selection changed. */
+ static void
+-list_selection_changed (GtkTreeSelection *selection,
+- GtkFileChooserWidget *impl)
++list_selection_changed (void *selection,
++ GtkFileChooserWidget *impl)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+
+- if (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->browse_files_tree_view)) == NULL)
+- return;
+-
+ if (priv->location_entry)
+ update_chooser_entry (impl);
+
+@@ -8070,15 +8433,34 @@ list_row_activated (GtkTreeView
+ GtkTreeViewColumn *column,
+ GtkFileChooserWidget *impl)
+ {
++ GtkTreeModel *model;
++ model = gtk_tree_view_get_model (tree_view);
++ item_activated (model, path, impl);
++}
++
++/* Callback used when a item in the icon file list is activated. */
++static void
++icon_item_activated (GtkIconView *icon_view,
++ GtkTreePath *path,
++ GtkFileChooserWidget *impl)
++{
++ GtkTreeModel *model;
++ model = gtk_icon_view_get_model (icon_view);
++ item_activated (model, path, impl);
++}
++
++/* Common implementation for list_row_activated and icon_item_activated */
++static void
++item_activated (GtkTreeModel *model,
++ GtkTreePath *path,
++ GtkFileChooserWidget *impl)
++{
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+ GFile *file;
+ GtkTreeIter iter;
+- GtkTreeModel *model;
+ gboolean is_folder;
+ gboolean is_sensitive;
+
+- model = gtk_tree_view_get_model (tree_view);
+-
+ if (!gtk_tree_model_get_iter (model, &iter, path))
+ return;
+
+@@ -8098,7 +8480,7 @@ list_row_activated (GtkTreeView
+ priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ g_signal_emit_by_name (impl, "file-activated");
+
+- out:
++ out:
+
+ if (file)
+ g_object_unref (file);
+@@ -8129,10 +8511,13 @@ static void
+ update_cell_renderer_attributes (GtkFileChooserWidget *impl)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ /* only applicable in the tree view (i.e. list view) */
++ if (!priv->browse_files_tree_view)
++ return;
+
+ gtk_tree_view_column_set_attributes (priv->list_name_column,
+ priv->list_pixbuf_renderer,
+- "surface", MODEL_COL_SURFACE,
++ "surface", MODEL_COL_LIST_SURFACE,
+ "sensitive", MODEL_COL_IS_SENSITIVE,
+ NULL);
+ gtk_tree_view_column_set_attributes (priv->list_name_column,
+@@ -8711,15 +9096,19 @@ gtk_file_chooser_widget_class_init (GtkF
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_files_stack);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, places_sidebar);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, places_view);
++ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, view_notebook);
++ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_files_list_swin);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_files_tree_view);
+- gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_files_swin);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_header_revealer);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_header_stack);
++ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_files_icon_swin);
++ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_files_icon_view);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_new_folder_button);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_path_bar_size_group);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_path_bar);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, filter_combo_hbox);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, filter_combo);
++ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, icon_view_scale);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, preview_box);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, extra_align);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, extra_and_filters);
+@@ -8738,6 +9127,7 @@ gtk_file_chooser_widget_class_init (GtkF
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, list_type_renderer);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, list_location_column);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, list_location_renderer);
++ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, list_icon_renderer);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, new_folder_name_entry);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, new_folder_create_button);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, new_folder_error_label);
+@@ -8747,6 +9137,7 @@ gtk_file_chooser_widget_class_init (GtkF
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, rename_file_error_label);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, rename_file_popover);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, remote_warning_bar);
++ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, view_mode_combo_box);
+
+ /* And a *lot* of callbacks to bind ... */
+ gtk_widget_class_bind_template_callback (widget_class, browse_files_key_press_event_cb);
+@@ -8761,6 +9152,10 @@ gtk_file_chooser_widget_class_init (GtkF
+ gtk_widget_class_bind_template_callback (widget_class, file_list_drag_end_cb);
+ gtk_widget_class_bind_template_callback (widget_class, list_selection_changed);
+ gtk_widget_class_bind_template_callback (widget_class, list_cursor_changed);
++ gtk_widget_class_bind_template_callback (widget_class, icon_item_activated);
++ gtk_widget_class_bind_template_callback (widget_class, icon_view_scale_value_changed_cb);
++ gtk_widget_class_bind_template_callback (widget_class, view_mode_combo_box_changed_cb);
++ gtk_widget_class_bind_template_callback (widget_class, view_notebook_switch_page_cb);
+ gtk_widget_class_bind_template_callback (widget_class, filter_combo_changed);
+ gtk_widget_class_bind_template_callback (widget_class, path_bar_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, places_sidebar_open_location_cb);
+@@ -8810,6 +9205,18 @@ post_process_ui (GtkFileChooserWidget *i
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+ gtk_drag_dest_add_uri_targets (impl->priv->browse_files_tree_view);
+
++ /* Setup file list iconview */
++ gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW (impl->priv->browse_files_icon_view),
++ GDK_BUTTON1_MASK,
++ NULL, 0,
++ GDK_ACTION_COPY | GDK_ACTION_MOVE);
++ gtk_drag_source_add_uri_targets (impl->priv->browse_files_icon_view);
++ gtk_drag_dest_set (impl->priv->browse_files_icon_view,
++ GTK_DEST_DEFAULT_ALL,
++ NULL, 0,
++ GDK_ACTION_COPY | GDK_ACTION_MOVE);
++ gtk_drag_dest_add_uri_targets (impl->priv->browse_files_icon_view);
++
+ /* File browser treemodel columns are shared between GtkFileChooser implementations,
+ * so we don't set cell renderer attributes in GtkBuilder, but rather keep that
+ * in code.
+@@ -8841,6 +9248,7 @@ post_process_ui (GtkFileChooserWidget *i
+ * that priv->icon_size be already setup.
+ */
+ set_icon_cell_renderer_fixed_size (impl);
++ impl->priv->browse_files_current_view = impl->priv->browse_files_tree_view;
+
+ atk_obj = gtk_widget_get_accessible (impl->priv->browse_new_folder_button);
+ if (GTK_IS_ACCESSIBLE (atk_obj))
+@@ -8902,7 +9310,8 @@ gtk_file_chooser_widget_init (GtkFileCho
+ priv->show_size_column = TRUE;
+ priv->show_type_column = TRUE;
+ priv->type_format = TYPE_FORMAT_MIME;
+- priv->icon_size = FALLBACK_ICON_SIZE;
++ priv->list_view_icon_size = FALLBACK_LIST_VIEW_ICON_SIZE;
++ priv->icon_view_icon_size = FALLBACK_ICON_VIEW_ICON_SIZE;
+ priv->load_state = LOAD_EMPTY;
+ priv->reload_state = RELOAD_EMPTY;
+ priv->pending_select_files = NULL;
+@@ -8914,6 +9323,7 @@ gtk_file_chooser_widget_init (GtkFileCho
+ priv->create_folders = TRUE;
+ priv->auto_selecting_first_row = FALSE;
+ priv->renamed_file = NULL;
++ priv->view_mode = VIEW_MODE_LIST;
+
+ /* Ensure GTK+ private types used by the template
+ * definition before calling gtk_widget_init_template()
+@@ -8961,6 +9371,258 @@ gtk_file_chooser_widget_new (GtkFileChoo
+ NULL);
+ }
+
++static gboolean
++get_selected_tree_iter_from_icon_view (GtkFileChooserWidget *impl,
++ GtkTreeIter *iter_out)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ GList *icon_selection;
++ GtkTreePath *icon_selection_path;
++
++ icon_selection = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (priv->browse_files_icon_view));
++ if (!icon_selection)
++ return FALSE;
++
++ icon_selection_path = g_list_nth_data (icon_selection, 0);
++ gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->current_model),
++ iter_out,
++ icon_selection_path);
++
++ g_list_foreach (icon_selection, (GFunc) gtk_tree_path_free, NULL);
++ g_list_free (icon_selection);
++ return TRUE;
++}
++
++static void
++icon_view_selection_selected_foreach (GtkFileChooserWidget *impl,
++ GtkTreeSelectionForeachFunc func,
++ gpointer data)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ GtkTreeIter iter;
++ GList *icon_selection;
++ GList *elem;
++ GtkTreePath *icon_selection_path;
++
++ icon_selection = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (priv->browse_files_icon_view));
++ for (elem = icon_selection; elem; elem = elem->next)
++ {
++ icon_selection_path = elem->data;
++ gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->current_model),
++ &iter,
++ icon_selection_path);
++ (* func) (GTK_TREE_MODEL (priv->current_model),
++ icon_selection_path,
++ &iter,
++ data);
++ }
++
++ g_list_foreach (icon_selection, (GFunc) gtk_tree_path_free, NULL);
++ g_list_free (icon_selection);
++}
++
++static void
++selection_selected_foreach (GtkFileChooserWidget *impl,
++ ViewMode view,
++ GtkTreeSelectionForeachFunc func,
++ gpointer data)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ if (priv->current_model == NULL)
++ return;
++
++ if (view == VIEW_MODE_LIST)
++ {
++ GtkTreeSelection *selection;
++ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
++ gtk_tree_selection_selected_foreach (selection, func, data);
++ }
++ else if (view == VIEW_MODE_ICON)
++ icon_view_selection_selected_foreach (impl, func, data);
++ else
++ g_assert_not_reached ();
++}
++
++static void
++current_selection_selected_foreach (GtkFileChooserWidget *impl,
++ GtkTreeSelectionForeachFunc func,
++ gpointer data)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ selection_selected_foreach (impl, priv->view_mode, func, data);
++}
++
++static guint
++current_selection_count_selected_rows (GtkFileChooserWidget *impl)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ if (priv->view_mode == VIEW_MODE_LIST)
++ {
++ GtkTreeSelection *selection;
++ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
++ return gtk_tree_selection_count_selected_rows (selection);
++ }
++ if (priv->view_mode == VIEW_MODE_ICON)
++ {
++ GList *icon_selection;
++ icon_selection = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (priv->browse_files_icon_view));
++ guint count = g_list_length (icon_selection);
++ g_list_foreach (icon_selection, (GFunc) gtk_tree_path_free, NULL);
++ g_list_free (icon_selection);
++ return count;
++ }
++ g_assert_not_reached ();
++ return 0;
++}
++
++static void
++selection_select_iter (GtkFileChooserWidget *impl,
++ GtkTreeIter *iter,
++ ViewMode target)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ if (target == VIEW_MODE_LIST)
++ {
++ GtkTreeSelection *selection;
++ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
++ gtk_tree_selection_select_iter (selection, iter);
++ }
++ else if (target == VIEW_MODE_ICON)
++ {
++ GtkTreePath *path;
++ path = gtk_tree_model_get_path (priv->current_model, iter);
++ gtk_icon_view_select_path (GTK_ICON_VIEW (priv->browse_files_icon_view), path);
++ gtk_tree_path_free (path);
++ }
++ else
++ g_assert_not_reached ();
++}
++
++static void
++current_selection_select_iter (GtkFileChooserWidget *impl,
++ GtkTreeIter *iter)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ selection_select_iter (impl, iter, priv->view_mode);
++}
++
++struct copy_old_selection_to_current_view_closure {
++ GtkFileChooserWidget *impl;
++};
++
++static void
++copy_old_selection_to_current_view_foreach_cp (GtkTreeModel *model,
++ GtkTreePath *path,
++ GtkTreeIter *iter,
++ gpointer data)
++{
++ struct copy_old_selection_to_current_view_closure *closure;
++ closure = data;
++ selection_select_iter (closure->impl, iter, closure->impl->priv->view_mode);
++}
++
++static void
++copy_old_selection_to_current_view (GtkFileChooserWidget *impl,
++ ViewMode old_view_mode)
++{
++ struct copy_old_selection_to_current_view_closure closure;
++ closure.impl = impl;
++
++ selection_selected_foreach(impl,
++ old_view_mode,
++ copy_old_selection_to_current_view_foreach_cp,
++ &closure);
++}
++
++static void
++current_selection_unselect_iter (GtkFileChooserWidget *impl,
++ GtkTreeIter *iter)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ if (priv->view_mode == VIEW_MODE_LIST)
++ {
++ GtkTreeSelection *selection;
++ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
++ gtk_tree_selection_unselect_iter (selection, iter);
++ }
++ else if (priv->view_mode == VIEW_MODE_ICON)
++ {
++ GtkTreePath *path;
++ path = gtk_tree_model_get_path (priv->current_model, iter);
++ gtk_icon_view_unselect_path (GTK_ICON_VIEW (priv->browse_files_icon_view), path);
++ gtk_tree_path_free (path);
++ }
++ else
++ g_assert_not_reached ();
++}
++
++static void
++current_selection_unselect_all (GtkFileChooserWidget *impl)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ if (priv->view_mode == VIEW_MODE_LIST)
++ {
++ GtkTreeSelection *selection;
++ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
++ gtk_tree_selection_unselect_all (selection);
++ }
++ else if (priv->view_mode == VIEW_MODE_ICON)
++ gtk_icon_view_unselect_all (GTK_ICON_VIEW (priv->browse_files_icon_view));
++ else
++ g_assert_not_reached ();
++}
++
++static void
++current_view_set_file_model (GtkFileChooserWidget *impl, GtkTreeModel *model)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ GtkWidget *view;
++
++ priv->current_model = model;
++
++ if (priv->view_mode == VIEW_MODE_LIST)
++ view = priv->browse_files_tree_view;
++ else if (priv->view_mode == VIEW_MODE_ICON)
++ view = priv->browse_files_icon_view;
++ else
++ g_assert_not_reached ();
++
++ g_object_set (view, "model", priv->current_model, NULL);
++}
++
++static void
++current_view_set_cursor (GtkFileChooserWidget *impl, GtkTreePath *path)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ if (priv->view_mode == VIEW_MODE_LIST)
++ gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->browse_files_tree_view), path, NULL, FALSE);
++ else if (priv->view_mode == VIEW_MODE_ICON)
++ gtk_icon_view_set_cursor (GTK_ICON_VIEW (priv->browse_files_icon_view), path, NULL, FALSE);
++ else
++ g_assert_not_reached ();
++}
++
++static void
++current_view_set_select_multiple (GtkFileChooserWidget *impl, gboolean select_multiple)
++{
++ GtkFileChooserWidgetPrivate *priv = impl->priv;
++ GtkTreeSelection *selection;
++ GtkSelectionMode mode;
++
++ mode = select_multiple ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_BROWSE;
++
++ if (priv->view_mode == VIEW_MODE_LIST)
++ {
++ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
++ gtk_tree_selection_set_mode (selection, mode);
++ gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (priv->browse_files_tree_view), select_multiple);
++ }
++ else if (priv->view_mode == VIEW_MODE_ICON)
++ gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (priv->browse_files_icon_view), mode);
++ else
++ g_assert_not_reached ();
++}
++
+ static void
+ gtk_file_chooser_widget_add_choice (GtkFileChooser *chooser,
+ const char *id,
+@@ -9080,4 +9742,3 @@ gtk_file_chooser_widget_get_choice (GtkF
+
+ return NULL;
+ }
+-
+--- a/gtk/org.gtk.Settings.FileChooser.gschema.xml
++++ b/gtk/org.gtk.Settings.FileChooser.gschema.xml
+@@ -55,6 +55,11 @@
+ <value nick='category' value='2'/>
+ </enum>
+
++ <enum id='org.gtk.Settings.FileChooser.ViewMode'>
++ <value nick='list-view' value='0'/>
++ <value nick='icon-view' value='1'/>
++ </enum>
++
+ <schema id='org.gtk.Settings.FileChooser' path='/org/gtk/settings/file-chooser/'>
+ <key name='last-folder-uri' type='s'>
+ <default>""</default>
+@@ -63,16 +68,30 @@
+ <default>'path-bar'</default>
+ <summary>Location mode</summary>
+ <description>
+- Controls whether the file chooser shows just a path bar, or a visible entry
++ Controls whether the file chooser shows just a path bar, or a visible entry
+ for the filename as well, for the benefit of typing-oriented users. The
+ possible values for these modes are "path-bar" and "filename-entry".
+ </description>
+ </key>
++ <key name='view-mode' enum='org.gtk.Settings.FileChooser.ViewMode'>
++ <default>'list-view'</default>
++ <summary>Change view mode</summary>
++ <description>
++ Controls the view mode used.
++ </description>
++ </key>
++ <key name='icon-view-scale' type='i'>
++ <default>48</default>
++ <summary>Change icon size</summary>
++ <description>
++ Controls the size of the icons in icon view mode.
++ </description>
++ </key>
+ <key name='show-hidden' type='b'>
+ <default>false</default>
+ <summary>Show hidden files</summary>
+ <description>
+- Controls whether the file chooser shows hidden files or not.
++ Controls whether the file chooser shows hidden files or not.
+ </description>
+ </key>
+ <key type="b" name="sort-directories-first">
+@@ -91,37 +110,37 @@
+ <default>true</default>
+ <summary>Show file sizes</summary>
+ <description>
+- Controls whether the file chooser shows a column with file sizes.
++ Controls whether the file chooser shows a column with file sizes.
+ </description>
+ </key>
+ <key name='show-type-column' type='b'>
+ <default>true</default>
+ <summary>Show file types</summary>
+ <description>
+- Controls whether the file chooser shows a column with file types.
++ Controls whether the file chooser shows a column with file types.
+ </description>
+ </key>
+ <key name='sort-column' enum='org.gtk.Settings.FileChooser.SortColumn'>
+ <default>'name'</default>
+ <summary>Sort column</summary>
+ <description>
+- Can be one of "name", "modified", or "size". It controls
+- which of the columns in the file chooser is used for sorting
+- the list of files.
++ Can be one of "name", "modified", or "size". It controls
++ which of the columns in the file chooser is used for sorting
++ the list of files.
+ </description>
+ </key>
+ <key name='sort-order' enum='org.gtk.Settings.FileChooser.SortOrder'>
+ <default>'ascending'</default>
+ <summary>Sort order</summary>
+ <description>
+- Can be one of the strings "ascending" or "descending".
++ Can be one of the strings "ascending" or "descending".
+ </description>
+ </key>
+ <key name='window-position' type='(ii)'>
+ <default>(-1, -1)</default>
+ <summary>Window position</summary>
+ <description>
+- The (x, y) coordinates of the upper-left corner of the GtkFileChooserDialog's
++ The (x, y) coordinates of the upper-left corner of the GtkFileChooserDialog's
+ window.
+ </description>
+ </key>
+--- a/gtk/ui/gtkfilechooserwidget.ui
++++ b/gtk/ui/gtkfilechooserwidget.ui
+@@ -9,6 +9,56 @@
+ <property name="visible">1</property>
+ <property name="orientation">vertical</property>
+ <child>
++ <object class="GtkBox" id="combo_box_and_scale">
++ <property name="visible">1</property>
++ <child>
++ <object class="GtkComboBoxText" id="view_mode_combo_box">
++ <items>
++ <item translatable="yes" id="browse_files_tree_view">List View</item>
++ <item translatable="yes" id="browse_files_icon_view">Icon View</item>
++ </items>
++ <property name="active">0</property>
++ <property name="visible">1</property>
++ <property name="tooltip-text" translatable="yes">Select filechooser view</property>
++ <property name="halign">start</property>
++ <property name="valign">start</property>
++ <!-- <property name="has-entry">True</property> -->
++ <signal name="changed" handler="view_mode_combo_box_changed_cb" swapped="no"/>
++ </object>
++ <packing>
++ <property name="position">0</property>
++ <property name="pack-type">start</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkAdjustment" id="icon_view_icon_size">
++ <property name="upper">256</property>
++ <property name="lower">32</property>
++ <property name="value">32</property>
++ <property name="step_increment">16</property>
++ </object>
++ </child>
++ <child>
++ <object class="GtkScale" id="icon_view_scale">
++ <property name="visible">0</property>
++ <property name="orientation">horizontal</property>
++ <property name="adjustment">icon_view_icon_size</property>
++ <property name="can_focus">1</property>
++ <property name="halign">end</property>
++ <property name="valign">fill</property>
++ <property name="margin_right">10</property>
++ <property name="width-request">100</property>
++ <property name="draw_value">False</property>
++ <signal name="value-changed" handler="icon_view_scale_value_changed_cb" swapped="no"/>
++ </object>
++ <packing>
++ <property name="position">1</property>
++ <property name="pack-type">end</property>
++ </packing>
++ </child>
++ </object>
++ </child>
++ <child>
+ <object class="GtkPaned" id="browse_widgets_hpaned">
+ <property name="visible">1</property>
+ <child>
+@@ -187,110 +237,172 @@
+ <property name="visible">1</property>
+ <property name="orientation">vertical</property>
+ <child>
+- <object class="GtkScrolledWindow" id="browse_files_swin">
++ <object class="GtkNotebook" id="view_notebook">
+ <property name="visible">1</property>
+- <property name="hscrollbar-policy">never</property>
++ <property name="show-tabs">False</property>
++ <signal name="switch-page" handler="view_notebook_switch_page_cb" swapped="no"/>
+ <child>
+- <object class="GtkTreeView" id="browse_files_tree_view">
++ <object class="GtkScrolledWindow" id="browse_files_list_swin">
+ <property name="visible">1</property>
+- <property name="has-tooltip">1</property>
+- <property name="enable-search">0</property>
+- <child internal-child="accessible">
+- <object class="AtkObject" id="browse_files_tree_view-atkobject">
+- <property name="AtkObject::accessible-name" translatable="yes">Files</property>
+- </object>
+- </child>
+- <signal name="button-press-event" handler="list_button_press_event_cb" swapped="no"/>
+- <signal name="drag-data-received" handler="file_list_drag_data_received_cb" swapped="no"/>
+- <signal name="drag-drop" handler="file_list_drag_drop_cb" swapped="no"/>
+- <signal name="drag-begin" handler="file_list_drag_begin_cb" swapped="no"/>
+- <signal name="drag-motion" handler="file_list_drag_motion_cb" swapped="no"/>
+- <signal name="drag-end" handler="file_list_drag_end_cb" swapped="no"/>
+- <signal name="key-press-event" handler="browse_files_key_press_event_cb" swapped="no"/>
+- <signal name="popup-menu" handler="list_popup_menu_cb" swapped="no"/>
+- <signal name="query-tooltip" handler="file_list_query_tooltip_cb" swapped="no"/>
+- <signal name="row-activated" handler="list_row_activated" swapped="no"/>
+- <signal name="cursor-changed" handler="list_cursor_changed" swapped="no"/>
+- <child internal-child="selection">
+- <object class="GtkTreeSelection" id="treeview-selection2">
+- <signal name="changed" handler="list_selection_changed" swapped="no"/>
+- </object>
+- </child>
++ <property name="hscrollbar_policy">never</property>
+ <child>
+- <object class="GtkTreeViewColumn" id="list_name_column">
+- <property name="title" translatable="yes">Name</property>
+- <property name="resizable">1</property>
+- <property name="expand">1</property>
++ <object class="GtkTreeView" id="browse_files_tree_view">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="has_tooltip">True</property>
++ <property name="enable_search">False</property>
++ <signal name="button-press-event" handler="list_button_press_event_cb" swapped="no"/>
++ <signal name="cursor-changed" handler="list_cursor_changed" swapped="no"/>
++ <signal name="drag-data-received" handler="file_list_drag_data_received_cb" swapped="no"/>
++ <signal name="drag-drop" handler="file_list_drag_drop_cb" swapped="no"/>
++ <signal name="drag-motion" handler="file_list_drag_motion_cb" swapped="no"/>
++ <signal name="key-press-event" handler="browse_files_key_press_event_cb" swapped="no"/>
++ <signal name="popup-menu" handler="list_popup_menu_cb" swapped="no"/>
++ <signal name="query-tooltip" handler="file_list_query_tooltip_cb" swapped="no"/>
++ <signal name="row-activated" handler="list_row_activated" swapped="no"/>
++ <child internal-child="selection">
++ <object class="GtkTreeSelection" id="treeview-selection2">
++ <signal name="changed" handler="list_selection_changed" swapped="no"/>
++ </object>
++ </child>
+ <child>
+- <object class="GtkCellRendererPixbuf" id="list_pixbuf_renderer">
+- <property name="xpad">6</property>
++ <object class="GtkTreeViewColumn" id="list_name_column">
++ <property name="resizable">True</property>
++ <property name="title" translatable="yes">Name</property>
++ <property name="expand">True</property>
++ <child>
++ <object class="GtkCellRendererPixbuf" id="list_pixbuf_renderer">
++ <property name="xpad">6</property>
++ </object>
++ </child>
++ <child>
++ <object class="GtkCellRendererText" id="list_name_renderer">
++ <property name="width-chars">10</property>
++ <property name="ellipsize">end</property>
++ </object>
++ </child>
+ </object>
+ </child>
+ <child>
+- <object class="GtkCellRendererText" id="list_name_renderer">
+- <property name="width-chars">10</property>
+- <property name="ellipsize">end</property>
++ <object class="GtkTreeViewColumn" id="list_location_column">
++ <property name="title" translatable="yes">Location</property>
++ <property name="resizable">1</property>
++ <property name="visible">0</property>
++ <property name="expand">1</property>
++ <child>
++ <object class="GtkCellRendererText" id="list_location_renderer">
++ <property name="xalign">0</property>
++ <property name="width-chars">10</property>
++ <property name="ellipsize">start</property>
++ <property name="xpad">6</property>
++ </object>
++ </child>
+ </object>
+ </child>
+- </object>
+- </child>
+- <child>
+- <object class="GtkTreeViewColumn" id="list_location_column">
+- <property name="title" translatable="yes">Location</property>
+- <property name="resizable">1</property>
+- <property name="visible">0</property>
+- <property name="expand">1</property>
+ <child>
+- <object class="GtkCellRendererText" id="list_location_renderer">
+- <property name="xalign">0</property>
+- <property name="width-chars">10</property>
+- <property name="ellipsize">start</property>
+- <property name="xpad">6</property>
++ <object class="GtkTreeViewColumn" id="list_size_column">
++ <property name="title" translatable="yes">Size</property>
++ <property name="sizing">fixed</property>
++ <child>
++ <object class="GtkCellRendererText" id="list_size_renderer">
++ <property name="xalign">0</property>
++ <property name="xpad">6</property>
++ </object>
++ </child>
+ </object>
+ </child>
+- </object>
+- </child>
+- <child>
+- <object class="GtkTreeViewColumn" id="list_size_column">
+- <property name="title" translatable="yes">Size</property>
+- <property name="sizing">fixed</property>
+ <child>
+- <object class="GtkCellRendererText" id="list_size_renderer">
+- <property name="xalign">0</property>
+- <property name="xpad">6</property>
++ <object class="GtkTreeViewColumn" id="list_type_column">
++ <property name="title" translatable="yes">Type</property>
++ <property name="resizable">1</property>
++ <child>
++ <object class="GtkCellRendererText" id="list_type_renderer">
++ <property name="xalign">0</property>
++ <property name="xpad">6</property>
++ </object>
++ </child>
+ </object>
+ </child>
+- </object>
+- </child>
+- <child>
+- <object class="GtkTreeViewColumn" id="list_type_column">
+- <property name="title" translatable="yes">Type</property>
+- <property name="resizable">1</property>
+ <child>
+- <object class="GtkCellRendererText" id="list_type_renderer">
+- <property name="xalign">0</property>
+- <property name="xpad">6</property>
++ <object class="GtkTreeViewColumn" id="list_time_column">
++ <property name="title" translatable="yes">Modified</property>
++ <property name="sizing">fixed</property>
++ <child>
++ <object class="GtkCellRendererText" id="list_date_renderer">
++ <property name="xpad">6</property>
++ </object>
++ </child>
++ <child>
++ <object class="GtkCellRendererText" id="list_time_renderer">
++ <property name="xpad">6</property>
++ </object>
++ </child>
+ </object>
+ </child>
+ </object>
+ </child>
++ </object>
++ </child>
++ <child type="tab">
++ <object class="GtkLabel" id="label_list_view">
++ <property name="visible">True</property>
++ <property name="can_focus">False</property>
++ <property name="label" translatable="yes">List View</property>
++ </object>
++ <packing>
++ <property name="tab_fill">False</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkScrolledWindow" id="browse_files_icon_swin">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="shadow_type">in</property>
++ <property name="hscrollbar-policy">GTK_POLICY_AUTOMATIC</property>
+ <child>
+- <object class="GtkTreeViewColumn" id="list_time_column">
+- <property name="title" translatable="yes">Modified</property>
+- <property name="sizing">fixed</property>
++ <object class="GtkIconView" id="browse_files_icon_view">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="has_tooltip">True</property>
++ <property name="column-spacing">2</property>
++ <signal name="button-press-event" handler="list_button_press_event_cb" swapped="no"/>
++ <signal name="drag-data-received" handler="file_list_drag_data_received_cb" swapped="no"/>
++ <signal name="drag-drop" handler="file_list_drag_drop_cb" swapped="no"/>
++ <signal name="item-activated" handler="icon_item_activated" swapped="no"/>
++ <signal name="key-press-event" handler="browse_files_key_press_event_cb" swapped="no"/>
++ <signal name="popup-menu" handler="list_popup_menu_cb" swapped="no"/>
++ <signal name="query-tooltip" handler="file_list_query_tooltip_cb" swapped="no"/>
++ <signal name="selection-changed" handler="list_selection_changed" swapped="no"/>
+ <child>
+- <object class="GtkCellRendererText" id="list_date_renderer">
+- <property name="xpad">6</property>
++ <object class="GtkCellRendererText" id="list_icon_renderer">
+ </object>
+ </child>
+ <child>
+- <object class="GtkCellRendererText" id="list_time_renderer">
+- <property name="xpad">6</property>
+- </object>
++ <object class="GtkCellRendererPixbuf" id="icon_view_pixbuf_renderer"/>
+ </child>
+ </object>
+ </child>
+ </object>
++ <packing>
++ <property name="position">1</property>
++ </packing>
++ </child>
++ <child type="tab">
++ <object class="GtkLabel" id="label_icon_view">
++ <property name="visible">True</property>
++ <property name="can_focus">False</property>
++ <property name="label" translatable="yes">Icon View</property>
++ </object>
++ <packing>
++ <property name="position">1</property>
++ <property name="tab_fill">False</property>
++ </packing>
++ </child>
++ <child>
++ <placeholder/>
++ </child>
++ <child type="tab">
++ <placeholder/>
+ </child>
+ </object>
+ <packing>
+@@ -409,7 +521,7 @@
+ </object>
+ <packing>
+ <property name="expand">1</property>
+- <property name="position">1</property>
++ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
diff --git a/gtk3-filechooser-icon-view.patch.diff b/gtk3-filechooser-icon-view.patch.diff
new file mode 100644
index 0000000..8f6bbfb
--- /dev/null
+++ b/gtk3-filechooser-icon-view.patch.diff
@@ -0,0 +1,1055 @@
+Last-modified: 2023-03-24
+Author: bgstack15
+Message: Adapt https://gist.github.com/Dudemanguy/c172394e30e1e7d0f477ad15c719bc71/raw/8f2e9fb36d736b600030a2db24a26304654f5e17/gtk3-filechooser-icon-view.patch to gtk3classic, attempt 1. This diff is the difference between the file stored in this git repo from the dudemanguy gist repo.
+--- ../gtk3classic/gtk3-filechooser-icon-view.patch 2023-03-24 09:13:38.020372785 -0400
++++ debian/patches/gtk3-filechooser-icon-view.patch 2023-03-24 09:23:58.530067566 -0400
+@@ -1,5 +1,3 @@
+-diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h
+-index a0a622c111..2af859433d 100644
+ --- a/gtk/gtkfilechooserprivate.h
+ +++ b/gtk/gtkfilechooserprivate.h
+ @@ -32,10 +32,14 @@
+@@ -93,11 +91,9 @@
+ GSList * _gtk_file_chooser_list_shortcut_folder_files (GtkFileChooser *chooser);
+
+
+-diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c
+-index d75a3f7857..623c71e84a 100644
+ --- a/gtk/gtkfilechooserwidget.c
+ +++ b/gtk/gtkfilechooserwidget.c
+-@@ -44,10 +44,12 @@
++@@ -45,10 +45,12 @@
+ #include "gtkfilesystemmodel.h"
+ #include "gtkgrid.h"
+ #include "gtkicontheme.h"
+@@ -110,27 +106,27 @@
+ #include "gtkpaned.h"
+ #include "gtkpathbar.h"
+ #include "gtkplacessidebar.h"
+-@@ -81,6 +83,7 @@
+- #include "gtkgesturelongpress.h"
++@@ -84,6 +86,7 @@
++ #include "gtkcssprovider.h"
+
+ #include <cairo-gobject.h>
+ +#include <math.h>
+
+ #ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+-@@ -198,6 +201,11 @@ typedef enum {
+- STARTUP_MODE_CWD
++@@ -202,6 +205,11 @@ typedef enum {
+ } StartupMode;
+
+-+typedef enum {
++ typedef enum {
+ + VIEW_MODE_LIST,
+ + VIEW_MODE_ICON,
+ +} ViewMode;
+ +
+- typedef enum {
+++typedef enum {
+ CLOCK_FORMAT_24,
+ CLOCK_FORMAT_12
+-@@ -228,8 +236,12 @@ struct _GtkFileChooserWidgetPrivate {
++ } ClockFormat;
++@@ -231,8 +239,12 @@ struct _GtkFileChooserWidgetPrivate {
+ GtkWidget *browse_header_revealer;
+ GtkWidget *browse_header_stack;
+ GtkWidget *browse_files_stack;
+@@ -144,7 +140,7 @@
+ GtkWidget *remote_warning_bar;
+
+ GtkWidget *browse_files_popover;
+-@@ -245,6 +257,12 @@ struct _GtkFileChooserWidgetPrivate {
++@@ -248,6 +260,12 @@ struct _GtkFileChooserWidgetPrivate {
+ GtkWidget *delete_file_item;
+ GtkWidget *sort_directories_item;
+ GtkWidget *show_time_item;
+@@ -157,7 +153,7 @@
+
+ GtkWidget *browse_new_folder_button;
+ GtkSizeGroup *browse_path_bar_size_group;
+-@@ -261,6 +279,7 @@ struct _GtkFileChooserWidgetPrivate {
++@@ -264,6 +282,7 @@ struct _GtkFileChooserWidgetPrivate {
+
+ GtkGesture *long_press_gesture;
+
+@@ -165,7 +161,7 @@
+ GtkFileSystemModel *browse_files_model;
+ char *browse_files_last_selected_name;
+
+-@@ -348,10 +367,17 @@ struct _GtkFileChooserWidgetPrivate {
++@@ -351,10 +370,17 @@ struct _GtkFileChooserWidgetPrivate {
+ guint location_changed_id;
+
+ gulong settings_signal_id;
+@@ -184,7 +180,7 @@
+ gulong toplevel_set_focus_id;
+ GtkWidget *toplevel_last_focus_widget;
+
+-@@ -419,7 +445,8 @@ enum {
++@@ -422,7 +448,8 @@ enum {
+ MODEL_COL_NAME_COLLATED,
+ MODEL_COL_IS_FOLDER,
+ MODEL_COL_IS_SENSITIVE,
+@@ -194,7 +190,7 @@
+ MODEL_COL_SIZE_TEXT,
+ MODEL_COL_DATE_TEXT,
+ MODEL_COL_TIME_TEXT,
+-@@ -439,7 +466,8 @@ enum {
++@@ -442,7 +469,8 @@ enum {
+ G_TYPE_STRING, /* MODEL_COL_NAME_COLLATED */ \
+ G_TYPE_BOOLEAN, /* MODEL_COL_IS_FOLDER */ \
+ G_TYPE_BOOLEAN, /* MODEL_COL_IS_SENSITIVE */ \
+@@ -204,7 +200,7 @@
+ G_TYPE_STRING, /* MODEL_COL_SIZE_TEXT */ \
+ G_TYPE_STRING, /* MODEL_COL_DATE_TEXT */ \
+ G_TYPE_STRING, /* MODEL_COL_TIME_TEXT */ \
+-@@ -449,7 +477,10 @@ enum {
++@@ -452,7 +480,10 @@ enum {
+ #define DEFAULT_RECENT_FILES_LIMIT 50
+
+ /* Icon size for if we can't get it from the theme */
+@@ -216,7 +212,7 @@
+
+ #define PREVIEW_HBOX_SPACING 12
+ #define NUM_LINES 45
+-@@ -570,7 +601,7 @@ static gboolean list_select_func (GtkTreeSelection *selection,
++@@ -573,7 +604,7 @@ static gboolean list_select_func (GtkT
+ gboolean path_currently_selected,
+ gpointer data);
+
+@@ -225,7 +221,7 @@
+ GtkFileChooserWidget *impl);
+ static void list_row_activated (GtkTreeView *tree_view,
+ GtkTreePath *path,
+-@@ -578,6 +609,13 @@ static void list_row_activated (GtkTreeView *tree_view,
++@@ -581,6 +612,13 @@ static void list_row_activated (
+ GtkFileChooserWidget *impl);
+ static void list_cursor_changed (GtkTreeView *treeview,
+ GtkFileChooserWidget *impl);
+@@ -239,7 +235,7 @@
+
+ static void path_bar_clicked (GtkPathBar *path_bar,
+ GFile *file,
+-@@ -590,6 +628,13 @@ static void update_cell_renderer_attributes (GtkFileChooserWidget *impl);
++@@ -593,6 +631,13 @@ static void update_cell_renderer_attribu
+ static void load_remove_timer (GtkFileChooserWidget *impl, LoadState new_load_state);
+ static void browse_files_center_selected_row (GtkFileChooserWidget *impl);
+
+@@ -253,7 +249,7 @@
+ static void location_switch_to_path_bar (GtkFileChooserWidget *impl);
+
+ static void stop_loading_and_clear_list_model (GtkFileChooserWidget *impl,
+-@@ -619,6 +664,26 @@ static gboolean recent_should_respond (GtkFileChooserWidget *impl);
++@@ -622,6 +667,26 @@ static gboolean recent_should_respond
+ static void set_file_system_backend (GtkFileChooserWidget *impl);
+ static void unset_file_system_backend (GtkFileChooserWidget *impl);
+
+@@ -280,7 +276,7 @@
+ static void clear_model_cache (GtkFileChooserWidget *impl,
+ gint column);
+ static void set_model_filter (GtkFileChooserWidget *impl,
+-@@ -956,7 +1021,7 @@ update_preview_widget_visibility (GtkFileChooserWidget *impl)
++@@ -959,7 +1024,7 @@ update_preview_widget_visibility (GtkFil
+ }
+ }
+
+@@ -289,7 +285,7 @@
+ gtk_widget_show (priv->preview_box);
+ else
+ gtk_widget_hide (priv->preview_box);
+-@@ -1224,19 +1289,16 @@ selection_check (GtkFileChooserWidget *impl,
++@@ -1227,19 +1292,16 @@ selection_check (GtkFileChooserWidget *i
+ gboolean *all_files,
+ gboolean *all_folders)
+ {
+@@ -312,7 +308,7 @@
+
+ g_assert (closure.num_selected == 0 || !(closure.all_files && closure.all_folders));
+
+-@@ -1361,7 +1423,7 @@ browse_files_key_press_event_cb (GtkWidget *widget,
++@@ -1367,7 +1429,7 @@ browse_files_key_press_event_cb (GtkWidg
+ return TRUE;
+ }
+
+@@ -321,7 +317,7 @@
+ {
+ if (gtk_widget_child_focus (priv->places_sidebar, GTK_DIR_LEFT))
+ return TRUE;
+-@@ -1464,12 +1526,8 @@ add_to_shortcuts_cb (GSimpleAction *action,
++@@ -1470,12 +1532,8 @@ add_to_shortcuts_cb (GSimpleAction *acti
+ gpointer data)
+ {
+ GtkFileChooserWidget *impl = data;
+@@ -335,7 +331,7 @@
+ add_bookmark_foreach_cb,
+ impl);
+ }
+-@@ -1842,6 +1900,86 @@ open_folder_cb (GSimpleAction *action,
++@@ -1848,6 +1906,86 @@ open_folder_cb (GSimpleAction *action,
+ }
+ G_GNUC_END_IGNORE_DEPRECATIONS
+
+@@ -422,7 +418,7 @@
+ /* callback used when the "Show Hidden Files" menu item is toggled */
+ static void
+ change_show_hidden_state (GSimpleAction *action,
+-@@ -2169,6 +2307,7 @@ check_file_list_popover_sensitivity (GtkFileChooserWidget *impl)
++@@ -2175,6 +2313,7 @@ check_file_list_popover_sensitivity (Gtk
+ gboolean all_files;
+ gboolean all_folders;
+ gboolean active;
+@@ -430,7 +426,7 @@
+ GActionGroup *actions;
+ GAction *action, *action2;
+
+-@@ -2177,6 +2316,7 @@ check_file_list_popover_sensitivity (GtkFileChooserWidget *impl)
++@@ -2183,6 +2322,7 @@ check_file_list_popover_sensitivity (Gtk
+ selection_check (impl, &num_selected, &all_files, &all_folders);
+
+ active = (num_selected != 0);
+@@ -438,7 +434,7 @@
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "copy-location");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), active);
+-@@ -2190,6 +2330,21 @@ check_file_list_popover_sensitivity (GtkFileChooserWidget *impl)
++@@ -2196,6 +2336,21 @@ check_file_list_popover_sensitivity (Gtk
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "open");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), (num_selected == 1) && all_folders);
+
+@@ -460,7 +456,7 @@
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "rename");
+ if (num_selected == 1)
+ {
+-@@ -2255,6 +2410,11 @@ static GActionEntry entries[] = {
++@@ -2261,6 +2416,11 @@ static GActionEntry entries[] = {
+ { "rename", rename_file_cb, NULL, NULL, NULL },
+ { "delete", delete_file_cb, NULL, NULL, NULL },
+ { "trash", trash_file_cb, NULL, NULL, NULL },
+@@ -472,10 +468,10 @@
+ { "toggle-show-hidden", NULL, NULL, "false", change_show_hidden_state },
+ { "toggle-show-size", NULL, NULL, "false", change_show_size_state },
+ { "toggle-show-type", NULL, NULL, "false", change_show_type_state },
+-@@ -2280,15 +2440,9 @@ append_separator (GtkWidget *box)
+- {
+- GtkWidget *separator;
+-
++@@ -2290,17 +2450,6 @@ append_separator (GtkWidget *box)
++ gtk_widget_set_visible (GTK_WIDGET (separator), TRUE);
++ gtk_menu_shell_append (GTK_MENU_SHELL (box), separator);
++ return separator;
+ - separator = g_object_new (GTK_TYPE_SEPARATOR,
+ - "orientation", GTK_ORIENTATION_HORIZONTAL,
+ - "visible", TRUE,
+@@ -485,33 +481,27 @@
+ - "margin-bottom", 6,
+ - NULL);
+ - gtk_container_add (GTK_CONTAINER (box), separator);
+-+ separator = gtk_separator_menu_item_new ();
+-+ gtk_widget_set_visible (GTK_WIDGET (separator), TRUE);
+-+ gtk_menu_shell_append (GTK_MENU_SHELL (box), separator);
+-
+- return separator;
++-
++- return separator;
+ }
+-@@ -2301,12 +2455,13 @@ add_button (GtkWidget *box,
+- {
+- GtkWidget *item;
+
++ /* Constructs the popup menu for the file list if needed */
++@@ -2319,14 +2468,6 @@ add_button (GtkWidget *box,
++ gtk_widget_set_visible (GTK_WIDGET (item), TRUE);
++ gtk_menu_shell_append (GTK_MENU_SHELL (box), item);
++ return item;
+ - item = g_object_new (GTK_TYPE_MODEL_BUTTON,
+ - "visible", TRUE,
+ - "action-name", action,
+ - "text", label,
+ - NULL);
+ - gtk_container_add (GTK_CONTAINER (box), item);
+-+ if (g_str_match_string ("toggle", action, TRUE))
+-+ item = gtk_check_menu_item_new_with_mnemonic (label);
+-+ else
+-+ item = gtk_menu_item_new_with_mnemonic (label);
+-+ g_object_set (G_OBJECT (item), "action-name", action, NULL);
+-+ gtk_widget_set_visible (GTK_WIDGET (item), TRUE);
+-+ gtk_menu_shell_append (GTK_MENU_SHELL (box), item);
+-
+- return item;
++-
++- return item;
+ }
+-@@ -2320,11 +2475,9 @@ file_list_build_popover (GtkFileChooserWidget *impl)
++
++ static void
++@@ -2338,11 +2479,6 @@ file_list_build_popover (GtkFileChooserW
+ if (priv->browse_files_popover)
+ return;
+
+@@ -520,13 +510,10 @@
+ - g_object_set (box, "margin", 10, NULL);
+ - gtk_widget_show (box);
+ - gtk_container_add (GTK_CONTAINER (priv->browse_files_popover), box);
+-+ priv->browse_files_popover = gtk_menu_new ();
+-+ gtk_menu_attach_to_widget (GTK_MENU (priv->browse_files_popover), GTK_WIDGET (priv->browse_files_tree_view), NULL);
+-+ box = priv->browse_files_popover;
+-
+- priv->visit_file_item = add_button (box, _("_Visit File"), "item.visit");
+- priv->open_folder_item = add_button (box, _("_Open With File Manager"), "item.open");
+-@@ -2336,11 +2489,29 @@ file_list_build_popover (GtkFileChooserWidget *impl)
++ priv->browse_files_popover = gtk_menu_new ();
++ gtk_menu_attach_to_widget (GTK_MENU (priv->browse_files_popover), GTK_WIDGET (priv->browse_files_tree_view), NULL);
++ box = priv->browse_files_popover;
++@@ -2357,11 +2493,29 @@ file_list_build_popover (GtkFileChooserW
+
+ append_separator (box);
+
+@@ -558,10 +545,10 @@
+ + priv->hidden_files_item = add_button (box, _("Show _Hidden Files"), "item.toggle-show-hidden");
+ + priv->sort_directories_item = add_button (box, _("Sort _Folders before Files"), "item.toggle-sort-dirs-first");
+ + }
+- }
+-
+- /* Updates the popover for the file list, creating it if necessary */
+-@@ -2392,39 +2563,11 @@ file_list_show_popover (GtkFileChooserWidget *impl,
++ g_object_set (priv->visit_file_item, "image", gtk_image_new_from_icon_name ("gtk-jump-to", GTK_ICON_SIZE_MENU), NULL);
++ g_object_set (priv->open_folder_item, "image", gtk_image_new_from_icon_name ("gtk-open", GTK_ICON_SIZE_MENU), NULL);
++ g_object_set (priv->copy_file_location_item, "image", gtk_image_new_from_icon_name ("gtk-copy", GTK_ICON_SIZE_MENU), NULL);
++@@ -2419,41 +2573,10 @@ file_list_show_popover (GtkFileChooserWi
+ gdouble y)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+@@ -573,7 +560,9 @@
+ -
+
+ file_list_update_popover (impl);
+-
++ gtk_menu_popup_at_pointer (GTK_MENU (priv->browse_files_popover), NULL);
++ return;
++-
+ - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+ - list = gtk_tree_selection_get_selected_rows (selection, &model);
+ - if (list)
+@@ -598,12 +587,10 @@
+ -
+ - gtk_popover_set_pointing_to (GTK_POPOVER (priv->browse_files_popover), &rect);
+ - gtk_popover_popup (GTK_POPOVER (priv->browse_files_popover));
+-+ gtk_menu_popup_at_pointer (GTK_MENU (priv->browse_files_popover), NULL);
+-+ return;
+ }
+
+ /* Callback used for the GtkWidget::popup-menu signal of the file list */
+-@@ -2461,7 +2604,7 @@ list_button_press_event_cb (GtkWidget *widget,
++@@ -2490,7 +2613,7 @@ list_button_press_event_cb (GtkWidget
+ return FALSE;
+
+ in_press = TRUE;
+@@ -612,14 +599,14 @@
+ in_press = FALSE;
+
+ file_list_show_popover (impl, event->x, event->y);
+-@@ -2492,13 +2635,16 @@ file_list_set_sort_column_ids (GtkFileChooserWidget *impl)
++@@ -2521,13 +2644,16 @@ file_list_set_sort_column_ids (GtkFileCh
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+
+-- gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), -1);
++- gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), 0);
+ + if (priv->view_mode == VIEW_MODE_LIST)
+ + {
+-+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), -1);
+++ gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), 0);
+
+ - gtk_tree_view_column_set_sort_column_id (priv->list_name_column, MODEL_COL_NAME);
+ - gtk_tree_view_column_set_sort_column_id (priv->list_time_column, MODEL_COL_TIME);
+@@ -635,7 +622,7 @@
+ }
+
+ static gboolean
+-@@ -2521,11 +2667,22 @@ file_list_query_tooltip_cb (GtkWidget *widget,
++@@ -2550,11 +2676,22 @@ file_list_query_tooltip_cb (GtkWidget *
+ return FALSE;
+
+
+@@ -663,7 +650,7 @@
+
+ gtk_tree_model_get (model, &iter,
+ MODEL_COL_FILE, &file,
+-@@ -2539,10 +2696,18 @@ file_list_query_tooltip_cb (GtkWidget *widget,
++@@ -2568,10 +2705,18 @@ file_list_query_tooltip_cb (GtkWidget *
+
+ filename = g_file_get_path (file);
+ gtk_tooltip_set_text (tooltip, filename);
+@@ -686,7 +673,7 @@
+ g_free (filename);
+ g_object_unref (file);
+ gtk_tree_path_free (path);
+-@@ -2558,8 +2723,8 @@ set_icon_cell_renderer_fixed_size (GtkFileChooserWidget *impl)
++@@ -2587,8 +2732,8 @@ set_icon_cell_renderer_fixed_size (GtkFi
+
+ gtk_cell_renderer_get_padding (priv->list_pixbuf_renderer, &xpad, &ypad);
+ gtk_cell_renderer_set_fixed_size (priv->list_pixbuf_renderer,
+@@ -697,7 +684,7 @@
+ }
+
+ static gboolean
+-@@ -2843,7 +3008,7 @@ location_mode_set (GtkFileChooserWidget *impl,
++@@ -2872,7 +3017,7 @@ location_mode_set (GtkFileChooserWidget
+ location_switch_to_path_bar (impl);
+
+ if (switch_to_file_list)
+@@ -706,7 +693,7 @@
+
+ break;
+
+-@@ -2914,6 +3079,119 @@ location_toggle_popup_handler (GtkFileChooserWidget *impl)
++@@ -2943,6 +3088,119 @@ location_toggle_popup_handler (GtkFileCh
+ }
+ }
+
+@@ -826,7 +813,7 @@
+ static void
+ gtk_file_chooser_widget_constructed (GObject *object)
+ {
+-@@ -3022,18 +3300,11 @@ set_select_multiple (GtkFileChooserWidget *impl,
++@@ -3051,18 +3309,11 @@ set_select_multiple (GtkFileChooserWidge
+ gboolean property_notify)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+@@ -846,7 +833,7 @@
+
+ priv->select_multiple = select_multiple;
+ g_object_notify (G_OBJECT (impl), "select-multiple");
+-@@ -3160,6 +3431,7 @@ operation_mode_set_enter_location (GtkFileChooserWidget *impl)
++@@ -3189,6 +3440,7 @@ operation_mode_set_enter_location (GtkFi
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_header_stack), "location");
+ gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), TRUE);
+ location_bar_update (impl);
+@@ -854,7 +841,7 @@
+ gtk_widget_set_sensitive (priv->filter_combo, TRUE);
+ location_mode_set (impl, LOCATION_MODE_FILENAME_ENTRY);
+ }
+-@@ -3189,7 +3461,7 @@ operation_mode_set_search (GtkFileChooserWidget *impl)
++@@ -3218,7 +3470,7 @@ operation_mode_set_search (GtkFileChoose
+ visible_widget = gtk_stack_get_visible_child (GTK_STACK (priv->browse_files_stack));
+
+ if (visible_widget != priv->places_view &&
+@@ -863,7 +850,7 @@
+ {
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_files_stack), "list");
+ }
+-@@ -3314,6 +3586,12 @@ update_appearance (GtkFileChooserWidget *impl)
++@@ -3343,6 +3595,12 @@ update_appearance (GtkFileChooserWidget
+ location_mode_set (impl, priv->location_mode);
+ }
+
+@@ -876,7 +863,7 @@
+ if (priv->location_entry)
+ _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->action);
+
+-@@ -3322,7 +3600,7 @@ update_appearance (GtkFileChooserWidget *impl)
++@@ -3351,7 +3609,7 @@ update_appearance (GtkFileChooserWidget
+ /* This *is* needed; we need to redraw the file list because the "sensitivity"
+ * of files may change depending whether we are in a file or folder-only mode.
+ */
+@@ -885,7 +872,7 @@
+
+ emit_default_size_changed (impl);
+ }
+-@@ -3752,14 +4030,27 @@ change_icon_theme (GtkFileChooserWidget *impl)
++@@ -3781,14 +4039,27 @@ change_icon_theme (GtkFileChooserWidget
+ profile_start ("start", NULL);
+
+ if (gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height))
+@@ -918,7 +905,7 @@
+ gtk_widget_queue_resize (priv->browse_files_tree_view);
+
+ profile_end ("end", NULL);
+-@@ -3860,7 +4151,7 @@ set_sort_column (GtkFileChooserWidget *impl)
++@@ -3889,7 +4160,7 @@ set_sort_column (GtkFileChooserWidget *i
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+ GtkTreeSortable *sortable;
+
+@@ -927,7 +914,7 @@
+
+ /* can happen when we're still populating the model */
+ if (sortable == NULL)
+-@@ -3875,6 +4166,7 @@ static void
++@@ -3904,6 +4175,7 @@ static void
+ settings_load (GtkFileChooserWidget *impl)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+@@ -935,7 +922,7 @@
+ gboolean show_hidden;
+ gboolean show_size_column;
+ gboolean show_type_column;
+-@@ -3882,6 +4174,7 @@ settings_load (GtkFileChooserWidget *impl)
++@@ -3911,6 +4183,7 @@ settings_load (GtkFileChooserWidget *imp
+ DateFormat date_format;
+ TypeFormat type_format;
+ gint sort_column;
+@@ -943,7 +930,7 @@
+ GtkSortType sort_order;
+ StartupMode startup_mode;
+ gint sidebar_width;
+-@@ -3889,6 +4182,8 @@ settings_load (GtkFileChooserWidget *impl)
++@@ -3918,6 +4191,8 @@ settings_load (GtkFileChooserWidget *imp
+
+ settings = _gtk_file_chooser_get_settings_for_widget (GTK_WIDGET (impl));
+
+@@ -952,7 +939,7 @@
+ show_hidden = g_settings_get_boolean (settings, SETTINGS_KEY_SHOW_HIDDEN);
+ show_size_column = g_settings_get_boolean (settings, SETTINGS_KEY_SHOW_SIZE_COLUMN);
+ show_type_column = g_settings_get_boolean (settings, SETTINGS_KEY_SHOW_TYPE_COLUMN);
+-@@ -3900,12 +4195,20 @@ settings_load (GtkFileChooserWidget *impl)
++@@ -3929,12 +4204,20 @@ settings_load (GtkFileChooserWidget *imp
+ date_format = g_settings_get_enum (settings, SETTINGS_KEY_DATE_FORMAT);
+ type_format = g_settings_get_enum (settings, SETTINGS_KEY_TYPE_FORMAT);
+
+@@ -976,7 +963,7 @@
+
+ priv->sort_column = sort_column;
+ priv->sort_order = sort_order;
+-@@ -3934,6 +4237,8 @@ settings_save (GtkFileChooserWidget *impl)
++@@ -3963,6 +4246,8 @@ settings_save (GtkFileChooserWidget *imp
+ /* All the other state */
+
+ g_settings_set_enum (settings, SETTINGS_KEY_LOCATION_MODE, priv->location_mode);
+@@ -985,7 +972,7 @@
+ g_settings_set_boolean (settings, SETTINGS_KEY_SHOW_HIDDEN,
+ gtk_file_chooser_get_show_hidden (GTK_FILE_CHOOSER (impl)));
+ g_settings_set_boolean (settings, SETTINGS_KEY_SHOW_SIZE_COLUMN, priv->show_size_column);
+-@@ -4445,10 +4750,14 @@ load_set_model (GtkFileChooserWidget *impl)
++@@ -4474,10 +4759,14 @@ load_set_model (GtkFileChooserWidget *im
+ g_assert (priv->browse_files_model != NULL);
+
+ profile_msg (" gtk_tree_view_set_model start", NULL);
+@@ -1004,7 +991,7 @@
+ set_sort_column (impl);
+ profile_msg (" gtk_tree_view_set_model end", NULL);
+ priv->list_sort_ascending = TRUE;
+-@@ -4528,7 +4837,7 @@ browse_files_select_first_row (GtkFileChooserWidget *impl)
++@@ -4557,7 +4846,7 @@ browse_files_select_first_row (GtkFileCh
+ GtkTreeIter dummy_iter;
+ GtkTreeModel *tree_model;
+
+@@ -1013,7 +1000,7 @@
+
+ if (!tree_model)
+ return;
+-@@ -4547,8 +4856,7 @@ browse_files_select_first_row (GtkFileChooserWidget *impl)
++@@ -4576,8 +4865,7 @@ browse_files_select_first_row (GtkFileCh
+ */
+ priv->auto_selecting_first_row = TRUE;
+
+@@ -1023,7 +1010,7 @@
+ priv->auto_selecting_first_row = FALSE;
+ }
+ gtk_tree_path_free (path);
+-@@ -4574,7 +4882,13 @@ center_selected_row_foreach_cb (GtkTreeModel *model,
++@@ -4603,7 +4891,13 @@ center_selected_row_foreach_cb (GtkTreeM
+ if (closure->already_centered)
+ return;
+
+@@ -1038,7 +1025,7 @@
+ closure->already_centered = TRUE;
+ }
+
+-@@ -4582,15 +4896,11 @@ center_selected_row_foreach_cb (GtkTreeModel *model,
++@@ -4611,15 +4905,11 @@ center_selected_row_foreach_cb (GtkTreeM
+ static void
+ browse_files_center_selected_row (GtkFileChooserWidget *impl)
+ {
+@@ -1055,7 +1042,7 @@
+ }
+
+ static gboolean
+-@@ -4598,7 +4908,6 @@ show_and_select_files (GtkFileChooserWidget *impl,
++@@ -4627,7 +4917,6 @@ show_and_select_files (GtkFileChooserWid
+ GSList *files)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+@@ -1063,7 +1050,7 @@
+ GtkFileSystemModel *fsmodel;
+ gboolean enabled_hidden, removed_filters;
+ gboolean selected_a_file;
+-@@ -4607,8 +4916,7 @@ show_and_select_files (GtkFileChooserWidget *impl,
++@@ -4636,8 +4925,7 @@ show_and_select_files (GtkFileChooserWid
+ g_assert (priv->load_state == LOAD_FINISHED);
+ g_assert (priv->browse_files_model != NULL);
+
+@@ -1073,7 +1060,7 @@
+
+ g_assert (fsmodel == priv->browse_files_model);
+
+-@@ -4663,11 +4971,10 @@ show_and_select_files (GtkFileChooserWidget *impl,
++@@ -4692,11 +4980,10 @@ show_and_select_files (GtkFileChooserWid
+ {
+ GtkTreePath *path;
+
+@@ -1087,7 +1074,7 @@
+ gtk_tree_path_free (path);
+
+ selected_a_file = TRUE;
+-@@ -4818,12 +5125,15 @@ stop_loading_and_clear_list_model (GtkFileChooserWidget *impl,
++@@ -4847,12 +5134,15 @@ stop_loading_and_clear_list_model (GtkFi
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+
+@@ -1104,11 +1091,10 @@
+ }
+
+ /* Replace 'target' with 'replacement' in the input string. */
+-@@ -5093,6 +5403,18 @@ end:
+- return g_strdup ("");
++@@ -5123,6 +5413,18 @@ end:
+ }
+
+-+static gboolean
++ static gboolean
+ +get_visible_range (GtkTreePath **start, GtkTreePath **end,
+ + GtkFileChooserWidget *impl)
+ +{
+@@ -1120,10 +1106,11 @@
+ + g_assert_not_reached ();
+ +}
+ +
+- static gboolean
+++static gboolean
+ file_system_model_set (GtkFileSystemModel *model,
+ GFile *file,
+-@@ -5152,12 +5474,15 @@ file_system_model_set (GtkFileSystemModel *model,
++ GFileInfo *info,
++@@ -5181,12 +5483,15 @@ file_system_model_set (GtkFileSystemMode
+ else
+ g_value_set_boolean (value, TRUE);
+ break;
+@@ -1141,7 +1128,7 @@
+ }
+ else
+ {
+-@@ -5211,6 +5536,76 @@ file_system_model_set (GtkFileSystemModel *model,
++@@ -5240,6 +5545,76 @@ file_system_model_set (GtkFileSystemMode
+ else
+ g_value_set_boxed (value, NULL);
+ break;
+@@ -1218,7 +1205,7 @@
+ case MODEL_COL_SIZE:
+ g_value_set_int64 (value, info ? g_file_info_get_size (info) : 0);
+ break;
+-@@ -5403,7 +5798,6 @@ static void
++@@ -5432,7 +5807,6 @@ static void
+ update_chooser_entry (GtkFileChooserWidget *impl)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+@@ -1226,7 +1213,7 @@
+ struct update_chooser_entry_selected_foreach_closure closure;
+
+ /* no need to update the file chooser's entry if there's no entry */
+-@@ -5420,9 +5814,8 @@ update_chooser_entry (GtkFileChooserWidget *impl)
++@@ -5449,9 +5823,8 @@ update_chooser_entry (GtkFileChooserWidg
+
+ g_assert (priv->location_entry != NULL);
+
+@@ -1237,7 +1224,7 @@
+
+ if (closure.num_selected == 0)
+ {
+-@@ -5919,19 +6312,15 @@ gtk_file_chooser_widget_unselect_file (GtkFileChooser *chooser,
++@@ -5948,19 +6321,15 @@ gtk_file_chooser_widget_unselect_file (G
+ {
+ GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+@@ -1260,7 +1247,7 @@
+ }
+
+ static gboolean
+-@@ -5942,12 +6331,9 @@ maybe_select (GtkTreeModel *model,
++@@ -5971,12 +6340,9 @@ maybe_select (GtkTreeModel *model,
+ {
+ GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (data);
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+@@ -1273,7 +1260,7 @@
+ gtk_tree_model_get (model, iter,
+ MODEL_COL_IS_FOLDER, &is_folder,
+ MODEL_COL_IS_SENSITIVE, &is_sensitive,
+-@@ -5956,9 +6342,9 @@ maybe_select (GtkTreeModel *model,
++@@ -5985,9 +6351,9 @@ maybe_select (GtkTreeModel *model,
+ if (is_sensitive &&
+ ((is_folder && priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ||
+ (!is_folder && priv->action == GTK_FILE_CHOOSER_ACTION_OPEN)))
+@@ -1285,7 +1272,7 @@
+
+ return FALSE;
+ }
+-@@ -5974,8 +6360,15 @@ gtk_file_chooser_widget_select_all (GtkFileChooser *chooser)
++@@ -6003,8 +6369,15 @@ gtk_file_chooser_widget_select_all (GtkF
+ {
+ GtkTreeSelection *selection;
+
+@@ -1303,7 +1290,7 @@
+ return;
+ }
+
+-@@ -5988,10 +6381,7 @@ static void
++@@ -6017,10 +6390,7 @@ static void
+ gtk_file_chooser_widget_unselect_all (GtkFileChooser *chooser)
+ {
+ GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
+@@ -1315,7 +1302,7 @@
+ pending_select_files_free (impl);
+ }
+
+-@@ -6147,15 +6537,13 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
++@@ -6176,15 +6546,13 @@ gtk_file_chooser_widget_get_files (GtkFi
+ current_focus = NULL;
+
+ file_list_seen = FALSE;
+@@ -1334,7 +1321,7 @@
+
+ /* If there is no selection in the file list, we probably have this situation:
+ *
+-@@ -6189,7 +6577,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
++@@ -6218,7 +6586,7 @@ gtk_file_chooser_widget_get_files (GtkFi
+ else
+ return NULL;
+ }
+@@ -1343,7 +1330,7 @@
+ goto file_list;
+ else if (priv->location_entry && priv->toplevel_last_focus_widget == priv->location_entry)
+ goto file_entry;
+-@@ -6467,8 +6855,6 @@ switch_folder_foreach_cb (GtkTreeModel *model,
++@@ -6496,8 +6864,6 @@ switch_folder_foreach_cb (GtkTreeModel *
+ static void
+ switch_to_selected_folder (GtkFileChooserWidget *impl)
+ {
+@@ -1352,7 +1339,7 @@
+ struct switch_folder_closure closure;
+
+ /* We do this with foreach() rather than get_selected() as we may be in
+-@@ -6479,8 +6865,7 @@ switch_to_selected_folder (GtkFileChooserWidget *impl)
++@@ -6508,8 +6874,7 @@ switch_to_selected_folder (GtkFileChoose
+ closure.file = NULL;
+ closure.num_selected = 0;
+
+@@ -1362,7 +1349,7 @@
+
+ g_assert (closure.file && closure.num_selected == 1);
+
+-@@ -6498,19 +6883,33 @@ get_selected_file_info_from_file_list (GtkFileChooserWidget *impl,
++@@ -6527,19 +6892,33 @@ get_selected_file_info_from_file_list (G
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GFileInfo *info;
+@@ -1404,7 +1391,7 @@
+ return info;
+ }
+
+-@@ -7007,7 +7406,7 @@ gtk_file_chooser_widget_should_respond (GtkFileChooserEmbed *chooser_embed)
++@@ -7036,7 +7415,7 @@ gtk_file_chooser_widget_should_respond (
+
+ current_focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
+
+@@ -1413,7 +1400,7 @@
+ {
+ /* The following array encodes what we do based on the priv->action and the
+ * number of files selected.
+-@@ -7254,9 +7653,9 @@ gtk_file_chooser_widget_initial_focus (GtkFileChooserEmbed *chooser_embed)
++@@ -7283,9 +7662,9 @@ gtk_file_chooser_widget_initial_focus (G
+ {
+ if (priv->location_mode == LOCATION_MODE_PATH_BAR
+ || priv->operation_mode == OPERATION_MODE_RECENT)
+@@ -1425,7 +1412,7 @@
+ }
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+-@@ -7269,6 +7668,7 @@ gtk_file_chooser_widget_initial_focus (GtkFileChooserEmbed *chooser_embed)
++@@ -7298,6 +7677,7 @@ gtk_file_chooser_widget_initial_focus (G
+
+ g_assert (widget != NULL);
+ gtk_widget_grab_focus (widget);
+@@ -1433,7 +1420,7 @@
+ }
+
+ static void
+-@@ -7292,45 +7692,23 @@ selected_foreach_get_file_cb (GtkTreeModel *model,
++@@ -7321,45 +7701,23 @@ selected_foreach_get_file_cb (GtkTreeMod
+ static GSList *
+ get_selected_files (GtkFileChooserWidget *impl)
+ {
+@@ -1481,7 +1468,7 @@
+ result = g_slist_reverse (result);
+
+ return result;
+-@@ -7402,6 +7780,7 @@ search_engine_finished_cb (GtkSearchEngine *engine,
++@@ -7429,6 +7787,7 @@ search_engine_finished_cb (GtkSearchEngi
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_files_stack), "empty");
+ gtk_entry_grab_focus_without_selecting (GTK_ENTRY (priv->search_entry));
+ }
+@@ -1489,7 +1476,7 @@
+ }
+
+ static void
+-@@ -7427,7 +7806,7 @@ search_clear_model (GtkFileChooserWidget *impl,
++@@ -7454,7 +7813,7 @@ search_clear_model (GtkFileChooserWidget
+
+ if (remove &&
+ gtk_tree_view_get_model (GTK_TREE_VIEW (priv->browse_files_tree_view)) == GTK_TREE_MODEL (priv->search_model))
+@@ -1498,7 +1485,7 @@
+
+ g_clear_object (&priv->search_model);
+ }
+-@@ -7637,7 +8016,7 @@ recent_clear_model (GtkFileChooserWidget *impl,
++@@ -7664,7 +8023,7 @@ recent_clear_model (GtkFileChooserWidget
+ return;
+
+ if (remove)
+@@ -1507,17 +1494,17 @@
+
+ g_set_object (&priv->recent_model, NULL);
+ }
+-@@ -7690,8 +8069,7 @@ recent_idle_cleanup (gpointer data)
++@@ -7717,8 +8076,7 @@ recent_idle_cleanup (gpointer data)
+ GtkFileChooserWidget *impl = load_data->impl;
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+
+ - gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view),
+ - GTK_TREE_MODEL (priv->recent_model));
+ + current_view_set_file_model (impl, GTK_TREE_MODEL (priv->recent_model));
+- gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), -1);
++ gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), 0);
+
+ gtk_tree_view_column_set_sort_column_id (priv->list_name_column, -1);
+-@@ -7839,12 +8217,8 @@ static gboolean
++@@ -7866,12 +8224,8 @@ static gboolean
+ recent_should_respond (GtkFileChooserWidget *impl)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+@@ -1531,7 +1518,7 @@
+ }
+
+ static void
+-@@ -7904,29 +8278,40 @@ check_preview_change (GtkFileChooserWidget *impl)
++@@ -7931,29 +8285,40 @@ check_preview_change (GtkFileChooserWidg
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+
+@@ -1588,7 +1575,7 @@
+ {
+ GtkTreeIter iter;
+
+-@@ -8010,15 +8395,13 @@ list_select_func (GtkTreeSelection *selection,
++@@ -8037,15 +8402,13 @@ list_select_func (GtkTreeSelection *sele
+ return TRUE;
+ }
+
+@@ -1607,11 +1594,10 @@
+ if (priv->location_entry)
+ update_chooser_entry (impl);
+
+-@@ -8042,16 +8425,35 @@ list_row_activated (GtkTreeView *tree_view,
+- GtkTreePath *path,
++@@ -8070,15 +8433,34 @@ list_row_activated (GtkTreeView
+ GtkTreeViewColumn *column,
+ GtkFileChooserWidget *impl)
+-+{
++ {
+ + GtkTreeModel *model;
+ + model = gtk_tree_view_get_model (tree_view);
+ + item_activated (model, path, impl);
+@@ -1633,7 +1619,7 @@
+ +item_activated (GtkTreeModel *model,
+ + GtkTreePath *path,
+ + GtkFileChooserWidget *impl)
+- {
+++{
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+ GFile *file;
+ GtkTreeIter iter;
+@@ -1646,7 +1632,7 @@
+ if (!gtk_tree_model_get_iter (model, &iter, path))
+ return;
+
+-@@ -8071,7 +8473,7 @@ list_row_activated (GtkTreeView *tree_view,
++@@ -8098,7 +8480,7 @@ list_row_activated (GtkTreeView
+ priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ g_signal_emit_by_name (impl, "file-activated");
+
+@@ -1655,7 +1641,7 @@
+
+ if (file)
+ g_object_unref (file);
+-@@ -8102,10 +8504,13 @@ static void
++@@ -8129,10 +8511,13 @@ static void
+ update_cell_renderer_attributes (GtkFileChooserWidget *impl)
+ {
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+@@ -1670,7 +1656,7 @@
+ "sensitive", MODEL_COL_IS_SENSITIVE,
+ NULL);
+ gtk_tree_view_column_set_attributes (priv->list_name_column,
+-@@ -8688,15 +9093,19 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
++@@ -8711,15 +9096,19 @@ gtk_file_chooser_widget_class_init (GtkF
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, browse_files_stack);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, places_sidebar);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, places_view);
+@@ -1691,7 +1677,7 @@
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, preview_box);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, extra_align);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, extra_and_filters);
+-@@ -8715,6 +9124,7 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
++@@ -8738,6 +9127,7 @@ gtk_file_chooser_widget_class_init (GtkF
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, list_type_renderer);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, list_location_column);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, list_location_renderer);
+@@ -1699,7 +1685,7 @@
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, new_folder_name_entry);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, new_folder_create_button);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, new_folder_error_label);
+-@@ -8724,6 +9134,7 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
++@@ -8747,6 +9137,7 @@ gtk_file_chooser_widget_class_init (GtkF
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, rename_file_error_label);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, rename_file_popover);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, remote_warning_bar);
+@@ -1707,7 +1693,7 @@
+
+ /* And a *lot* of callbacks to bind ... */
+ gtk_widget_class_bind_template_callback (widget_class, browse_files_key_press_event_cb);
+-@@ -8738,6 +9149,10 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
++@@ -8761,6 +9152,10 @@ gtk_file_chooser_widget_class_init (GtkF
+ gtk_widget_class_bind_template_callback (widget_class, file_list_drag_end_cb);
+ gtk_widget_class_bind_template_callback (widget_class, list_selection_changed);
+ gtk_widget_class_bind_template_callback (widget_class, list_cursor_changed);
+@@ -1718,7 +1704,7 @@
+ gtk_widget_class_bind_template_callback (widget_class, filter_combo_changed);
+ gtk_widget_class_bind_template_callback (widget_class, path_bar_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, places_sidebar_open_location_cb);
+-@@ -8785,6 +9200,18 @@ post_process_ui (GtkFileChooserWidget *impl)
++@@ -8810,6 +9205,18 @@ post_process_ui (GtkFileChooserWidget *i
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+ gtk_drag_dest_add_uri_targets (impl->priv->browse_files_tree_view);
+
+@@ -1737,7 +1723,7 @@
+ /* File browser treemodel columns are shared between GtkFileChooser implementations,
+ * so we don't set cell renderer attributes in GtkBuilder, but rather keep that
+ * in code.
+-@@ -8816,6 +9243,7 @@ post_process_ui (GtkFileChooserWidget *impl)
++@@ -8841,6 +9248,7 @@ post_process_ui (GtkFileChooserWidget *i
+ * that priv->icon_size be already setup.
+ */
+ set_icon_cell_renderer_fixed_size (impl);
+@@ -1745,7 +1731,7 @@
+
+ atk_obj = gtk_widget_get_accessible (impl->priv->browse_new_folder_button);
+ if (GTK_IS_ACCESSIBLE (atk_obj))
+-@@ -8867,7 +9295,8 @@ gtk_file_chooser_widget_init (GtkFileChooserWidget *impl)
++@@ -8902,7 +9310,8 @@ gtk_file_chooser_widget_init (GtkFileCho
+ priv->show_size_column = TRUE;
+ priv->show_type_column = TRUE;
+ priv->type_format = TYPE_FORMAT_MIME;
+@@ -1755,7 +1741,7 @@
+ priv->load_state = LOAD_EMPTY;
+ priv->reload_state = RELOAD_EMPTY;
+ priv->pending_select_files = NULL;
+-@@ -8879,6 +9308,7 @@ gtk_file_chooser_widget_init (GtkFileChooserWidget *impl)
++@@ -8914,6 +9323,7 @@ gtk_file_chooser_widget_init (GtkFileCho
+ priv->create_folders = TRUE;
+ priv->auto_selecting_first_row = FALSE;
+ priv->renamed_file = NULL;
+@@ -1763,7 +1749,7 @@
+
+ /* Ensure GTK+ private types used by the template
+ * definition before calling gtk_widget_init_template()
+-@@ -8926,6 +9356,258 @@ gtk_file_chooser_widget_new (GtkFileChooserAction action)
++@@ -8961,6 +9371,258 @@ gtk_file_chooser_widget_new (GtkFileChoo
+ NULL);
+ }
+
+@@ -2022,13 +2008,11 @@
+ static void
+ gtk_file_chooser_widget_add_choice (GtkFileChooser *chooser,
+ const char *id,
+-@@ -9045,4 +9727,3 @@ gtk_file_chooser_widget_get_choice (GtkFileChooser *chooser,
++@@ -9080,4 +9742,3 @@ gtk_file_chooser_widget_get_choice (GtkF
+
+ return NULL;
+ }
+ -
+-diff --git a/gtk/org.gtk.Settings.FileChooser.gschema.xml b/gtk/org.gtk.Settings.FileChooser.gschema.xml
+-index dda603ab61..d0f275a01e 100644
+ --- a/gtk/org.gtk.Settings.FileChooser.gschema.xml
+ +++ b/gtk/org.gtk.Settings.FileChooser.gschema.xml
+ @@ -55,6 +55,11 @@
+@@ -2121,44 +2105,12 @@
+ window.
+ </description>
+ </key>
+-@@ -129,23 +148,23 @@
+- <default>(-1, -1)</default>
+- <summary>Window size</summary>
+- <description>
+-- The size (width, height) of the GtkFileChooserDialog's window, in pixels.
+-+ The size (width, height) of the GtkFileChooserDialog's window, in pixels.
+- </description>
+- </key>
+- <key name='startup-mode' enum='org.gtk.Settings.FileChooser.StartupMode'>
+- <default>'recent'</default>
+- <summary>Startup mode</summary>
+- <description>
+-- Either "recent" or "cwd"; controls whether the file chooser
+-- starts up showing the list of recently-used files, or the
+-- contents of the current working directory.
+-+ Either "recent" or "cwd"; controls whether the file chooser
+-+ starts up showing the list of recently-used files, or the
+-+ contents of the current working directory.
+- </description>
+- </key>
+- <key name='sidebar-width' type='i'>
+- <default>148</default>
+- <summary>Sidebar width</summary>
+- <description>
+-- Width in pixels of the file chooser's places sidebar.
+-+ Width in pixels of the file chooser's places sidebar.
+- </description>
+- </key>
+- <key name="clock-format" enum="org.gtk.Settings.FileChooser.ClockFormat">
+-diff --git a/gtk/ui/gtkfilechooserwidget.ui b/gtk/ui/gtkfilechooserwidget.ui
+-index 01d4075f6c..269a95fd4b 100644
+ --- a/gtk/ui/gtkfilechooserwidget.ui
+ +++ b/gtk/ui/gtkfilechooserwidget.ui
+-@@ -8,6 +8,56 @@
+- <object class="GtkBox" id="browse_widgets_box">
++@@ -9,6 +9,56 @@
+ <property name="visible">1</property>
+ <property name="orientation">vertical</property>
+-+ <child>
++ <child>
+ + <object class="GtkBox" id="combo_box_and_scale">
+ + <property name="visible">1</property>
+ + <child>
+@@ -2208,10 +2160,11 @@
+ + </child>
+ + </object>
+ + </child>
+- <child>
+++ <child>
+ <object class="GtkPaned" id="browse_widgets_hpaned">
+ <property name="visible">1</property>
+-@@ -156,110 +206,172 @@
++ <child>
++@@ -187,110 +237,172 @@
+ <property name="visible">1</property>
+ <property name="orientation">vertical</property>
+ <child>
+@@ -2458,7 +2411,7 @@
+ </child>
+ </object>
+ <packing>
+-@@ -378,7 +490,7 @@
++@@ -409,7 +521,7 @@
+ </object>
+ <packing>
+ <property name="expand">1</property>
bgstack15