Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Dudemanguy/d70734d5bdf82e79cbfb22894fac8a1b to your computer and use it in GitHub Desktop.
Save Dudemanguy/d70734d5bdf82e79cbfb22894fac8a1b to your computer and use it in GitHub Desktop.
Adds an icon view to the gtk2 filechooser upload dialog. Generated from https://github.com/Dudemanguy911/gtk/tree/gtk2-filechooser-icon-view
diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c
index c11354248e..a994aa9c6f 100644
--- a/gtk/gtkfilechooserdefault.c
+++ b/gtk/gtkfilechooserdefault.c
@@ -80,6 +80,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <locale.h>
+#include <math.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -205,7 +206,8 @@ enum {
MODEL_COL_NAME_COLLATED,
MODEL_COL_IS_FOLDER,
MODEL_COL_IS_SENSITIVE,
- MODEL_COL_PIXBUF,
+ MODEL_COL_LIST_PIXBUF,
+ MODEL_COL_ICON_PIXBUF,
MODEL_COL_SIZE_TEXT,
MODEL_COL_MTIME_TEXT,
MODEL_COL_ELLIPSIZE,
@@ -222,7 +224,8 @@ enum {
G_TYPE_STRING, /* MODEL_COL_NAME_COLLATED */ \
G_TYPE_BOOLEAN, /* MODEL_COL_IS_FOLDER */ \
G_TYPE_BOOLEAN, /* MODEL_COL_IS_SENSITIVE */ \
- GDK_TYPE_PIXBUF, /* MODEL_COL_PIXBUF */ \
+ GDK_TYPE_PIXBUF, /* MODEL_COL_LIST_PIXBUF */ \
+ GDK_TYPE_PIXBUF, /* MODEL_COL_ICON_PIXBUF */ \
G_TYPE_STRING, /* MODEL_COL_SIZE_TEXT */ \
G_TYPE_STRING, /* MODEL_COL_MTIME_TEXT */ \
PANGO_TYPE_ELLIPSIZE_MODE /* MODEL_COL_ELLIPSIZE */
@@ -249,7 +252,10 @@ typedef enum {
} ShortcutsIndex;
/* 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
@@ -337,6 +343,7 @@ static void show_hidden_handler (GtkFileChooserDefault *impl);
static void search_shortcut_handler (GtkFileChooserDefault *impl);
static void recent_shortcut_handler (GtkFileChooserDefault *impl);
static void update_appearance (GtkFileChooserDefault *impl);
+static void set_sort_column (GtkFileChooserDefault *impl);
static void set_current_filter (GtkFileChooserDefault *impl,
GtkFileFilter *filter);
@@ -371,12 +378,18 @@ 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 *tree_or_icon_selection,
GtkFileChooserDefault *impl);
static void list_row_activated (GtkTreeView *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
GtkFileChooserDefault *impl);
+static void icon_item_activated (GtkIconView *icon_view,
+ GtkTreePath *path,
+ GtkFileChooserDefault *impl);
+static void item_activated (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkFileChooserDefault *impl);
static void path_bar_clicked (GtkPathBar *path_bar,
GFile *file,
@@ -394,6 +407,13 @@ static void update_cell_renderer_attributes (GtkFileChooserDefault *impl);
static void load_remove_timer (GtkFileChooserDefault *impl, LoadState new_load_state);
static void browse_files_center_selected_row (GtkFileChooserDefault *impl);
+static void view_mode_set (GtkFileChooserDefault *impl, ViewMode view_mode);
+static void view_mode_combo_box_changed_cb (GtkComboBox *combo,
+ GtkFileChooserDefault *impl);
+
+static void icon_view_scale_value_changed_cb (GtkRange *range,
+ GtkFileChooserDefault *impl);
+
static void location_button_toggled_cb (GtkToggleButton *toggle,
GtkFileChooserDefault *impl);
static void location_switch_to_path_bar (GtkFileChooserDefault *impl);
@@ -422,7 +442,27 @@ static GSList * recent_get_selected_files (GtkFileChooserDefault *impl);
static void set_file_system_backend (GtkFileChooserDefault *impl);
static void unset_file_system_backend (GtkFileChooserDefault *impl);
-
+static gboolean get_selected_tree_iter_from_icon_view (GtkFileChooserDefault *impl,
+ GtkTreeIter *iter_out);
+static void current_selection_selected_foreach (GtkFileChooserDefault *impl,
+ GtkTreeSelectionForeachFunc func,
+ gpointer data);
+static guint current_selection_count_selected_rows (GtkFileChooserDefault *impl);
+static void current_selection_select_iter (GtkFileChooserDefault *impl,
+ GtkTreeIter *iter);
+static void copy_old_selection_to_current_view (GtkFileChooserDefault *impl,
+ ViewMode old_view_mode);
+static void current_selection_unselect_iter (GtkFileChooserDefault *impl,
+ GtkTreeIter *iter);
+static void current_selection_unselect_all (GtkFileChooserDefault *impl);
+static void current_view_set_file_model (GtkFileChooserDefault *impl,
+ GtkTreeModel *model);
+static void current_view_set_cursor (GtkFileChooserDefault *impl,
+ GtkTreePath *path);
+static void current_view_set_select_multiple (GtkFileChooserDefault *impl,
+ gboolean select_multiple);
+
+static GSource *add_idle_while_impl_is_alive (GtkFileChooserDefault *impl, GCallback callback);
@@ -723,7 +763,8 @@ _gtk_file_chooser_default_init (GtkFileChooserDefault *impl)
impl->select_multiple = FALSE;
impl->show_hidden = FALSE;
impl->show_size_column = TRUE;
- impl->icon_size = FALLBACK_ICON_SIZE;
+ impl->list_view_icon_size = FALLBACK_LIST_VIEW_ICON_SIZE;
+ impl->icon_view_icon_size = FALLBACK_ICON_VIEW_ICON_SIZE;
impl->load_state = LOAD_EMPTY;
impl->reload_state = RELOAD_EMPTY;
impl->pending_select_files = NULL;
@@ -733,6 +774,7 @@ _gtk_file_chooser_default_init (GtkFileChooserDefault *impl)
impl->sort_order = GTK_SORT_ASCENDING;
impl->recent_manager = gtk_recent_manager_get_default ();
impl->create_folders = TRUE;
+ impl->view_mode = VIEW_MODE_LIST;
gtk_box_set_spacing (GTK_BOX (impl), 12);
@@ -1159,7 +1201,7 @@ render_recent_icon (GtkFileChooserDefault *impl)
theme = gtk_icon_theme_get_default ();
retval = gtk_icon_theme_load_icon (theme, "document-open-recent",
- impl->icon_size, 0,
+ impl->list_view_icon_size, 0,
NULL);
/* fallback */
@@ -1197,7 +1239,7 @@ shortcuts_reload_icons_get_info_cb (GCancellable *cancellable,
if (cancelled || error)
goto out;
- pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (data->impl), data->impl->icon_size);
+ pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (data->impl), data->impl->list_view_icon_size);
path = gtk_tree_row_reference_get_path (data->row_ref);
if (path)
@@ -1261,7 +1303,7 @@ shortcuts_reload_icons (GtkFileChooserDefault *impl)
volume = data;
pixbuf = _gtk_file_system_volume_render_icon (volume, GTK_WIDGET (impl),
- impl->icon_size, NULL);
+ impl->list_view_icon_size, NULL);
}
else if (shortcut_type == SHORTCUT_TYPE_FILE)
{
@@ -1297,7 +1339,7 @@ shortcuts_reload_icons (GtkFileChooserDefault *impl)
*/
icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
pixbuf = gtk_icon_theme_load_icon (icon_theme, "folder-remote",
- impl->icon_size, 0, NULL);
+ impl->list_view_icon_size, 0, NULL);
}
}
else if (shortcut_type == SHORTCUT_TYPE_SEARCH)
@@ -1508,7 +1550,7 @@ get_file_info_finished (GCancellable *cancellable,
if (!request->label_copy)
request->label_copy = g_strdup (g_file_info_get_display_name (info));
pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (request->impl),
- request->impl->icon_size);
+ request->impl->list_view_icon_size);
gtk_list_store_set (request->impl->shortcuts_model, &iter,
SHORTCUTS_COL_PIXBUF, pixbuf,
@@ -1616,7 +1658,7 @@ shortcuts_insert_file (GtkFileChooserDefault *impl,
data = volume;
label_copy = _gtk_file_system_volume_get_display_name (volume);
pixbuf = _gtk_file_system_volume_render_icon (volume, GTK_WIDGET (impl),
- impl->icon_size, NULL);
+ impl->list_view_icon_size, NULL);
}
else if (shortcut_type == SHORTCUT_TYPE_FILE)
{
@@ -1675,7 +1717,7 @@ shortcuts_insert_file (GtkFileChooserDefault *impl,
*/
icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
pixbuf = gtk_icon_theme_load_icon (icon_theme, "folder-remote",
- impl->icon_size, 0, NULL);
+ impl->list_view_icon_size, 0, NULL);
}
}
else
@@ -2235,6 +2277,52 @@ shortcuts_model_create (GtkFileChooserDefault *impl)
NULL);
}
+static gboolean
+start_editing_icon_view_idle_cb (GtkFileChooserDefault *impl)
+{
+ GDK_THREADS_ENTER ();
+
+ g_source_destroy (impl->start_editing_icon_view_idle);
+ impl->start_editing_icon_view_idle = NULL;
+
+ gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (impl->browse_files_icon_view),
+ impl->start_editing_icon_view_path,
+ TRUE,
+ 0.5,
+ 0.0);
+
+ g_object_set (impl->list_name_renderer, "editable", TRUE, NULL);
+ gtk_icon_view_set_cursor (GTK_ICON_VIEW (impl->browse_files_icon_view),
+ impl->start_editing_icon_view_path,
+ impl->list_name_renderer,
+ TRUE);
+
+ gtk_tree_path_free (impl->start_editing_icon_view_path);
+ impl->start_editing_icon_view_path = NULL;
+
+ GDK_THREADS_LEAVE ();
+
+ return FALSE;
+}
+
+static void
+add_idle_to_edit_icon_view (GtkFileChooserDefault *impl, GtkTreePath *path)
+{
+ /* Normally we would run the code in the start_editing_icon_view_idle_cb() synchronously,
+ * but GtkIconView doesn't like to start editing itself immediately after getting an item
+ * added - it wants to run its layout loop first. So, we add the editable item first, and
+ * only start editing it until an idle handler.
+ */
+
+ g_assert (impl->start_editing_icon_view_idle == NULL);
+ g_assert (impl->start_editing_icon_view_path == NULL);
+
+ impl->start_editing_icon_view_path = path;
+ impl->start_editing_icon_view_idle = add_idle_while_impl_is_alive (impl,
+ G_CALLBACK (start_editing_icon_view_idle_cb));
+}
+
+
/* Callback used when the "New Folder" button is clicked */
static void
new_folder_button_clicked (GtkButton *button,
@@ -2252,17 +2340,26 @@ new_folder_button_clicked (GtkButton *button,
_gtk_file_system_model_add_editable (impl->browse_files_model, &iter);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->browse_files_model), &iter);
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->browse_files_tree_view),
- path, impl->list_name_column,
- FALSE, 0.0, 0.0);
- g_object_set (impl->list_name_renderer, "editable", TRUE, NULL);
- gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view),
- path,
- impl->list_name_column,
- TRUE);
+ if (impl->view_mode == VIEW_MODE_LIST)
+ {
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->browse_files_tree_view),
+ path, impl->list_name_column,
+ FALSE, 0.0, 0.0);
- gtk_tree_path_free (path);
+ g_object_set (impl->list_name_renderer, "editable", TRUE, NULL);
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view),
+ path,
+ impl->list_name_column,
+ TRUE);
+ gtk_tree_path_free (path);
+ }
+ else if (impl->view_mode == VIEW_MODE_ICON)
+ {
+ add_idle_to_edit_icon_view (impl, path);
+ }
+ else
+ g_assert_not_reached ();
}
static GSource *
@@ -2355,6 +2452,17 @@ renderer_edited_cb (GtkCellRendererText *cell_renderer_text,
queue_edited_idle (impl, new_text);
}
+/* Callback used from the icon view text renderer to center editable text */
+static void
+renderer_editing_started_cb (GtkCellRendererText *cell_renderer_text,
+ GtkCellEditable *editable,
+ const gchar *path,
+ GtkFileChooserDefault *impl)
+{
+ if (GTK_IS_ENTRY (editable))
+ gtk_entry_set_alignment (GTK_ENTRY (editable), 0.5);
+}
+
/* Callback used from the text cell renderer when the new folder edition gets
* canceled.
*/
@@ -2525,16 +2633,10 @@ add_bookmark_foreach_cb (GtkTreeModel *model,
static void
bookmarks_add_selected_folder (GtkFileChooserDefault *impl)
{
- GtkTreeSelection *selection;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
-
- if (gtk_tree_selection_count_selected_rows (selection) == 0)
+ if (current_selection_count_selected_rows (impl) == 0)
shortcuts_add_bookmark_from_file (impl, impl->current_folder, -1);
else
- gtk_tree_selection_selected_foreach (selection,
- add_bookmark_foreach_cb,
- impl);
+ current_selection_selected_foreach (impl, add_bookmark_foreach_cb, impl);
}
/* Callback used when the "Add bookmark" button is clicked */
@@ -2650,17 +2752,16 @@ selection_check (GtkFileChooserDefault *impl,
gboolean *all_folders)
{
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 (impl->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));
@@ -2704,15 +2805,13 @@ static GFile *
get_selected_file (GtkFileChooserDefault *impl)
{
struct get_selected_file_closure closure;
- GtkTreeSelection *selection;
closure.impl = impl;
closure.file = NULL;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- gtk_tree_selection_selected_foreach (selection,
- get_selected_file_foreach_cb,
- &closure);
+ current_selection_selected_foreach(impl,
+ get_selected_file_foreach_cb,
+ &closure);
return closure.file;
}
@@ -2787,13 +2886,11 @@ bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl)
tip = g_strdup_printf (_("Add the selected folders to the bookmarks"));
else
{
- GtkTreeSelection *selection;
UpdateTooltipData data;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
data.impl = impl;
data.tip = NULL;
- gtk_tree_selection_selected_foreach (selection, update_tooltip, &data);
+ current_selection_selected_foreach(impl, update_tooltip, &data);
tip = data.tip;
}
@@ -3775,7 +3872,7 @@ browse_files_key_press_event_cb (GtkWidget *widget,
return TRUE;
}
- if (key_is_left_or_right (event))
+ if (impl->view_mode == VIEW_MODE_LIST && key_is_left_or_right (event))
{
gtk_widget_grab_focus (impl->browse_shortcuts_tree_view);
return TRUE;
@@ -3857,6 +3954,145 @@ show_size_column_toggled_cb (GtkCheckMenuItem *item,
impl->show_size_column);
}
+/* Callback used when "Sort by Name" menu item is toggled */
+static void
+sort_by_name_toggled_cb (GtkCheckMenuItem *item,
+ GtkFileChooserDefault *impl)
+{
+ GtkCheckMenuItem *size_item = GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_by_size_item),
+ *mtime_item = GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_by_mtime_item);
+
+ // This could be avoided if we used GtkAction's
+ if (!gtk_check_menu_item_get_active (item) &&
+ !gtk_check_menu_item_get_active (size_item) &&
+ !gtk_check_menu_item_get_active (mtime_item))
+ {
+ gtk_check_menu_item_set_active (item, TRUE);
+ return;
+ }
+
+ if (gtk_check_menu_item_get_active (item))
+ {
+ gtk_check_menu_item_set_active (size_item, FALSE);
+ gtk_check_menu_item_set_active (mtime_item, FALSE);
+
+ impl->sort_column = MODEL_COL_NAME;
+ set_sort_column (impl);
+ }
+}
+
+/* Callback used when "Sort by Size" menu item is toggled */
+static void
+sort_by_size_toggled_cb (GtkCheckMenuItem *item,
+ GtkFileChooserDefault *impl)
+{
+ GtkCheckMenuItem *name_item = GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_by_name_item),
+ *mtime_item = GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_by_mtime_item);
+
+ // This could be avoided if we used GtkAction's
+ if (!gtk_check_menu_item_get_active (item) &&
+ !gtk_check_menu_item_get_active (name_item) &&
+ !gtk_check_menu_item_get_active (mtime_item))
+ {
+ gtk_check_menu_item_set_active (item, TRUE);
+ return;
+ }
+
+ if (gtk_check_menu_item_get_active (item))
+ {
+ gtk_check_menu_item_set_active (name_item, FALSE);
+ gtk_check_menu_item_set_active (mtime_item, FALSE);
+
+ impl->sort_column = MODEL_COL_SIZE;
+ set_sort_column (impl);
+ }
+}
+
+/* Callback used when "Sort by Modification Date" menu item is toggled */
+static void
+sort_by_mtime_toggled_cb (GtkCheckMenuItem *item,
+ GtkFileChooserDefault *impl)
+{
+ GtkCheckMenuItem *name_item = GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_by_name_item),
+ *size_item = GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_by_size_item);
+
+ // This could be avoided if we used GtkAction's
+ if (!gtk_check_menu_item_get_active (item) &&
+ !gtk_check_menu_item_get_active (name_item) &&
+ !gtk_check_menu_item_get_active (size_item))
+ {
+ gtk_check_menu_item_set_active (item, TRUE);
+ return;
+ }
+
+ if (gtk_check_menu_item_get_active (item))
+ {
+ gtk_check_menu_item_set_active (name_item, FALSE);
+ gtk_check_menu_item_set_active (size_item, FALSE);
+
+ impl->sort_column = MODEL_COL_MTIME;
+ set_sort_column (impl);
+ }
+}
+
+/* Callback used when "Ascending" menu item is toggled */
+static void
+sort_ascending_toggled_cb (GtkCheckMenuItem *item,
+ GtkFileChooserDefault *impl)
+{
+ GtkCheckMenuItem *desc_item = GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_descending_item);
+
+ // This could be avoided if we used GtkAction's
+ if (!gtk_check_menu_item_get_active (item) &&
+ !gtk_check_menu_item_get_active (desc_item))
+ {
+ gtk_check_menu_item_set_active (item, TRUE);
+ return;
+ }
+
+ if (gtk_check_menu_item_get_active (item))
+ {
+ gtk_check_menu_item_set_active (desc_item, FALSE);
+
+ // The sort column is explicitly set to mtime for the recent model
+ // This prevents it from switching when changing sort order
+ if (impl->view_mode == VIEW_MODE_ICON && impl->current_model == GTK_TREE_MODEL (impl->recent_model))
+ gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (impl->current_model), &impl->sort_column, NULL);
+
+ impl->sort_order = GTK_SORT_ASCENDING;
+ set_sort_column (impl);
+ }
+}
+
+/* Callback used when "Descending" menu item is toggled */
+static void
+sort_descending_toggled_cb (GtkCheckMenuItem *item,
+ GtkFileChooserDefault *impl)
+{
+ GtkCheckMenuItem *asc_item = GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_ascending_item);
+
+ // This could be avoided if we used GtkAction's
+ if (!gtk_check_menu_item_get_active (item) &&
+ !gtk_check_menu_item_get_active (asc_item))
+ {
+ gtk_check_menu_item_set_active (item, TRUE);
+ return;
+ }
+
+ if (gtk_check_menu_item_get_active (item))
+ {
+ gtk_check_menu_item_set_active (asc_item, FALSE);
+
+ // The sort column is explicitly set to mtime for the recent model
+ // This prevents it from switching when changing sort order
+ if (impl->view_mode == VIEW_MODE_ICON && impl->current_model == GTK_TREE_MODEL (impl->recent_model))
+ gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (impl->current_model), &impl->sort_column, NULL);
+
+ impl->sort_order = GTK_SORT_DESCENDING;
+ set_sort_column (impl);
+ }
+}
+
/* Shows an error dialog about not being able to select a dragged file */
static void
error_selecting_dragged_file_dialog (GtkFileChooserDefault *impl,
@@ -3928,9 +4164,9 @@ file_list_drag_data_received_get_info_cb (GCancellable *cancellable,
gtk_file_chooser_default_unselect_all (chooser);
gtk_file_chooser_default_select_file (chooser, data->file, &error);
if (error)
- error_selecting_dragged_file_dialog (data->impl, data->file, error);
+ error_selecting_dragged_file_dialog (data->impl, data->file, error);
else
- browse_files_center_selected_row (data->impl);
+ browse_files_center_selected_row (data->impl);
}
if (data->impl->select_multiple)
@@ -4034,7 +4270,7 @@ file_list_build_popup_menu (GtkFileChooserDefault *impl)
impl->browse_files_popup_menu = gtk_menu_new ();
gtk_menu_attach_to_widget (GTK_MENU (impl->browse_files_popup_menu),
- impl->browse_files_tree_view,
+ impl->browse_files_current_view,
popup_menu_detach_cb);
item = gtk_image_menu_item_new_with_mnemonic (_("_Add to Bookmarks"));
@@ -4057,12 +4293,72 @@ file_list_build_popup_menu (GtkFileChooserDefault *impl)
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
- item = gtk_check_menu_item_new_with_mnemonic (_("Show _Size Column"));
- impl->browse_files_popup_menu_size_column_item = item;
- g_signal_connect (item, "toggled",
- G_CALLBACK (show_size_column_toggled_cb), impl);
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
+ if (impl->view_mode == VIEW_MODE_LIST)
+ {
+ item = gtk_check_menu_item_new_with_mnemonic (_("Show _Size Column"));
+ impl->browse_files_popup_menu_size_column_item = item;
+ g_signal_connect (item, "toggled",
+ G_CALLBACK (show_size_column_toggled_cb), impl);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
+ }
+ else if (impl->view_mode == VIEW_MODE_ICON)
+ {
+ GtkWidget *menu, *subitem;
+
+ item = gtk_menu_item_new_with_label (_("Arrange Items"));
+ menu = gtk_menu_new ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
+
+ subitem = gtk_check_menu_item_new_with_mnemonic (_("Sort by _Name"));
+ impl->browse_files_popup_menu_sort_by_name_item = subitem;
+ gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (subitem), TRUE);
+ g_signal_connect (subitem, "toggled",
+ G_CALLBACK (sort_by_name_toggled_cb), impl);
+ gtk_widget_show (subitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), subitem);
+
+ subitem = gtk_check_menu_item_new_with_mnemonic (_("Sort by _Size"));
+ impl->browse_files_popup_menu_sort_by_size_item = subitem;
+ gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (subitem), TRUE);
+ g_signal_connect (subitem, "toggled",
+ G_CALLBACK (sort_by_size_toggled_cb), impl);
+ gtk_widget_show (subitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), subitem);
+
+ subitem = gtk_check_menu_item_new_with_mnemonic (_("Sort by Modification _Date"));
+ impl->browse_files_popup_menu_sort_by_mtime_item = subitem;
+ gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (subitem), TRUE);
+ g_signal_connect (subitem, "toggled",
+ G_CALLBACK (sort_by_mtime_toggled_cb), impl);
+ gtk_widget_show (subitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), subitem);
+
+ subitem = gtk_separator_menu_item_new ();
+ gtk_widget_show (subitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), subitem);
+
+ subitem = gtk_check_menu_item_new_with_mnemonic (_("_Ascending"));
+ impl->browse_files_popup_menu_sort_ascending_item = subitem;
+ gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (subitem), TRUE);
+ g_signal_connect (subitem, "toggled",
+ G_CALLBACK (sort_ascending_toggled_cb), impl);
+ gtk_widget_show (subitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), subitem);
+
+ subitem = gtk_check_menu_item_new_with_mnemonic (_("_Descending"));
+ impl->browse_files_popup_menu_sort_descending_item = subitem;
+ gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (subitem), TRUE);
+ g_signal_connect (subitem, "toggled",
+ G_CALLBACK (sort_descending_toggled_cb), impl);
+ gtk_widget_show (subitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), subitem);
+
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
+ }
+ else
+ g_assert_not_reached ();
bookmarks_check_add_sensitivity (impl);
}
@@ -4087,13 +4383,61 @@ file_list_update_popup_menu (GtkFileChooserDefault *impl)
g_signal_handlers_unblock_by_func (impl->browse_files_popup_menu_hidden_files_item,
G_CALLBACK (show_hidden_toggled_cb), impl);
- /* 'Show Size Column' */
- g_signal_handlers_block_by_func (impl->browse_files_popup_menu_size_column_item,
- G_CALLBACK (show_size_column_toggled_cb), impl);
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_size_column_item),
- impl->show_size_column);
- g_signal_handlers_unblock_by_func (impl->browse_files_popup_menu_size_column_item,
- G_CALLBACK (show_size_column_toggled_cb), impl);
+ if (impl->view_mode == VIEW_MODE_LIST)
+ {
+ /* 'Show Size Column' */
+ g_signal_handlers_block_by_func (impl->browse_files_popup_menu_size_column_item,
+ G_CALLBACK (show_size_column_toggled_cb), impl);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_size_column_item),
+ impl->show_size_column);
+ g_signal_handlers_unblock_by_func (impl->browse_files_popup_menu_size_column_item,
+ G_CALLBACK (show_size_column_toggled_cb), impl);
+ }
+ else if (impl->view_mode == VIEW_MODE_ICON)
+ {
+ gint column = impl->sort_column;
+ GtkSortType order = impl->sort_order;
+
+ if (impl->current_model == GTK_TREE_MODEL (impl->recent_model))
+ gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (impl->current_model), &column, &order);
+
+ g_signal_handlers_block_by_func (impl->browse_files_popup_menu_sort_by_name_item,
+ G_CALLBACK (sort_by_name_toggled_cb), impl);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_by_name_item),
+ column == MODEL_COL_NAME);
+ g_signal_handlers_unblock_by_func (impl->browse_files_popup_menu_sort_by_name_item,
+ G_CALLBACK (sort_by_name_toggled_cb), impl);
+
+ g_signal_handlers_block_by_func (impl->browse_files_popup_menu_sort_by_size_item,
+ G_CALLBACK (sort_by_size_toggled_cb), impl);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_by_size_item),
+ column == MODEL_COL_SIZE);
+ g_signal_handlers_unblock_by_func (impl->browse_files_popup_menu_sort_by_size_item,
+ G_CALLBACK (sort_by_size_toggled_cb), impl);
+
+ g_signal_handlers_block_by_func (impl->browse_files_popup_menu_sort_by_mtime_item,
+ G_CALLBACK (sort_by_mtime_toggled_cb), impl);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_by_mtime_item),
+ column == MODEL_COL_MTIME);
+ g_signal_handlers_unblock_by_func (impl->browse_files_popup_menu_sort_by_mtime_item,
+ G_CALLBACK (sort_by_mtime_toggled_cb), impl);
+
+ g_signal_handlers_block_by_func (impl->browse_files_popup_menu_sort_ascending_item,
+ G_CALLBACK (sort_ascending_toggled_cb), impl);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_ascending_item),
+ order == GTK_SORT_ASCENDING);
+ g_signal_handlers_unblock_by_func (impl->browse_files_popup_menu_sort_ascending_item,
+ G_CALLBACK (sort_ascending_toggled_cb), impl);
+
+ g_signal_handlers_block_by_func (impl->browse_files_popup_menu_sort_descending_item,
+ G_CALLBACK (sort_descending_toggled_cb), impl);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_sort_descending_item),
+ order == GTK_SORT_DESCENDING);
+ g_signal_handlers_unblock_by_func (impl->browse_files_popup_menu_sort_descending_item,
+ G_CALLBACK (sort_descending_toggled_cb), impl);
+ }
+ else
+ g_assert_not_reached ();
}
static void
@@ -4141,7 +4485,7 @@ file_list_popup_menu (GtkFileChooserDefault *impl,
{
gtk_menu_popup (GTK_MENU (impl->browse_files_popup_menu),
NULL, NULL,
- popup_position_func, impl->browse_files_tree_view,
+ popup_position_func, impl->browse_files_current_view,
0, GDK_CURRENT_TIME);
gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->browse_files_popup_menu),
FALSE);
@@ -4175,28 +4519,25 @@ list_button_press_event_cb (GtkWidget *widget,
return FALSE;
in_press = TRUE;
- gtk_widget_event (impl->browse_files_tree_view, (GdkEvent *) event);
+ gtk_widget_event (widget, (GdkEvent *) event);
in_press = FALSE;
file_list_popup_menu (impl, event);
return TRUE;
}
-typedef struct {
- OperationMode operation_mode;
- gint general_column;
- gint model_column;
-} ColumnMap;
-
/* Sets the sort column IDs for the file list; needs to be done whenever we
* change the model on the treeview.
*/
static void
file_list_set_sort_column_ids (GtkFileChooserDefault *impl)
{
- gtk_tree_view_column_set_sort_column_id (impl->list_name_column, MODEL_COL_NAME);
- gtk_tree_view_column_set_sort_column_id (impl->list_mtime_column, MODEL_COL_MTIME);
- gtk_tree_view_column_set_sort_column_id (impl->list_size_column, MODEL_COL_SIZE);
+ if (impl->view_mode == VIEW_MODE_LIST)
+ {
+ gtk_tree_view_column_set_sort_column_id (impl->list_name_column, MODEL_COL_NAME);
+ gtk_tree_view_column_set_sort_column_id (impl->list_mtime_column, MODEL_COL_MTIME);
+ gtk_tree_view_column_set_sort_column_id (impl->list_size_column, MODEL_COL_SIZE);
+ }
}
static gboolean
@@ -4248,32 +4589,34 @@ file_list_query_tooltip_cb (GtkWidget *widget,
}
static void
-set_icon_cell_renderer_fixed_size (GtkFileChooserDefault *impl, GtkCellRenderer *renderer)
+set_icon_cell_renderer_fixed_size (GtkFileChooserDefault *impl,
+ GtkCellRenderer *renderer,
+ ViewMode view_mode)
{
+ int icon_size;
gint xpad, ypad;
+ if (view_mode == VIEW_MODE_LIST)
+ icon_size = impl->list_view_icon_size;
+ else if (view_mode == VIEW_MODE_ICON)
+ icon_size = impl->icon_view_icon_size;
+ else
+ g_assert_not_reached ();
+
gtk_cell_renderer_get_padding (renderer, &xpad, &ypad);
gtk_cell_renderer_set_fixed_size (renderer,
- xpad * 2 + impl->icon_size,
- ypad * 2 + impl->icon_size);
+ xpad * 2 + icon_size,
+ ypad * 2 + icon_size);
}
-/* Creates the widgets for the file list */
+/* Creates the list view */
static GtkWidget *
-create_file_list (GtkFileChooserDefault *impl)
+create_browse_files_tree_view (GtkFileChooserDefault *impl)
{
- GtkWidget *swin;
GtkTreeSelection *selection;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
- /* Scrolled window */
- swin = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin),
- GTK_SHADOW_IN);
-
/* Tree/list view */
impl->browse_files_tree_view = gtk_tree_view_new ();
@@ -4284,7 +4627,6 @@ create_file_list (GtkFileChooserDefault *impl)
atk_object_set_name (gtk_widget_get_accessible (impl->browse_files_tree_view), _("Files"));
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (impl->browse_files_tree_view), TRUE);
- gtk_container_add (GTK_CONTAINER (swin), impl->browse_files_tree_view);
gtk_drag_dest_set (impl->browse_files_tree_view,
GTK_DEST_DEFAULT_ALL,
@@ -4336,7 +4678,7 @@ create_file_list (GtkFileChooserDefault *impl)
renderer = gtk_cell_renderer_pixbuf_new ();
/* We set a fixed size so that we get an empty slot even if no icons are loaded yet */
- set_icon_cell_renderer_fixed_size (impl, renderer);
+ set_icon_cell_renderer_fixed_size (impl, renderer, VIEW_MODE_LIST);
gtk_tree_view_column_pack_start (impl->list_name_column, renderer, FALSE);
impl->list_name_renderer = gtk_cell_renderer_text_new ();
@@ -4379,6 +4721,101 @@ create_file_list (GtkFileChooserDefault *impl)
file_list_set_sort_column_ids (impl);
update_cell_renderer_attributes (impl);
+ return impl->browse_files_tree_view;
+}
+
+/* Creates icon view (alternative for the list view) */
+static GtkWidget *
+create_browse_files_icon_view (GtkFileChooserDefault *impl)
+{
+ impl->browse_files_icon_view = gtk_icon_view_new ();
+
+ g_object_set_data (G_OBJECT (impl->browse_files_icon_view), I_("GtkFileChooserDefault"), impl);
+ gtk_icon_view_set_item_padding (GTK_ICON_VIEW (impl->browse_files_icon_view), 0);
+
+ g_signal_connect (impl->browse_files_icon_view, "item-activated",
+ G_CALLBACK (icon_item_activated), impl);
+ g_signal_connect (impl->browse_files_icon_view, "key-press-event",
+ G_CALLBACK (browse_files_key_press_event_cb), impl);
+ g_signal_connect (impl->browse_files_icon_view, "selection-changed",
+ G_CALLBACK (list_selection_changed), impl);
+ g_signal_connect (impl->browse_files_icon_view, "popup-menu",
+ G_CALLBACK (list_popup_menu_cb), impl);
+ g_signal_connect (impl->browse_files_icon_view, "button-press-event",
+ G_CALLBACK (list_button_press_event_cb), impl);
+
+ gtk_drag_dest_set (impl->browse_files_icon_view,
+ GTK_DEST_DEFAULT_ALL,
+ NULL, 0,
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+ gtk_drag_dest_add_uri_targets (impl->browse_files_icon_view);
+ g_signal_connect (impl->browse_files_icon_view, "drag-data-received",
+ G_CALLBACK (file_list_drag_data_received_cb), impl);
+ g_signal_connect (impl->browse_files_icon_view, "drag-drop",
+ G_CALLBACK (file_list_drag_drop_cb), impl);
+ g_signal_connect (impl->browse_files_icon_view, "drag-motion",
+ G_CALLBACK (file_list_drag_motion_cb), impl);
+ gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW (impl->browse_files_icon_view),
+ GDK_BUTTON1_MASK,
+ NULL, 0,
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+ gtk_drag_source_add_uri_targets (impl->browse_files_icon_view);
+
+ impl->list_icon_renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (G_OBJECT (impl->list_icon_renderer),
+ "ypad", 3u,
+ NULL);
+
+ set_icon_cell_renderer_fixed_size (impl, GTK_CELL_RENDERER (impl->list_icon_renderer),
+ VIEW_MODE_ICON);
+
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (impl->browse_files_icon_view),
+ impl->list_icon_renderer, TRUE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (impl->browse_files_icon_view),
+ impl->list_icon_renderer, "pixbuf", MODEL_COL_ICON_PIXBUF);
+
+ impl->list_name_renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT (impl->list_name_renderer),
+ "alignment", PANGO_ALIGN_CENTER,
+ "wrap-mode", PANGO_WRAP_WORD_CHAR,
+ "wrap-width", ICON_VIEW_ITEM_WIDTH - 6,
+ "yalign", 0.0f,
+ NULL);
+ gtk_cell_renderer_set_fixed_size (GTK_CELL_RENDERER (impl->list_name_renderer), ICON_VIEW_ITEM_WIDTH, -1);
+
+ g_signal_connect (impl->list_name_renderer, "edited",
+ G_CALLBACK (renderer_edited_cb), impl);
+ g_signal_connect (impl->list_name_renderer, "editing-started",
+ G_CALLBACK (renderer_editing_started_cb), impl);
+ g_signal_connect (impl->list_name_renderer, "editing-canceled",
+ G_CALLBACK (renderer_editing_canceled_cb), impl);
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (impl->browse_files_icon_view),
+ impl->list_name_renderer, TRUE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (impl->browse_files_icon_view),
+ impl->list_name_renderer, "text", MODEL_COL_NAME);
+
+ return impl->browse_files_icon_view;
+}
+
+/* Creates the widgets for the file list */
+static GtkWidget *
+create_file_list (GtkFileChooserDefault *impl)
+{
+ GtkWidget *swin;
+
+ /* Scrolled window */
+ swin = gtk_scrolled_window_new (NULL, NULL);
+ impl->browse_files_scrolled_window = swin;
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin),
+ GTK_SHADOW_IN);
+
+ /* Initially VIEW_MODE_LIST is used, settings_load may change this later. */
+ create_browse_files_tree_view (impl);
+ impl->browse_files_current_view = impl->browse_files_tree_view;
+ gtk_container_add (GTK_CONTAINER (swin), impl->browse_files_tree_view);
+
gtk_widget_show_all (swin);
return swin;
@@ -4601,7 +5038,7 @@ location_mode_set (GtkFileChooserDefault *impl,
location_switch_to_path_bar (impl);
if (switch_to_file_list)
- gtk_widget_grab_focus (impl->browse_files_tree_view);
+ gtk_widget_grab_focus (impl->browse_files_current_view);
break;
@@ -4661,6 +5098,108 @@ location_toggle_popup_handler (GtkFileChooserDefault *impl)
}
}
+static void
+view_mode_set (GtkFileChooserDefault *impl, ViewMode view_mode)
+{
+ GtkWidget *old_view = NULL;
+ ViewMode old_view_mode = impl->view_mode;
+
+ if (old_view_mode == view_mode)
+ return;
+
+ impl->view_mode = view_mode;
+ gtk_combo_box_set_active (GTK_COMBO_BOX (impl->view_mode_combo_box),
+ view_mode);
+
+ /* Creating the target view */
+ if (view_mode == VIEW_MODE_ICON)
+ {
+ create_browse_files_icon_view (impl);
+ impl->browse_files_current_view = impl->browse_files_icon_view;
+ old_view = impl->browse_files_tree_view;
+ }
+ else if (view_mode == VIEW_MODE_LIST)
+ {
+ create_browse_files_tree_view (impl);
+ impl->browse_files_current_view = impl->browse_files_tree_view;
+ old_view = impl->browse_files_icon_view;
+ }
+ else
+ g_assert_not_reached ();
+
+ /* Set model and selection */
+ current_view_set_file_model (impl, impl->current_model);
+ current_view_set_select_multiple (impl, impl->select_multiple);
+ copy_old_selection_to_current_view (impl, old_view_mode);
+
+ /* Destroy the old view */
+ if (view_mode == VIEW_MODE_ICON)
+ {
+ impl->browse_files_tree_view = NULL;
+ impl->list_name_column = NULL;
+ impl->list_mtime_column = NULL;
+ impl->list_size_column = NULL;
+ gtk_widget_show (impl->icon_view_scale_hbox);
+ }
+ else if (view_mode == VIEW_MODE_LIST)
+ {
+ impl->browse_files_icon_view = NULL;
+ gtk_widget_hide (impl->icon_view_scale_hbox);
+ }
+ else
+ g_assert_not_reached ();
+
+ if (impl->browse_files_popup_menu)
+ gtk_menu_detach (GTK_MENU (impl->browse_files_popup_menu));
+
+ gtk_widget_destroy (old_view);
+
+ /* Display the new view */
+ gtk_container_add (GTK_CONTAINER (impl->browse_files_scrolled_window),
+ impl->browse_files_current_view);
+ gtk_widget_show (impl->browse_files_current_view);
+
+ browse_files_center_selected_row (impl);
+}
+
+/* Callback used when view mode combo box active item is changed */
+static void
+view_mode_combo_box_changed_cb (GtkComboBox *combo,
+ GtkFileChooserDefault *impl)
+{
+ ViewMode target = gtk_combo_box_get_active (combo);
+
+ view_mode_set (impl, target);
+}
+
+/* Callback used when the icon view scale is changed */
+static void
+icon_view_scale_value_changed_cb (GtkRange *range,
+ GtkFileChooserDefault *impl)
+{
+ gdouble value = gtk_range_get_value (range);
+ value = round (value / 16) * 16;
+
+ if (impl->icon_view_icon_size == (gint)value)
+ return;
+
+ impl->icon_view_icon_size = (gint)value;
+
+ if (impl->view_mode != VIEW_MODE_ICON)
+ return;
+
+ set_icon_cell_renderer_fixed_size (impl, impl->list_icon_renderer, VIEW_MODE_ICON);
+
+ if (impl->browse_files_model)
+ _gtk_file_system_model_clear_cache (impl->browse_files_model, MODEL_COL_ICON_PIXBUF);
+ if (impl->search_model)
+ _gtk_file_system_model_clear_cache (impl->search_model, MODEL_COL_ICON_PIXBUF);
+ if (impl->recent_model)
+ _gtk_file_system_model_clear_cache (impl->recent_model, MODEL_COL_ICON_PIXBUF);
+
+ gtk_widget_queue_resize (impl->browse_files_current_view);
+}
+
/* Callback used when one of the location mode buttons is toggled */
static void
location_button_toggled_cb (GtkToggleButton *toggle,
@@ -4685,6 +5224,53 @@ location_button_toggled_cb (GtkToggleButton *toggle,
location_mode_set (impl, new_mode, FALSE);
}
+/* Creates a combo box with two items: List View and Icon View. */
+static void
+view_mode_combo_box_create (GtkFileChooserDefault *impl)
+{
+ impl->view_mode_combo_box = gtk_combo_box_text_new ();
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(impl->view_mode_combo_box),
+ _("List View")); /* VIEW_MODE_LIST */
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(impl->view_mode_combo_box),
+ _("Icon View")); /* VIEW_MODE_ICON */
+ gtk_combo_box_set_active (GTK_COMBO_BOX(impl->view_mode_combo_box),
+ VIEW_MODE_LIST);
+
+ g_signal_connect (impl->view_mode_combo_box, "changed",
+ G_CALLBACK (view_mode_combo_box_changed_cb), impl);
+}
+
+/* Creates a hscale for the icon view. */
+static void
+icon_view_scale_create (GtkFileChooserDefault *impl)
+{
+ GtkObject *adj;
+
+ impl->icon_view_scale_hbox = gtk_hbox_new (FALSE, 12);
+
+ impl->icon_view_scale_zoom_out_icon = gtk_image_new_from_stock (GTK_STOCK_ZOOM_OUT, GTK_ICON_SIZE_BUTTON);
+ gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->icon_view_scale_zoom_out_icon);
+ gtk_box_pack_start (GTK_BOX (impl->icon_view_scale_hbox), impl->icon_view_scale_zoom_out_icon, FALSE, FALSE, 0);
+ gtk_widget_show (impl->icon_view_scale_zoom_out_icon);
+
+ adj = gtk_adjustment_new (32, 32, 256, 16, 16, 0);
+ impl->icon_view_scale = gtk_hscale_new (GTK_ADJUSTMENT (adj));
+ gtk_scale_set_draw_value (GTK_SCALE (impl->icon_view_scale), FALSE);
+ gtk_widget_set_size_request (impl->icon_view_scale, 100, -1);
+ gtk_box_pack_start (GTK_BOX (impl->icon_view_scale_hbox), impl->icon_view_scale, FALSE, FALSE, 0);
+ gtk_widget_show (impl->icon_view_scale);
+
+ impl->icon_view_scale_zoom_in_icon = gtk_image_new_from_stock (GTK_STOCK_ZOOM_IN, GTK_ICON_SIZE_BUTTON);
+ gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->icon_view_scale_zoom_in_icon);
+ gtk_box_pack_start (GTK_BOX (impl->icon_view_scale_hbox), impl->icon_view_scale_zoom_in_icon, FALSE, FALSE, 0);
+ gtk_widget_show (impl->icon_view_scale_zoom_in_icon);
+
+ g_signal_connect (impl->icon_view_scale, "value-changed",
+ G_CALLBACK (icon_view_scale_value_changed_cb), impl);
+
+}
+
+
/* Creates a toggle button for the location entry. */
static void
location_button_create (GtkFileChooserDefault *impl)
@@ -4804,6 +5390,10 @@ path_bar_widgets_create (GtkFileChooserDefault *impl)
impl->browse_path_bar_size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
gtk_size_group_set_ignore_hidden (impl->browse_path_bar_size_group, FALSE);
+ /* View mode combo box */
+ view_mode_combo_box_create (impl);
+ gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->view_mode_combo_box, FALSE, FALSE, 0);
+
/* Location button */
location_button_create (impl);
gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->location_button);
@@ -4825,6 +5415,10 @@ path_bar_widgets_create (GtkFileChooserDefault *impl)
/* Widgets for special modes (recently-used in Open mode, Search mode) */
special_mode_widgets_create (impl);
+ /* Icon view scale */
+ icon_view_scale_create (impl);
+ gtk_box_pack_end (GTK_BOX (impl->browse_path_bar_hbox), impl->icon_view_scale_hbox, FALSE, FALSE, 0);
+
/* Create Folder */
impl->browse_new_folder_button = gtk_button_new_with_mnemonic (_("Create Fo_lder"));
g_signal_connect (impl->browse_new_folder_button, "clicked",
@@ -5067,18 +5661,10 @@ set_select_multiple (GtkFileChooserDefault *impl,
gboolean select_multiple,
gboolean property_notify)
{
- GtkTreeSelection *selection;
- GtkSelectionMode mode;
-
if (select_multiple == impl->select_multiple)
return;
- mode = select_multiple ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_BROWSE;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- gtk_tree_selection_set_mode (selection, mode);
-
- gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (impl->browse_files_tree_view), select_multiple);
+ current_view_set_select_multiple (impl, select_multiple);
impl->select_multiple = select_multiple;
g_object_notify (G_OBJECT (impl), "select-multiple");
@@ -5186,27 +5772,27 @@ path_bar_update (GtkFileChooserDefault *impl)
break;
case OPERATION_MODE_RECENT:
- if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
- {
- GtkTreeSelection *selection;
- gboolean have_selected;
- GtkTreeIter iter;
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE && impl->view_mode == VIEW_MODE_LIST)
+ {
+ GtkTreeSelection *selection;
+ gboolean have_selected;
+ GtkTreeIter iter;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- /* Save mode means single-selection mode, so the following is valid */
- have_selected = gtk_tree_selection_get_selected (selection, NULL, &iter);
+ /* Save mode means single-selection mode, so the following is valid */
+ have_selected = gtk_tree_selection_get_selected (selection, NULL, &iter);
- if (have_selected)
- {
- mode = PATH_BAR_FOLDER_PATH;
- put_recent_folder_in_pathbar (impl, &iter);
- }
- else
- mode = PATH_BAR_SELECT_A_FOLDER;
- }
+ if (have_selected)
+ {
+ mode = PATH_BAR_FOLDER_PATH;
+ put_recent_folder_in_pathbar (impl, &iter);
+ }
+ else
+ mode = PATH_BAR_SELECT_A_FOLDER;
+ }
else
- mode = PATH_BAR_RECENTLY_USED;
+ mode = PATH_BAR_RECENTLY_USED;
break;
@@ -5396,6 +5982,12 @@ update_appearance (GtkFileChooserDefault *impl)
location_mode_set (impl, impl->location_mode, TRUE);
}
+ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ gtk_widget_show (impl->view_mode_combo_box);
+ else
+ gtk_widget_hide (impl->view_mode_combo_box);
+
if (impl->location_entry)
_gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
@@ -5405,7 +5997,7 @@ update_appearance (GtkFileChooserDefault *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 (impl->browse_files_tree_view);
+ gtk_widget_queue_draw (impl->browse_files_current_view);
emit_default_size_changed (impl);
}
@@ -5787,20 +6379,36 @@ change_icon_theme (GtkFileChooserDefault *impl)
settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
if (gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU, &width, &height))
- impl->icon_size = MAX (width, height);
+ impl->list_view_icon_size = MAX (width, height);
else
- impl->icon_size = FALLBACK_ICON_SIZE;
+ impl->list_view_icon_size = FALLBACK_LIST_VIEW_ICON_SIZE;
shortcuts_reload_icons (impl);
/* the first cell in the first column is the icon column, and we have a fixed size there */
- cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (
- gtk_tree_view_get_column (GTK_TREE_VIEW (impl->browse_files_tree_view), 0)));
- renderer = GTK_CELL_RENDERER (cells->data);
- set_icon_cell_renderer_fixed_size (impl, renderer);
- g_list_free (cells);
+ if (impl->view_mode == VIEW_MODE_LIST)
+ {
+ cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (
+ gtk_tree_view_get_column (GTK_TREE_VIEW (impl->browse_files_tree_view), 0)));
+ renderer = GTK_CELL_RENDERER (cells->data);
+ set_icon_cell_renderer_fixed_size (impl, renderer, VIEW_MODE_LIST);
+ g_list_free (cells);
+ }
if (impl->browse_files_model)
- _gtk_file_system_model_clear_cache (impl->browse_files_model, MODEL_COL_PIXBUF);
- gtk_widget_queue_resize (impl->browse_files_tree_view);
+ {
+ _gtk_file_system_model_clear_cache (impl->browse_files_model, MODEL_COL_LIST_PIXBUF);
+ _gtk_file_system_model_clear_cache (impl->browse_files_model, MODEL_COL_ICON_PIXBUF);
+ }
+ if (impl->search_model)
+ {
+ _gtk_file_system_model_clear_cache (impl->search_model, MODEL_COL_LIST_PIXBUF);
+ _gtk_file_system_model_clear_cache (impl->search_model, MODEL_COL_ICON_PIXBUF);
+ }
+ if (impl->recent_model)
+ {
+ _gtk_file_system_model_clear_cache (impl->recent_model, MODEL_COL_LIST_PIXBUF);
+ _gtk_file_system_model_clear_cache (impl->recent_model, MODEL_COL_ICON_PIXBUF);
+ }
+ gtk_widget_queue_resize (impl->browse_files_current_view);
profile_end ("end", NULL);
}
@@ -5900,7 +6508,7 @@ set_sort_column (GtkFileChooserDefault *impl)
{
GtkTreeSortable *sortable;
- sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view)));
+ sortable = GTK_TREE_SORTABLE (impl->current_model);
/* can happen when we're still populating the model */
if (sortable == NULL)
return;
@@ -5915,15 +6523,18 @@ settings_load (GtkFileChooserDefault *impl)
{
GtkFileChooserSettings *settings;
LocationMode location_mode;
+ ViewMode view_mode;
gboolean show_hidden;
gboolean show_size_column;
- gint sort_column;
+ gint sort_column, icon_view_scale;
GtkSortType sort_order;
StartupMode startup_mode;
settings = _gtk_file_chooser_settings_new ();
location_mode = _gtk_file_chooser_settings_get_location_mode (settings);
+ view_mode = _gtk_file_chooser_settings_get_view_mode (settings);
+ icon_view_scale = _gtk_file_chooser_settings_get_icon_view_scale (settings);
show_hidden = _gtk_file_chooser_settings_get_show_hidden (settings);
show_size_column = _gtk_file_chooser_settings_get_show_size_column (settings);
sort_column = _gtk_file_chooser_settings_get_sort_column (settings);
@@ -5933,11 +6544,16 @@ settings_load (GtkFileChooserDefault *impl)
g_object_unref (settings);
location_mode_set (impl, location_mode, TRUE);
+ view_mode_set (impl, view_mode);
+
+ gtk_range_set_value (GTK_RANGE (impl->icon_view_scale), icon_view_scale);
+ impl->icon_view_icon_size = icon_view_scale;
gtk_file_chooser_set_show_hidden (GTK_FILE_CHOOSER (impl), show_hidden);
impl->show_size_column = show_size_column;
- gtk_tree_view_column_set_visible (impl->list_size_column, show_size_column);
+ if (impl->list_size_column)
+ gtk_tree_view_column_set_visible (impl->list_size_column, show_size_column);
impl->sort_column = sort_column;
impl->sort_order = sort_order;
@@ -5976,6 +6592,8 @@ settings_save (GtkFileChooserDefault *impl)
/* All the other state */
_gtk_file_chooser_settings_set_location_mode (settings, impl->location_mode);
+ _gtk_file_chooser_settings_set_view_mode (settings, impl->view_mode);
+ _gtk_file_chooser_settings_set_icon_view_scale (settings, impl->icon_view_icon_size);
_gtk_file_chooser_settings_set_show_hidden (settings, gtk_file_chooser_get_show_hidden (GTK_FILE_CHOOSER (impl)));
_gtk_file_chooser_settings_set_show_size_column (settings, impl->show_size_column);
_gtk_file_chooser_settings_set_sort_column (settings, impl->sort_column);
@@ -6213,12 +6831,16 @@ load_set_model (GtkFileChooserDefault *impl)
g_assert (impl->browse_files_model != NULL);
profile_msg (" gtk_tree_view_set_model start", NULL);
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
- GTK_TREE_MODEL (impl->browse_files_model));
- gtk_tree_view_columns_autosize (GTK_TREE_VIEW (impl->browse_files_tree_view));
- gtk_tree_view_set_search_column (GTK_TREE_VIEW (impl->browse_files_tree_view),
- MODEL_COL_NAME);
- file_list_set_sort_column_ids (impl);
+ current_view_set_file_model (impl, GTK_TREE_MODEL (impl->browse_files_model));
+
+ if (impl->view_mode == VIEW_MODE_LIST)
+ {
+ gtk_tree_view_columns_autosize (GTK_TREE_VIEW (impl->browse_files_tree_view));
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (impl->browse_files_tree_view),
+ MODEL_COL_NAME);
+ file_list_set_sort_column_ids (impl);
+ }
+
set_sort_column (impl);
profile_msg (" gtk_tree_view_set_model end", NULL);
impl->list_sort_ascending = TRUE;
@@ -6290,7 +6912,7 @@ browse_files_select_first_row (GtkFileChooserDefault *impl)
GtkTreeIter dummy_iter;
GtkTreeModel *tree_model;
- tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view));
+ tree_model = impl->current_model;
if (!tree_model)
return;
@@ -6299,7 +6921,7 @@ browse_files_select_first_row (GtkFileChooserDefault *impl)
/* If the list is empty, do nothing. */
if (gtk_tree_model_get_iter (tree_model, &dummy_iter, path))
- gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view), path, NULL, FALSE);
+ current_view_set_cursor (impl, path);
gtk_tree_path_free (path);
}
@@ -6310,7 +6932,7 @@ struct center_selected_row_closure {
};
/* Callback used from gtk_tree_selection_selected_foreach(); centers the
- * selected row in the tree view.
+ * selected row in the current view.
*/
static void
center_selected_row_foreach_cb (GtkTreeModel *model,
@@ -6324,7 +6946,13 @@ center_selected_row_foreach_cb (GtkTreeModel *model,
if (closure->already_centered)
return;
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (closure->impl->browse_files_tree_view), path, NULL, TRUE, 0.5, 0.0);
+ if (closure->impl->view_mode == VIEW_MODE_LIST)
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (closure->impl->browse_files_tree_view), path, NULL, TRUE, 0.5, 0.0);
+ else if (closure->impl->view_mode == VIEW_MODE_ICON)
+ gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (closure->impl->browse_files_icon_view), path, TRUE, 0.5, 0.0);
+ else
+ g_assert_not_reached ();
+
closure->already_centered = TRUE;
}
@@ -6333,20 +6961,17 @@ static void
browse_files_center_selected_row (GtkFileChooserDefault *impl)
{
struct center_selected_row_closure closure;
- GtkTreeSelection *selection;
closure.impl = impl;
closure.already_centered = FALSE;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->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
show_and_select_files (GtkFileChooserDefault *impl,
GSList *files)
{
- GtkTreeSelection *selection;
GtkFileSystemModel *fsmodel;
gboolean enabled_hidden, removed_filters;
gboolean selected_a_file;
@@ -6355,8 +6980,7 @@ show_and_select_files (GtkFileChooserDefault *impl,
g_assert (impl->load_state == LOAD_FINISHED);
g_assert (impl->browse_files_model != NULL);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- fsmodel = GTK_FILE_SYSTEM_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view)));
+ fsmodel = GTK_FILE_SYSTEM_MODEL (impl->current_model);
g_assert (fsmodel == impl->browse_files_model);
@@ -6412,11 +7036,10 @@ show_and_select_files (GtkFileChooserDefault *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 (impl->browse_files_tree_view),
- path, NULL, FALSE);
+ current_view_set_cursor (impl, path);
gtk_tree_path_free (path);
selected_a_file = TRUE;
@@ -6452,7 +7075,7 @@ pending_select_files_process (GtkFileChooserDefault *impl)
*/
if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN &&
gtk_widget_get_mapped (GTK_WIDGET (impl)))
- browse_files_select_first_row (impl);
+ browse_files_select_first_row (impl);
}
g_assert (impl->pending_select_files == NULL);
@@ -6531,12 +7154,14 @@ stop_loading_and_clear_list_model (GtkFileChooserDefault *impl,
if (impl->browse_files_model)
{
+ if (impl->current_model == GTK_TREE_MODEL (impl->browse_files_model))
+ impl->current_model = NULL;
g_object_unref (impl->browse_files_model);
impl->browse_files_model = NULL;
}
if (remove_from_treeview)
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL);
+ current_view_set_file_model (impl, NULL);
}
static char *
@@ -6690,6 +7315,17 @@ file_system_model_got_thumbnail (GObject *object, GAsyncResult *res, gpointer da
GDK_THREADS_LEAVE ();
}
+static gboolean
+get_visible_range (GtkTreePath **start, GtkTreePath **end,
+ GtkFileChooserDefault *impl)
+{
+ if (impl->view_mode == VIEW_MODE_LIST)
+ return gtk_tree_view_get_visible_range (GTK_TREE_VIEW (impl->browse_files_tree_view), start, end);
+ if (impl->view_mode == VIEW_MODE_ICON)
+ return gtk_icon_view_get_visible_range (GTK_ICON_VIEW (impl->browse_files_icon_view), start, end);
+ g_assert_not_reached ();
+}
+
static gboolean
file_system_model_set (GtkFileSystemModel *model,
GFile *file,
@@ -6747,38 +7383,59 @@ file_system_model_set (GtkFileSystemModel *model,
else
g_value_set_boolean (value, TRUE);
break;
- case MODEL_COL_PIXBUF:
+ case MODEL_COL_LIST_PIXBUF:
+ case MODEL_COL_ICON_PIXBUF:
if (info)
{
+ GtkTreeModel *tree_model;
+ GtkTreePath *path, *start, *end;
+ GtkTreeIter iter;
+ gboolean file_visible;
+
+ /* not loading icon view's icon in the list view */
+ if (column == MODEL_COL_ICON_PIXBUF && impl->view_mode == VIEW_MODE_LIST)
+ return FALSE;
+
+ tree_model = impl->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))
{
- g_value_take_object (value, _gtk_file_info_render_icon (info, GTK_WIDGET (impl), impl->icon_size));
+ gint icon_size;
+
+ if (column == MODEL_COL_ICON_PIXBUF)
+ icon_size = impl->icon_view_icon_size;
+ else
+ icon_size = impl->list_view_icon_size;
+
+ g_value_take_object (value, _gtk_file_info_render_icon (info, GTK_WIDGET (impl), icon_size));
+ return TRUE;
}
- else
- {
- GtkTreeModel *tree_model;
- GtkTreePath *path, *start, *end;
- GtkTreeIter iter;
- if (impl->browse_files_tree_view == NULL ||
- g_file_info_has_attribute (info, "filechooser::queried"))
- return FALSE;
+ if (!get_visible_range (&start, &end, impl))
+ return FALSE;
- tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view));
- if (tree_model != GTK_TREE_MODEL (model))
- return FALSE;
+ if (!_gtk_file_system_model_get_iter_for_file (model,
+ &iter,
+ file))
+ g_assert_not_reached ();
- if (!_gtk_file_system_model_get_iter_for_file (model,
- &iter,
- file))
- g_assert_not_reached ();
- if (!gtk_tree_view_get_visible_range (GTK_TREE_VIEW (impl->browse_files_tree_view), &start, &end))
- return FALSE;
- path = gtk_tree_model_get_path (tree_model, &iter);
- if (gtk_tree_path_compare (start, path) != 1 &&
- gtk_tree_path_compare (path, end) != 1)
+ 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::queried", TRUE);
+ 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 ","
@@ -6789,14 +7446,23 @@ file_system_model_set (GtkFileSystemModel *model,
file_system_model_got_thumbnail,
model);
}
- gtk_tree_path_free (path);
- gtk_tree_path_free (start);
- gtk_tree_path_free (end);
- return FALSE;
}
+ return FALSE;
}
else
- g_value_set_object (value, NULL);
+ {
+ if (column == MODEL_COL_ICON_PIXBUF)
+ {
+ g_value_take_object (value,
+ gtk_icon_theme_load_icon (gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl))),
+ "inode-directory",
+ impl->icon_view_icon_size,
+ 0,
+ NULL));
+ }
+ 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);
@@ -6922,7 +7588,6 @@ update_chooser_entry_selected_foreach (GtkTreeModel *model,
static void
update_chooser_entry (GtkFileChooserDefault *impl)
{
- GtkTreeSelection *selection;
struct update_chooser_entry_selected_foreach_closure closure;
/* no need to update the file chooser's entry if there's no entry */
@@ -6939,9 +7604,8 @@ update_chooser_entry (GtkFileChooserDefault *impl)
g_assert (impl->location_entry != NULL);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->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)
{
@@ -7413,7 +8077,6 @@ gtk_file_chooser_default_unselect_file (GtkFileChooser *chooser,
GFile *file)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
- GtkTreeView *tree_view = GTK_TREE_VIEW (impl->browse_files_tree_view);
GtkTreeIter iter;
if (!impl->browse_files_model)
@@ -7424,8 +8087,7 @@ gtk_file_chooser_default_unselect_file (GtkFileChooser *chooser,
file))
return;
- gtk_tree_selection_unselect_iter (gtk_tree_view_get_selection (tree_view),
- &iter);
+ current_selection_unselect_iter (impl, &iter);
}
static gboolean
@@ -7435,12 +8097,9 @@ maybe_select (GtkTreeModel *model,
gpointer data)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
- GtkTreeSelection *selection;
gboolean is_sensitive;
gboolean is_folder;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
-
gtk_tree_model_get (model, iter,
MODEL_COL_IS_FOLDER, &is_folder,
MODEL_COL_IS_SENSITIVE, &is_sensitive,
@@ -7449,9 +8108,9 @@ maybe_select (GtkTreeModel *model,
if (is_sensitive &&
((is_folder && impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ||
(!is_folder && impl->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;
}
@@ -7466,8 +8125,15 @@ gtk_file_chooser_default_select_all (GtkFileChooser *chooser)
{
GtkTreeSelection *selection;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- gtk_tree_selection_select_all (selection);
+ if (impl->view_mode == VIEW_MODE_LIST)
+ {
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+ gtk_tree_selection_select_all (selection);
+ }
+ else if (impl->view_mode == VIEW_MODE_ICON)
+ gtk_icon_view_select_all (GTK_ICON_VIEW (impl->browse_files_icon_view));
+ else
+ g_assert_not_reached ();
return;
}
@@ -7480,9 +8146,8 @@ static void
gtk_file_chooser_default_unselect_all (GtkFileChooser *chooser)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
- GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- gtk_tree_selection_unselect_all (selection);
+ current_selection_unselect_all (impl);
pending_select_files_free (impl);
}
@@ -7635,15 +8300,13 @@ gtk_file_chooser_default_get_files (GtkFileChooser *chooser)
current_focus = NULL;
file_list_seen = FALSE;
- if (current_focus == impl->browse_files_tree_view)
+ if (current_focus == impl->browse_files_current_view)
{
- GtkTreeSelection *selection;
-
file_list:
file_list_seen = TRUE;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->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:
*
@@ -7683,7 +8346,7 @@ gtk_file_chooser_default_get_files (GtkFileChooser *chooser)
else
return NULL;
}
- else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view)
+ else if (impl->toplevel_last_focus_widget == impl->browse_files_current_view)
goto file_list;
else if (impl->location_entry && impl->toplevel_last_focus_widget == impl->location_entry)
goto file_entry;
@@ -8147,7 +8810,6 @@ switch_folder_foreach_cb (GtkTreeModel *model,
static void
switch_to_selected_folder (GtkFileChooserDefault *impl)
{
- GtkTreeSelection *selection;
struct switch_folder_closure closure;
/* We do this with foreach() rather than get_selected() as we may be in
@@ -8158,8 +8820,7 @@ switch_to_selected_folder (GtkFileChooserDefault *impl)
closure.file = NULL;
closure.num_selected = 0;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->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);
@@ -8178,14 +8839,28 @@ get_selected_file_info_from_file_list (GtkFileChooserDefault *impl,
GFileInfo *info;
g_assert (!impl->select_multiple);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
+
+ if (impl->view_mode == VIEW_MODE_LIST)
+ {
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+ if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
+ {
+ *had_selection = FALSE;
+ return NULL;
+ }
+ *had_selection = TRUE;
+ }
+ else if (impl->view_mode == VIEW_MODE_ICON)
{
- *had_selection = FALSE;
- return NULL;
+ if (!get_selected_tree_iter_from_icon_view (impl, &iter))
+ {
+ *had_selection = FALSE;
+ return NULL;
+ }
+ *had_selection = TRUE;
}
-
- *had_selection = TRUE;
+ else
+ g_assert_not_reached ();
info = _gtk_file_system_model_get_info (impl->browse_files_model, &iter);
return info;
@@ -8561,7 +9236,7 @@ file_exists_get_info_cb (GCancellable *cancellable,
}
else
{
- g_assert_not_reached();
+ g_assert_not_reached ();
}
if (needs_parent_check)
@@ -8667,7 +9342,7 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
current_focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
- if (current_focus == impl->browse_files_tree_view)
+ if (current_focus == impl->browse_files_current_view)
{
/* The following array encodes what we do based on the impl->action and the
* number of files selected.
@@ -8877,7 +9552,7 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
g_object_unref (file);
}
- else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view)
+ else if (impl->toplevel_last_focus_widget == impl->browse_files_current_view)
{
/* The focus is on a dialog's action area button, *and* the widget that
* was focused immediately before it is the file list.
@@ -8926,7 +9601,7 @@ gtk_file_chooser_default_initial_focus (GtkFileChooserEmbed *chooser_embed)
{
if (impl->location_mode == LOCATION_MODE_PATH_BAR
|| impl->operation_mode == OPERATION_MODE_RECENT)
- widget = impl->browse_files_tree_view;
+ widget = impl->browse_files_current_view;
else
widget = impl->location_entry;
}
@@ -8964,12 +9639,10 @@ static GSList *
search_get_selected_files (GtkFileChooserDefault *impl)
{
GSList *result;
- GtkTreeSelection *selection;
result = NULL;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- gtk_tree_selection_selected_foreach (selection, search_selected_foreach_get_file_cb, &result);
+ current_selection_selected_foreach (impl, search_selected_foreach_get_file_cb, &result);
result = g_slist_reverse (result);
return result;
@@ -8981,12 +9654,9 @@ search_get_selected_files (GtkFileChooserDefault *impl)
static gboolean
search_should_respond (GtkFileChooserDefault *impl)
{
- GtkTreeSelection *selection;
-
g_assert (impl->operation_mode == OPERATION_MODE_SEARCH);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- return (gtk_tree_selection_count_selected_rows (selection) != 0);
+ return (current_selection_count_selected_rows (impl) != 0);
}
/* Adds one hit from the search engine to the search_model */
@@ -9043,6 +9713,7 @@ search_engine_finished_cb (GtkSearchEngine *engine,
*/
gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
GTK_TREE_MODEL (impl->search_model));
+ current_view_set_file_model (impl, GTK_TREE_MODEL (impl->search_model));
file_list_set_sort_column_ids (impl);
#endif
@@ -9090,7 +9761,7 @@ search_clear_model (GtkFileChooserDefault *impl,
impl->search_model = NULL;
if (remove_from_treeview)
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL);
+ current_view_set_file_model (impl, NULL);
}
/* Stops any ongoing searches; does not touch the search_model */
@@ -9141,8 +9812,7 @@ search_setup_model (GtkFileChooserDefault *impl)
* more "alive" than setting the model at the end of the search
* run
*/
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
- GTK_TREE_MODEL (impl->search_model));
+ current_view_set_file_model (impl, GTK_TREE_MODEL (impl->search_model));
file_list_set_sort_column_ids (impl);
}
@@ -9306,7 +9976,7 @@ recent_clear_model (GtkFileChooserDefault *impl,
return;
if (remove_from_treeview)
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL);
+ current_view_set_file_model (impl, NULL);
g_object_unref (impl->recent_model);
impl->recent_model = NULL;
@@ -9363,8 +10033,7 @@ recent_idle_cleanup (gpointer data)
RecentLoadData *load_data = data;
GtkFileChooserDefault *impl = load_data->impl;
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
- GTK_TREE_MODEL (impl->recent_model));
+ current_view_set_file_model (impl, GTK_TREE_MODEL (impl->recent_model));
file_list_set_sort_column_ids (impl);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->recent_model), MODEL_COL_MTIME, GTK_SORT_DESCENDING);
@@ -9509,12 +10178,10 @@ static GSList *
recent_get_selected_files (GtkFileChooserDefault *impl)
{
GSList *result;
- GtkTreeSelection *selection;
result = NULL;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- gtk_tree_selection_selected_foreach (selection, recent_selected_foreach_get_file_cb, &result);
+ current_selection_selected_foreach (impl, recent_selected_foreach_get_file_cb, &result);
result = g_slist_reverse (result);
return result;
@@ -9526,12 +10193,9 @@ recent_get_selected_files (GtkFileChooserDefault *impl)
static gboolean
recent_should_respond (GtkFileChooserDefault *impl)
{
- GtkTreeSelection *selection;
-
g_assert (impl->operation_mode == OPERATION_MODE_RECENT);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
- return (gtk_tree_selection_count_selected_rows (selection) != 0);
+ return (current_selection_count_selected_rows (impl) != 0);
}
static void
@@ -9591,9 +10255,16 @@ check_preview_change (GtkFileChooserDefault *impl)
char *new_display_name;
GtkTreeModel *model;
- gtk_tree_view_get_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view), &cursor_path, NULL);
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view));
- if (cursor_path)
+ if (impl->view_mode == VIEW_MODE_LIST)
+ gtk_tree_view_get_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view), &cursor_path, NULL);
+ else if (impl->view_mode == VIEW_MODE_ICON)
+ cursor_path = NULL;
+ else
+ g_assert_not_reached ();
+
+ model = impl->current_model;
+
+ if (cursor_path && model)
{
GtkTreeIter iter;
@@ -9903,7 +10574,7 @@ shortcuts_key_press_event_cb (GtkWidget *widget,
if (key_is_left_or_right (event))
{
- gtk_widget_grab_focus (impl->browse_files_tree_view);
+ gtk_widget_grab_focus (impl->browse_files_current_view);
return TRUE;
}
@@ -9974,8 +10645,9 @@ list_select_func (GtkTreeSelection *selection,
return TRUE;
}
+/* GtkTreeSelection or GtkIconView selection changed. */
static void
-list_selection_changed (GtkTreeSelection *selection,
+list_selection_changed (void *selection,
GtkFileChooserDefault *impl)
{
/* See if we are in the new folder editable row for Save mode */
@@ -10012,15 +10684,34 @@ list_row_activated (GtkTreeView *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
GtkFileChooserDefault *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,
+ GtkFileChooserDefault *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,
+ GtkFileChooserDefault *impl)
{
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;
@@ -10070,6 +10761,10 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
{
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
+ /* only applicable in the tree view (i.e. list view) */
+ if (!impl->browse_files_tree_view)
+ return;
+
GList *walk, *list;
/* Keep the following column numbers in sync with create_file_list() */
@@ -10083,7 +10778,7 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
if (GTK_IS_CELL_RENDERER_PIXBUF (renderer))
{
gtk_tree_view_column_set_attributes (column, renderer,
- "pixbuf", MODEL_COL_PIXBUF,
+ "pixbuf", MODEL_COL_LIST_PIXBUF,
NULL);
}
else
@@ -10148,7 +10843,7 @@ location_popup_handler (GtkFileChooserDefault *impl,
change_folder_and_display_error (impl, impl->current_folder, FALSE);
if (impl->location_mode == LOCATION_MODE_PATH_BAR)
- widget_to_focus = impl->browse_files_tree_view;
+ widget_to_focus = impl->browse_files_current_view;
else
widget_to_focus = impl->location_entry;
@@ -10350,3 +11045,241 @@ shortcuts_pane_model_filter_new (GtkFileChooserDefault *impl,
return GTK_TREE_MODEL (model);
}
+static gboolean
+get_selected_tree_iter_from_icon_view (GtkFileChooserDefault *impl,
+ GtkTreeIter *iter_out)
+{
+ GList *icon_selection;
+ GtkTreePath *icon_selection_path;
+
+ icon_selection = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (impl->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 (impl->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 (GtkFileChooserDefault *impl,
+ GtkTreeSelectionForeachFunc func,
+ gpointer data)
+{
+ GtkTreeIter iter;
+ GList *icon_selection;
+ GList *elem;
+ GtkTreePath *icon_selection_path;
+
+ icon_selection = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (impl->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 (impl->current_model),
+ &iter,
+ icon_selection_path);
+ (* func) (GTK_TREE_MODEL (impl->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 (GtkFileChooserDefault *impl,
+ ViewMode view,
+ GtkTreeSelectionForeachFunc func,
+ gpointer data)
+{
+ if (impl->current_model == NULL)
+ return;
+
+ if (view == VIEW_MODE_LIST)
+ {
+ GtkTreeSelection *selection;
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->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 (GtkFileChooserDefault *impl,
+ GtkTreeSelectionForeachFunc func,
+ gpointer data)
+{
+ selection_selected_foreach (impl, impl->view_mode, func, data);
+}
+
+static guint
+current_selection_count_selected_rows (GtkFileChooserDefault *impl)
+{
+ if (impl->view_mode == VIEW_MODE_LIST)
+ {
+ GtkTreeSelection *selection;
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+ return gtk_tree_selection_count_selected_rows (selection);
+ }
+ if (impl->view_mode == VIEW_MODE_ICON)
+ {
+ GList *icon_selection;
+ icon_selection = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (impl->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 (GtkFileChooserDefault *impl,
+ GtkTreeIter *iter,
+ ViewMode target)
+{
+ if (target == VIEW_MODE_LIST)
+ {
+ GtkTreeSelection *selection;
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->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 (impl->current_model, iter);
+ gtk_icon_view_select_path (GTK_ICON_VIEW (impl->browse_files_icon_view), path);
+ gtk_tree_path_free (path);
+ }
+ else
+ g_assert_not_reached ();
+}
+
+static void
+current_selection_select_iter (GtkFileChooserDefault *impl,
+ GtkTreeIter *iter)
+{
+ selection_select_iter (impl, iter, impl->view_mode);
+}
+
+struct copy_old_selection_to_current_view_closure {
+ GtkFileChooserDefault *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->view_mode);
+}
+
+static void
+copy_old_selection_to_current_view (GtkFileChooserDefault *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 (GtkFileChooserDefault *impl,
+ GtkTreeIter *iter)
+{
+ if (impl->view_mode == VIEW_MODE_LIST)
+ {
+ GtkTreeSelection *selection;
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+ gtk_tree_selection_unselect_iter (selection, iter);
+ }
+ else if (impl->view_mode == VIEW_MODE_ICON)
+ {
+ GtkTreePath *path;
+ path = gtk_tree_model_get_path (impl->current_model, iter);
+ gtk_icon_view_unselect_path (GTK_ICON_VIEW (impl->browse_files_icon_view), path);
+ gtk_tree_path_free (path);
+ }
+ else
+ g_assert_not_reached ();
+}
+
+static void
+current_selection_unselect_all (GtkFileChooserDefault *impl)
+{
+ if (impl->view_mode == VIEW_MODE_LIST)
+ {
+ GtkTreeSelection *selection;
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+ gtk_tree_selection_unselect_all (selection);
+ }
+ else if (impl->view_mode == VIEW_MODE_ICON)
+ gtk_icon_view_unselect_all (GTK_ICON_VIEW (impl->browse_files_icon_view));
+ else
+ g_assert_not_reached ();
+}
+
+static void
+current_view_set_file_model (GtkFileChooserDefault *impl, GtkTreeModel *model)
+{
+ GtkWidget *view;
+
+ impl->current_model = model;
+
+ if (impl->view_mode == VIEW_MODE_LIST)
+ view = impl->browse_files_tree_view;
+ else if (impl->view_mode == VIEW_MODE_ICON)
+ view = impl->browse_files_icon_view;
+ else
+ g_assert_not_reached ();
+
+ g_object_set (view, "model", impl->current_model, NULL);
+}
+
+static void
+current_view_set_cursor (GtkFileChooserDefault *impl, GtkTreePath *path)
+{
+ if (impl->view_mode == VIEW_MODE_LIST)
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view), path, NULL, FALSE);
+ else if (impl->view_mode == VIEW_MODE_ICON)
+ gtk_icon_view_set_cursor (GTK_ICON_VIEW (impl->browse_files_icon_view), path, NULL, FALSE);
+ else
+ g_assert_not_reached ();
+}
+
+static void
+current_view_set_select_multiple (GtkFileChooserDefault *impl, gboolean select_multiple)
+{
+ GtkTreeSelection *selection;
+ GtkSelectionMode mode;
+ mode = select_multiple ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_BROWSE;
+
+ if (impl->view_mode == VIEW_MODE_LIST)
+ {
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+ gtk_tree_selection_set_mode (selection, mode);
+ gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (impl->browse_files_tree_view), select_multiple);
+ }
+ else if (impl->view_mode == VIEW_MODE_ICON)
+ gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (impl->browse_files_icon_view), mode);
+ else
+ g_assert_not_reached ();
+}
diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h
index dab74c3bdd..ba09a55364 100644
--- a/gtk/gtkfilechooserprivate.h
+++ b/gtk/gtkfilechooserprivate.h
@@ -33,6 +33,8 @@
#include "gtktreestore.h"
#include "gtktreeview.h"
#include "gtkvbox.h"
+#include "gtkiconview.h"
+#include "gtkhscale.h"
G_BEGIN_DECLS
@@ -135,6 +137,11 @@ typedef enum {
LOCATION_MODE_FILENAME_ENTRY
} LocationMode;
+typedef enum {
+ VIEW_MODE_LIST,
+ VIEW_MODE_ICON
+} ViewMode;
+
typedef enum {
OPERATION_MODE_BROWSE,
OPERATION_MODE_SEARCH,
@@ -170,10 +177,18 @@ struct _GtkFileChooserDefault
GtkWidget *browse_shortcuts_popup_menu_remove_item;
GtkWidget *browse_shortcuts_popup_menu_rename_item;
GtkWidget *browse_files_tree_view;
+ GtkWidget *browse_files_scrolled_window;
+ GtkWidget *browse_files_current_view;
+ GtkWidget *browse_files_icon_view;
GtkWidget *browse_files_popup_menu;
GtkWidget *browse_files_popup_menu_add_shortcut_item;
GtkWidget *browse_files_popup_menu_hidden_files_item;
GtkWidget *browse_files_popup_menu_size_column_item;
+ GtkWidget *browse_files_popup_menu_sort_by_name_item;
+ GtkWidget *browse_files_popup_menu_sort_by_size_item;
+ GtkWidget *browse_files_popup_menu_sort_by_mtime_item;
+ GtkWidget *browse_files_popup_menu_sort_ascending_item;
+ GtkWidget *browse_files_popup_menu_sort_descending_item;
GtkWidget *browse_new_folder_button;
GtkWidget *browse_path_bar_hbox;
GtkSizeGroup *browse_path_bar_size_group;
@@ -186,6 +201,7 @@ struct _GtkFileChooserDefault
gulong toplevel_unmapped_id;
+ GtkTreeModel *current_model;
GtkFileSystemModel *browse_files_model;
char *browse_files_last_selected_name;
@@ -211,6 +227,13 @@ struct _GtkFileChooserDefault
GtkWidget *extra_align;
GtkWidget *extra_widget;
+ GtkWidget *view_mode_combo_box;
+ GtkWidget *icon_view_scale_hbox;
+ GtkWidget *icon_view_scale;
+ GtkWidget *icon_view_scale_zoom_in_icon;
+ GtkWidget *icon_view_scale_zoom_out_icon;
+ ViewMode view_mode;
+
GtkWidget *location_button;
GtkWidget *location_entry_box;
GtkWidget *location_label;
@@ -259,6 +282,7 @@ struct _GtkFileChooserDefault
GtkTreeViewColumn *list_name_column;
GtkCellRenderer *list_name_renderer;
+ GtkCellRenderer *list_icon_renderer;
GtkTreeViewColumn *list_mtime_column;
GtkTreeViewColumn *list_size_column;
@@ -266,10 +290,14 @@ struct _GtkFileChooserDefault
char *edited_new_text;
gulong settings_signal_id;
- int icon_size;
+ int list_view_icon_size;
+ int icon_view_icon_size;
GSource *focus_entry_idle;
+ GSource *start_editing_icon_view_idle;
+ GtkTreePath *start_editing_icon_view_path;
+
gulong toplevel_set_focus_id;
GtkWidget *toplevel_last_focus_widget;
diff --git a/gtk/gtkfilechoosersettings.c b/gtk/gtkfilechoosersettings.c
index 5b8fb87611..ce34291ef0 100644
--- a/gtk/gtkfilechoosersettings.c
+++ b/gtk/gtkfilechoosersettings.c
@@ -39,6 +39,8 @@
#define SETTINGS_GROUP "Filechooser Settings"
#define LOCATION_MODE_KEY "LocationMode"
+#define VIEW_MODE_KEY "ViewMode"
+#define ICON_VIEW_SCALE_KEY "IconViewScale"
#define SHOW_HIDDEN_KEY "ShowHidden"
#define SHOW_SIZE_COLUMN_KEY "ShowSizeColumn"
#define GEOMETRY_X_KEY "GeometryX"
@@ -58,8 +60,11 @@
#define STARTUP_MODE_RECENT_STRING "recent"
#define STARTUP_MODE_CWD_STRING "cwd"
-#define MODE_PATH_BAR "path-bar"
-#define MODE_FILENAME_ENTRY "filename-entry"
+#define MODE_PATH_BAR "path-bar"
+#define MODE_FILENAME_ENTRY "filename-entry"
+
+#define MODE_LIST_VIEW "list-view"
+#define MODE_ICON_VIEW "icon-view"
#define EQ(a, b) (g_ascii_strcasecmp ((a), (b)) == 0)
@@ -114,7 +119,7 @@ ensure_settings_read (GtkFileChooserSettings *settings)
{
GError *error;
GKeyFile *key_file;
- gchar *location_mode_str, *filename;
+ gchar *location_mode_str, *view_mode_str, *filename;
gchar *sort_column, *sort_order;
gchar *startup_mode;
gboolean value;
@@ -159,6 +164,27 @@ ensure_settings_read (GtkFileChooserSettings *settings)
g_free (location_mode_str);
}
+ /* View mode */
+
+ view_mode_str = g_key_file_get_string (key_file, SETTINGS_GROUP,
+ VIEW_MODE_KEY, NULL);
+ if (view_mode_str)
+ {
+ if (EQ (view_mode_str, MODE_LIST_VIEW))
+ settings->view_mode = VIEW_MODE_LIST;
+ else if (EQ (view_mode_str, MODE_ICON_VIEW))
+ settings->view_mode = VIEW_MODE_ICON;
+ else
+ g_warning ("Unknown view mode '%s' encountered in filechooser settings",
+ view_mode_str);
+
+ g_free (view_mode_str);
+ }
+
+ /* Icon view scale */
+
+ get_int_key (key_file, SETTINGS_GROUP, ICON_VIEW_SCALE_KEY, &settings->icon_view_scale);
+
/* Show hidden */
value = g_key_file_get_boolean (key_file, SETTINGS_GROUP,
@@ -256,6 +282,8 @@ static void
_gtk_file_chooser_settings_init (GtkFileChooserSettings *settings)
{
settings->location_mode = LOCATION_MODE_PATH_BAR;
+ settings->view_mode = VIEW_MODE_LIST;
+ settings->icon_view_scale = 48;
settings->sort_order = GTK_SORT_ASCENDING;
settings->sort_column = FILE_LIST_COL_NAME;
settings->show_hidden = FALSE;
@@ -287,6 +315,34 @@ _gtk_file_chooser_settings_set_location_mode (GtkFileChooserSettings *settings,
settings->location_mode = location_mode;
}
+ViewMode
+_gtk_file_chooser_settings_get_view_mode (GtkFileChooserSettings *settings)
+{
+ ensure_settings_read (settings);
+ return settings->view_mode;
+}
+
+void
+_gtk_file_chooser_settings_set_view_mode (GtkFileChooserSettings *settings,
+ ViewMode view_mode)
+{
+ settings->view_mode = view_mode;
+}
+
+gint
+_gtk_file_chooser_settings_get_icon_view_scale (GtkFileChooserSettings *settings)
+{
+ ensure_settings_read (settings);
+ return settings->icon_view_scale;
+}
+
+void
+_gtk_file_chooser_settings_set_icon_view_scale (GtkFileChooserSettings *settings,
+ gint icon_view_scale)
+{
+ settings->icon_view_scale = icon_view_scale;
+}
+
gboolean
_gtk_file_chooser_settings_get_show_hidden (GtkFileChooserSettings *settings)
{
@@ -389,7 +445,7 @@ gboolean
_gtk_file_chooser_settings_save (GtkFileChooserSettings *settings,
GError **error)
{
- const gchar *location_mode_str;
+ const gchar *location_mode_str, *view_mode_str;
gchar *filename;
gchar *dirname;
gchar *contents;
@@ -417,6 +473,16 @@ _gtk_file_chooser_settings_save (GtkFileChooserSettings *settings,
return FALSE;
}
+ if (settings->view_mode == VIEW_MODE_LIST)
+ view_mode_str = MODE_LIST_VIEW;
+ else if (settings->view_mode == VIEW_MODE_ICON)
+ view_mode_str = MODE_ICON_VIEW;
+ else
+ {
+ g_assert_not_reached ();
+ return FALSE;
+ }
+
switch (settings->sort_column)
{
case FILE_LIST_COL_NAME:
@@ -473,6 +539,10 @@ _gtk_file_chooser_settings_save (GtkFileChooserSettings *settings,
g_key_file_set_string (key_file, SETTINGS_GROUP,
LOCATION_MODE_KEY, location_mode_str);
+ g_key_file_set_string (key_file, SETTINGS_GROUP,
+ VIEW_MODE_KEY, view_mode_str);
+ g_key_file_set_integer (key_file, SETTINGS_GROUP,
+ ICON_VIEW_SCALE_KEY, settings->icon_view_scale);
g_key_file_set_boolean (key_file, SETTINGS_GROUP,
SHOW_HIDDEN_KEY, settings->show_hidden);
g_key_file_set_boolean (key_file, SETTINGS_GROUP,
diff --git a/gtk/gtkfilechoosersettings.h b/gtk/gtkfilechoosersettings.h
index 2283192c01..b987fca8c3 100644
--- a/gtk/gtkfilechoosersettings.h
+++ b/gtk/gtkfilechoosersettings.h
@@ -45,9 +45,10 @@ struct _GtkFileChooserSettings
GObject object;
LocationMode location_mode;
+ ViewMode view_mode;
GtkSortType sort_order;
- gint sort_column;
+ gint sort_column, icon_view_scale;
StartupMode startup_mode;
int geometry_x;
@@ -73,6 +74,14 @@ LocationMode _gtk_file_chooser_settings_get_location_mode (GtkFileChooserSetting
void _gtk_file_chooser_settings_set_location_mode (GtkFileChooserSettings *settings,
LocationMode location_mode);
+ViewMode _gtk_file_chooser_settings_get_view_mode (GtkFileChooserSettings *settings);
+void _gtk_file_chooser_settings_set_view_mode (GtkFileChooserSettings *settings,
+ ViewMode view_mode);
+
+gint _gtk_file_chooser_settings_get_icon_view_scale (GtkFileChooserSettings *settings);
+void _gtk_file_chooser_settings_set_icon_view_scale (GtkFileChooserSettings *settings,
+ gint icon_view_scale);
+
gboolean _gtk_file_chooser_settings_get_show_hidden (GtkFileChooserSettings *settings);
void _gtk_file_chooser_settings_set_show_hidden (GtkFileChooserSettings *settings,
gboolean show_hidden);
@Dudemanguy
Copy link
Author

Oops, I must have somehow left out that directory when running diff. Thanks for pointing it out. It should work fine now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment