summaryrefslogtreecommitdiff
path: root/gtk/gtkfilechooserdefault.c
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2009-06-30 23:33:29 +0200
committerBenjamin Otte <otte@gnome.org>2009-10-15 22:00:08 +0200
commit4a1ff32325fd2ffc80ec3d9612f4e2a846261abc (patch)
treedef89c31d40c0a39e143f8c28e9d119c8ff2b487 /gtk/gtkfilechooserdefault.c
parent105e6fbc11dbc37a6b863b766b878cad1c63b969 (diff)
downloadgtk+-4a1ff32325fd2ffc80ec3d9612f4e2a846261abc.tar.gz
Load icons on-demand
Because loading icons takes a noticable performance, this code loads the pixbuf on demand and only loads icons for rows that are visible. There is a few caveats to this: - The pixbuf cell renderer must report the proer size even if the icon is not yet loaded. This is achieved by setting a fixed size. - On theme changes the cahced pixbufs and the cell renderer must be updated to conform to the new theme.
Diffstat (limited to 'gtk/gtkfilechooserdefault.c')
-rw-r--r--gtk/gtkfilechooserdefault.c102
1 files changed, 100 insertions, 2 deletions
diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c
index 730df06714..3abb38d790 100644
--- a/gtk/gtkfilechooserdefault.c
+++ b/gtk/gtkfilechooserdefault.c
@@ -4538,6 +4538,10 @@ create_file_list (GtkFileChooserDefault *impl)
gtk_tree_view_column_set_title (impl->list_name_column, _("Name"));
renderer = gtk_cell_renderer_pixbuf_new ();
+ /* We set a fixed size so that we get an emoty row even if no icons are loaded yet */
+ gtk_cell_renderer_set_fixed_size (renderer,
+ renderer->xpad * 2 + impl->icon_size,
+ renderer->ypad * 2 + impl->icon_size);
gtk_tree_view_column_pack_start (impl->list_name_column, renderer, FALSE);
impl->list_name_renderer = gtk_cell_renderer_text_new ();
@@ -5797,6 +5801,8 @@ change_icon_theme (GtkFileChooserDefault *impl)
{
GtkSettings *settings;
gint width, height;
+ GtkCellRenderer *renderer;
+ GList *cells;
profile_start ("start", NULL);
@@ -5808,6 +5814,16 @@ change_icon_theme (GtkFileChooserDefault *impl)
impl->icon_size = FALLBACK_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);
+ gtk_cell_renderer_set_fixed_size (renderer,
+ renderer->xpad * 2 + impl->icon_size,
+ renderer->ypad * 2 + impl->icon_size);
+ 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);
profile_end ("end", NULL);
@@ -6774,7 +6790,44 @@ my_g_format_time_for_display (glong secs)
return date_str;
}
-static gboolean
+#define copy_attribute(to, from, attribute) G_STMT_START { \
+ GFileAttributeType type; \
+ gpointer value; \
+\
+ if (g_file_info_get_attribute_data (from, attribute, &type, &value, NULL)) \
+ g_file_info_set_attribute (to, attribute, type, value); \
+}G_STMT_END
+
+static void
+file_system_model_got_thumbnail (GObject *object, GAsyncResult *res, gpointer data)
+{
+ GtkFileSystemModel *model = data; /* might be unreffed if operation was cancelled */
+ GFile *file = G_FILE (object);
+ GFileInfo *queried, *info;
+ GtkTreeIter iter;
+
+ queried = g_file_query_info_finish (file, res, NULL);
+ if (queried == NULL)
+ return;
+
+ /* now we know model is valid */
+
+ /* file was deleted */
+ if (!_gtk_file_system_model_get_iter_for_file (model, &iter, file))
+ return;
+
+ info = g_file_info_dup (_gtk_file_system_model_get_info (model, &iter));
+
+ copy_attribute (info, queried, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
+ copy_attribute (info, queried, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED);
+ copy_attribute (info, queried, G_FILE_ATTRIBUTE_STANDARD_ICON);
+
+ _gtk_file_system_model_update_file (model, file, info, FALSE);
+
+ g_object_unref (info);
+}
+
+static gboolean
file_system_model_set (GtkFileSystemModel *model,
GFile *file,
GFileInfo *info,
@@ -6806,7 +6859,52 @@ file_system_model_set (GtkFileSystemModel *model,
break;
case MODEL_COL_PIXBUF:
if (info)
- g_value_take_object (value, _gtk_file_info_render_icon (info, GTK_WIDGET (impl), impl->icon_size));
+ {
+ 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));
+ }
+ 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;
+
+ 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 (impl->browse_files_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)
+ {
+ g_file_info_set_attribute_boolean (info, "filechooser::queried", TRUE);
+ g_file_query_info_async (file,
+ G_FILE_ATTRIBUTE_THUMBNAIL_PATH ","
+ G_FILE_ATTRIBUTE_THUMBNAILING_FAILED ","
+ G_FILE_ATTRIBUTE_STANDARD_ICON,
+ 0,
+ G_PRIORITY_DEFAULT,
+ _gtk_file_system_model_get_cancellable (model),
+ file_system_model_got_thumbnail,
+ model);
+ }
+ gtk_tree_path_free (path);
+ gtk_tree_path_free (start);
+ gtk_tree_path_free (end);
+ return FALSE;
+ }
+ }
else
g_value_set_object (value, NULL);
break;