diff options
author | Benjamin Otte <otte@gnome.org> | 2009-06-30 23:33:29 +0200 |
---|---|---|
committer | Benjamin Otte <otte@gnome.org> | 2009-10-15 22:00:08 +0200 |
commit | 4a1ff32325fd2ffc80ec3d9612f4e2a846261abc (patch) | |
tree | def89c31d40c0a39e143f8c28e9d119c8ff2b487 /gtk/gtkfilechooserdefault.c | |
parent | 105e6fbc11dbc37a6b863b766b878cad1c63b969 (diff) | |
download | gtk+-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.c | 102 |
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; |