-
-
Save Dudemanguy/c172394e30e1e7d0f477ad15c719bc71 to your computer and use it in GitHub Desktop.
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 @@ | |
#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); | |
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 @@ | |
#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" | |
@@ -81,6 +83,7 @@ | |
#include "gtkgesturelongpress.h" | |
#include <cairo-gobject.h> | |
+#include <math.h> | |
#ifdef HAVE_UNISTD_H | |
#include <unistd.h> | |
@@ -198,6 +201,11 @@ typedef enum { | |
STARTUP_MODE_CWD | |
} StartupMode; | |
+typedef enum { | |
+ VIEW_MODE_LIST, | |
+ VIEW_MODE_ICON, | |
+} ViewMode; | |
+ | |
typedef enum { | |
CLOCK_FORMAT_24, | |
CLOCK_FORMAT_12 | |
@@ -228,8 +236,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; | |
@@ -245,6 +257,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; | |
@@ -261,6 +279,7 @@ struct _GtkFileChooserWidgetPrivate { | |
GtkGesture *long_press_gesture; | |
+ GtkTreeModel *current_model; | |
GtkFileSystemModel *browse_files_model; | |
char *browse_files_last_selected_name; | |
@@ -348,10 +367,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; | |
@@ -419,7 +445,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, | |
@@ -439,7 +466,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 */ \ | |
@@ -449,7 +477,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 | |
@@ -570,7 +601,7 @@ static gboolean list_select_func (GtkTreeSelection *selection, | |
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, | |
@@ -578,6 +609,13 @@ static void list_row_activated (GtkTreeView *tree_view, | |
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, | |
@@ -590,6 +628,13 @@ static void update_cell_renderer_attributes (GtkFileChooserWidget *impl); | |
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, | |
@@ -619,6 +664,26 @@ static gboolean recent_should_respond (GtkFileChooserWidget *impl); | |
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, | |
@@ -956,7 +1021,7 @@ update_preview_widget_visibility (GtkFileChooserWidget *impl) | |
} | |
} | |
- 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); | |
@@ -1224,19 +1289,16 @@ selection_check (GtkFileChooserWidget *impl, | |
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)); | |
@@ -1361,7 +1423,7 @@ browse_files_key_press_event_cb (GtkWidget *widget, | |
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; | |
@@ -1464,12 +1526,8 @@ add_to_shortcuts_cb (GSimpleAction *action, | |
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); | |
} | |
@@ -1842,6 +1900,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, | |
@@ -2169,6 +2307,7 @@ check_file_list_popover_sensitivity (GtkFileChooserWidget *impl) | |
gboolean all_files; | |
gboolean all_folders; | |
gboolean active; | |
+ gboolean always_active; | |
GActionGroup *actions; | |
GAction *action, *action2; | |
@@ -2177,6 +2316,7 @@ check_file_list_popover_sensitivity (GtkFileChooserWidget *impl) | |
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); | |
@@ -2190,6 +2330,21 @@ check_file_list_popover_sensitivity (GtkFileChooserWidget *impl) | |
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) | |
{ | |
@@ -2255,6 +2410,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 }, | |
@@ -2280,15 +2440,9 @@ append_separator (GtkWidget *box) | |
{ | |
GtkWidget *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); | |
+ 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; | |
} | |
@@ -2301,12 +2455,13 @@ add_button (GtkWidget *box, | |
{ | |
GtkWidget *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; | |
} | |
@@ -2320,11 +2475,9 @@ file_list_build_popover (GtkFileChooserWidget *impl) | |
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; | |
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) | |
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"); | |
+ } | |
} | |
/* Updates the popover for the file list, creating it if necessary */ | |
@@ -2392,39 +2563,11 @@ file_list_show_popover (GtkFileChooserWidget *impl, | |
gdouble y) | |
{ | |
GtkFileChooserWidgetPrivate *priv = impl->priv; | |
- GdkRectangle rect; | |
- GtkTreeSelection *selection; | |
- GtkTreeModel *model; | |
- GList *list; | |
- GtkTreePath *path; | |
- | |
file_list_update_popover (impl); | |
- 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)); | |
+ 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, | |
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); | |
@@ -2492,13 +2635,16 @@ file_list_set_sort_column_ids (GtkFileChooserWidget *impl) | |
{ | |
GtkFileChooserWidgetPrivate *priv = impl->priv; | |
- gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view), -1); | |
+ 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_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 | |
@@ -2521,11 +2667,22 @@ file_list_query_tooltip_cb (GtkWidget *widget, | |
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, | |
@@ -2539,10 +2696,18 @@ file_list_query_tooltip_cb (GtkWidget *widget, | |
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); | |
@@ -2558,8 +2723,8 @@ set_icon_cell_renderer_fixed_size (GtkFileChooserWidget *impl) | |
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 | |
@@ -2843,7 +3008,7 @@ location_mode_set (GtkFileChooserWidget *impl, | |
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; | |
@@ -2914,6 +3079,119 @@ location_toggle_popup_handler (GtkFileChooserWidget *impl) | |
} | |
} | |
+/* 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) | |
{ | |
@@ -3022,18 +3300,11 @@ set_select_multiple (GtkFileChooserWidget *impl, | |
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"); | |
@@ -3160,6 +3431,7 @@ operation_mode_set_enter_location (GtkFileChooserWidget *impl) | |
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); | |
} | |
@@ -3189,7 +3461,7 @@ operation_mode_set_search (GtkFileChooserWidget *impl) | |
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"); | |
} | |
@@ -3314,6 +3586,12 @@ update_appearance (GtkFileChooserWidget *impl) | |
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); | |
@@ -3322,7 +3600,7 @@ update_appearance (GtkFileChooserWidget *impl) | |
/* 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); | |
} | |
@@ -3752,14 +4030,27 @@ change_icon_theme (GtkFileChooserWidget *impl) | |
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); | |
@@ -3860,7 +4151,7 @@ set_sort_column (GtkFileChooserWidget *impl) | |
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) | |
@@ -3875,6 +4166,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; | |
@@ -3882,6 +4174,7 @@ settings_load (GtkFileChooserWidget *impl) | |
DateFormat date_format; | |
TypeFormat type_format; | |
gint sort_column; | |
+ gint icon_view_scale; | |
GtkSortType sort_order; | |
StartupMode startup_mode; | |
gint sidebar_width; | |
@@ -3889,6 +4182,8 @@ settings_load (GtkFileChooserWidget *impl) | |
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); | |
@@ -3900,12 +4195,20 @@ settings_load (GtkFileChooserWidget *impl) | |
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; | |
@@ -3934,6 +4237,8 @@ settings_save (GtkFileChooserWidget *impl) | |
/* 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); | |
@@ -4445,10 +4750,14 @@ load_set_model (GtkFileChooserWidget *impl) | |
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; | |
@@ -4528,7 +4837,7 @@ browse_files_select_first_row (GtkFileChooserWidget *impl) | |
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; | |
@@ -4547,8 +4856,7 @@ browse_files_select_first_row (GtkFileChooserWidget *impl) | |
*/ | |
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); | |
@@ -4574,7 +4882,13 @@ center_selected_row_foreach_cb (GtkTreeModel *model, | |
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; | |
} | |
@@ -4582,15 +4896,11 @@ center_selected_row_foreach_cb (GtkTreeModel *model, | |
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 | |
@@ -4598,7 +4908,6 @@ show_and_select_files (GtkFileChooserWidget *impl, | |
GSList *files) | |
{ | |
GtkFileChooserWidgetPrivate *priv = impl->priv; | |
- GtkTreeSelection *selection; | |
GtkFileSystemModel *fsmodel; | |
gboolean enabled_hidden, removed_filters; | |
gboolean selected_a_file; | |
@@ -4607,8 +4916,7 @@ show_and_select_files (GtkFileChooserWidget *impl, | |
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); | |
@@ -4663,11 +4971,10 @@ show_and_select_files (GtkFileChooserWidget *impl, | |
{ | |
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; | |
@@ -4818,12 +5125,15 @@ stop_loading_and_clear_list_model (GtkFileChooserWidget *impl, | |
{ | |
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. */ | |
@@ -5093,6 +5403,18 @@ end: | |
return g_strdup (""); | |
} | |
+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, | |
@@ -5152,12 +5474,15 @@ file_system_model_set (GtkFileSystemModel *model, | |
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 | |
{ | |
@@ -5211,6 +5536,76 @@ file_system_model_set (GtkFileSystemModel *model, | |
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; | |
@@ -5403,7 +5798,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 */ | |
@@ -5420,9 +5814,8 @@ update_chooser_entry (GtkFileChooserWidget *impl) | |
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) | |
{ | |
@@ -5919,19 +6312,15 @@ gtk_file_chooser_widget_unselect_file (GtkFileChooser *chooser, | |
{ | |
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 | |
@@ -5942,12 +6331,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, | |
@@ -5956,9 +6342,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; | |
} | |
@@ -5974,8 +6360,15 @@ gtk_file_chooser_widget_select_all (GtkFileChooser *chooser) | |
{ | |
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; | |
} | |
@@ -5988,10 +6381,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); | |
} | |
@@ -6147,15 +6537,13 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser) | |
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: | |
* | |
@@ -6189,7 +6577,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser) | |
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; | |
@@ -6467,8 +6855,6 @@ switch_folder_foreach_cb (GtkTreeModel *model, | |
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 | |
@@ -6479,8 +6865,7 @@ switch_to_selected_folder (GtkFileChooserWidget *impl) | |
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); | |
@@ -6498,19 +6883,33 @@ get_selected_file_info_from_file_list (GtkFileChooserWidget *impl, | |
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; | |
} | |
@@ -7007,7 +7406,7 @@ gtk_file_chooser_widget_should_respond (GtkFileChooserEmbed *chooser_embed) | |
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. | |
@@ -7254,9 +7653,9 @@ gtk_file_chooser_widget_initial_focus (GtkFileChooserEmbed *chooser_embed) | |
{ | |
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) | |
@@ -7269,6 +7668,7 @@ gtk_file_chooser_widget_initial_focus (GtkFileChooserEmbed *chooser_embed) | |
g_assert (widget != NULL); | |
gtk_widget_grab_focus (widget); | |
+ create_browse_files_icon_view (impl); | |
} | |
static void | |
@@ -7292,45 +7692,23 @@ selected_foreach_get_file_cb (GtkTreeModel *model, | |
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; | |
@@ -7402,6 +7780,7 @@ search_engine_finished_cb (GtkSearchEngine *engine, | |
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 | |
@@ -7427,7 +7806,7 @@ search_clear_model (GtkFileChooserWidget *impl, | |
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); | |
} | |
@@ -7637,7 +8016,7 @@ recent_clear_model (GtkFileChooserWidget *impl, | |
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); | |
} | |
@@ -7690,8 +8069,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_column_set_sort_column_id (priv->list_name_column, -1); | |
@@ -7839,12 +8217,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 | |
@@ -7904,29 +8278,40 @@ check_preview_change (GtkFileChooserWidget *impl) | |
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; | |
@@ -8010,15 +8395,13 @@ list_select_func (GtkTreeSelection *selection, | |
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); | |
@@ -8042,16 +8425,35 @@ list_row_activated (GtkTreeView *tree_view, | |
GtkTreePath *path, | |
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; | |
@@ -8071,7 +8473,7 @@ list_row_activated (GtkTreeView *tree_view, | |
priv->action == GTK_FILE_CHOOSER_ACTION_SAVE) | |
g_signal_emit_by_name (impl, "file-activated"); | |
- out: | |
+ out: | |
if (file) | |
g_object_unref (file); | |
@@ -8102,10 +8504,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, | |
@@ -8688,15 +9093,19 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class) | |
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); | |
@@ -8715,6 +9124,7 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class) | |
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); | |
@@ -8724,6 +9134,7 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class) | |
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); | |
@@ -8738,6 +9149,10 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class) | |
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); | |
@@ -8785,6 +9200,18 @@ post_process_ui (GtkFileChooserWidget *impl) | |
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. | |
@@ -8816,6 +9243,7 @@ post_process_ui (GtkFileChooserWidget *impl) | |
* 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)) | |
@@ -8867,7 +9295,8 @@ gtk_file_chooser_widget_init (GtkFileChooserWidget *impl) | |
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; | |
@@ -8879,6 +9308,7 @@ gtk_file_chooser_widget_init (GtkFileChooserWidget *impl) | |
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() | |
@@ -8926,6 +9356,258 @@ gtk_file_chooser_widget_new (GtkFileChooserAction action) | |
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, | |
@@ -9045,4 +9727,3 @@ gtk_file_chooser_widget_get_choice (GtkFileChooser *chooser, | |
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 @@ | |
<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> | |
@@ -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"> | |
<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> | |
@@ -156,110 +206,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> | |
@@ -378,7 +490,7 @@ | |
</object> | |
<packing> | |
<property name="expand">1</property> | |
- <property name="position">1</property> | |
+ <property name="position">2</property> | |
</packing> | |
</child> | |
</object> |
Apologies for the late response. I have brought this up before. Essentially, GNOME devs will not take this because it is based around the gtkiconview which they consider too slow. I am not aware of another widget that provides similar functionality in a better way. Gtkflowbox is supposed to be the future replacement for gtkiconview, but the last time I checked, it was heavily in development and not ready.
You would need to check out gtk's source code, apply it there, and then build it.
Is it possible to make it so that the generic folder/app icons are smaller than the image previews? I keep having to mess with the size slider depending on what folder I'm in.
Do you mean while in the icon view mode? No it is not. Everything is an icon with the same size which is how the iconview widget works.
I see. Shame. Thanks for maintaining this, though.
Hello, this patch is really nice, but can I make a suggestion? Wouldn't it be better to merge the new combo box + slider into an existing panel/area instead of making a new separate one? Like for example, you could place them on the left side of the bottom bar, inline with the existing combo box that says 'All files'. I tried to implement this myself but I have no idea what I'm doing in terms of making the patch file, building, etc.
If I were to merge that box/bar somewhere, I would prefer to put it on the top bar (where the cancel button and stuff is). However, the code that actually creates that is kind of complicated and different than just simplistic gtkfilechooserwidget.ui
for the rest of the dialog. Not impossible or anything of course, but I never felt like going through all that.
I'm currently fixing the patch for the newest gtk version, just correcting bugs without coding anything^^ hope that will work
EDIT: I think it won't, the gtk code totally changed^^
A gtk4 port of this would need to use GtkGridView. I keep telling myself I will get around to it one day, but it hasn't happened yet.
Thanks for the patch, it's a total lifesaver. Because the 4 files that get modified haven't been touched in about 2-3 years, it will almost certainly be a drop in patch for RHEL 8 / AlmaLinux 8. Thanks a ton man.
have you suggested this in gtk forum?