diff -ur Thunar-1.0.1/thunar/thunar-icon-factory.c Thunar-1.0.1-m1/thunar/thunar-icon-factory.c --- Thunar-1.0.1/thunar/thunar-icon-factory.c 2008-10-22 08:43:14.000000000 +0200 +++ Thunar-1.0.1-m1/thunar/thunar-icon-factory.c 2009-11-02 21:24:38.000000000 +0200 @@ -900,7 +900,139 @@ return thunar_icon_factory_lookup_icon (factory, name, size, wants_default); } +/** + * thunar_icon_factory_load_dir_icon: + * @factory : a #ThunarIconFactory instance. + * @file : a #ThunarFile. + * @icon_state : the desired icon state. + * @icon_size : the desired icon size. + * + * Creates direcory thumbnail by composing directory icon from current icon + * theme with .DirThumb image, if it exists. + * + * The caller is responsible to free the returned object using + * g_object_unref() when no longer needed. + * + * Return value: the #GdkPixbuf icon or NULL, if .DirThumb is absent. + **/ +GdkPixbuf* +thunar_icon_factory_load_dir_icon (ThunarIconFactory *factory, + ThunarFile *dir, + ThunarFileIconState icon_state, + gint icon_size) +{ + ThunarVfsInfo *dir_info; + ThunarVfsPath *dir_path; + ThunarVfsInfo *thumb_info; + ThunarVfsPath *thumb_path; + const gchar *icon_name; + GdkPixbuf *dir_pix = NULL; + ThunarIconKey key; + char buf[THUNAR_VFS_PATH_MAXSTRLEN]; + + dir_info = thunar_file_get_info(dir); + dir_path = thunar_file_get_path(dir); + thumb_path = thunar_vfs_path_relative(dir_path, ".DirThumb"); + thumb_info = thunar_vfs_info_new_for_path(thumb_path, NULL); + + if (!(dir_info->itime || thumb_info)) + return NULL; + thunar_vfs_path_to_string(dir_path, buf + 2, THUNAR_VFS_PATH_MAXSTRLEN -2, NULL); + buf[0] = '/'; + buf[1] = '0' + (icon_state == THUNAR_FILE_ICON_STATE_DEFAULT); + key.name = buf; + + /* if thumbnail is not valid - delete it */ + if (thumb_info && (thumb_info->mtime > dir_info->itime)) + { + int i; + + /* run over all possible icon sizes: from 16 till 128 */ + for (i = 1; i < 9; i++) + { + key.size = i * 16; + g_hash_table_remove (factory->icon_cache, &key); + } + dir_info->itime = 0; + } + + /* fetch thumbnail */ + key.size = icon_size; + dir_pix = g_hash_table_lookup(factory->icon_cache, &key); + if (dir_pix) + goto cleanup; + + /* If we got here, then there is no thumbnail of proper size. + * So, if .DirThumb exists, lets create one */ + if (thumb_info) + { + gchar *tmp; + GdkPixbuf *thumb_pix; + ThunarIconKey *nkey; + int size, w, h; + gdouble r1; + + icon_name = "gnome-fs-directory"; + if ((icon_state != THUNAR_FILE_ICON_STATE_DEFAULT) && + gtk_icon_theme_has_icon (factory->icon_theme, + "gnome-fs-directory-accept")) + icon_name = "gnome-fs-directory-accept"; + + dir_pix = thunar_icon_factory_lookup_icon (factory, icon_name, icon_size, FALSE); + if (!dir_pix) + goto cleanup; + g_object_unref(G_OBJECT(dir_pix)); + dir_pix = gdk_pixbuf_copy(dir_pix); + if (!dir_pix) + goto cleanup; + + tmp = thunar_vfs_path_dup_string(thumb_path); + thumb_pix = gdk_pixbuf_new_from_file (tmp, NULL); + g_free(tmp); + if (!thumb_pix) + goto cleanup; + + /* the thumb will be scaled down (keeping ratio) to fit into directory + * icon and placed at top right. margin is 10 pixels */ + size = icon_size-10; + w = gdk_pixbuf_get_width(thumb_pix); + h = gdk_pixbuf_get_height(thumb_pix); + if (w > h) + { + r1 = (gdouble) size / w; + w = size; + h = h * r1; + } else { + r1 = (gdouble) size / h; + h = size; + w = w * r1; + } + gdk_pixbuf_composite(thumb_pix, dir_pix, 10, 0, w, h, 10, 0, r1, r1, + GDK_INTERP_HYPER, 225); + g_object_unref(thumb_pix); + + /* generate a key for the new cached icon */ + nkey = g_malloc (sizeof (ThunarIconKey) + strlen (key.name) + 1); + nkey->name = ((gchar *) nkey) + sizeof (ThunarIconKey); + nkey->size = icon_size; + strcpy (nkey->name, key.name); + + /* insert the new icon into the cache */ + g_hash_table_insert (factory->icon_cache, nkey, dir_pix); + dir_info->itime = thumb_info->mtime; + } +cleanup: + if (thumb_info) + thunar_vfs_info_unref(thumb_info); + + if (dir_pix) + return g_object_ref(dir_pix); + + return NULL; +} + + /** * thunar_icon_factory_load_file_icon: @@ -943,6 +1075,12 @@ return icon; } + if (thunar_file_is_directory(file)) + { + icon = thunar_icon_factory_load_dir_icon(factory, file, icon_state, icon_size); + if (icon != NULL) + return icon; + } /* check if thumbnails are enabled and we can display a thumbnail for the item */ if (G_LIKELY (factory->show_thumbnails && thunar_file_is_regular (file))) { diff -ur Thunar-1.0.1/thunar-vfs/thunar-vfs-info.c Thunar-1.0.1-m1/thunar-vfs/thunar-vfs-info.c --- Thunar-1.0.1/thunar-vfs/thunar-vfs-info.c 2008-10-22 08:43:21.000000000 +0200 +++ Thunar-1.0.1-m1/thunar-vfs/thunar-vfs-info.c 2009-11-02 02:33:24.000000000 +0200 @@ -169,7 +169,7 @@ dst->custom_icon = g_strdup (info->custom_icon); dst->display_name = g_strdup (info->display_name); dst->ref_count = 1; - + dst->itime = 0; return dst; } diff -ur Thunar-1.0.1/thunar-vfs/thunar-vfs-info.h Thunar-1.0.1-m1/thunar-vfs/thunar-vfs-info.h --- Thunar-1.0.1/thunar-vfs/thunar-vfs-info.h 2008-10-22 08:43:21.000000000 +0200 +++ Thunar-1.0.1-m1/thunar-vfs/thunar-vfs-info.h 2009-11-02 01:28:08.000000000 +0200 @@ -107,6 +107,9 @@ /* file's display name (UTF-8) */ gchar *display_name; + /* icon modification time */ + ThunarVfsFileTime itime; + /*< private >*/ gint ref_count; }; diff -ur Thunar-1.0.1/thunar-vfs/thunar-vfs-io-local.c Thunar-1.0.1-m1/thunar-vfs/thunar-vfs-io-local.c --- Thunar-1.0.1/thunar-vfs/thunar-vfs-io-local.c 2009-01-12 22:38:49.000000000 +0200 +++ Thunar-1.0.1-m1/thunar-vfs/thunar-vfs-io-local.c 2009-11-02 02:42:09.000000000 +0200 @@ -271,7 +271,7 @@ } /* allocate a new info object */ - info = _thunar_vfs_slice_new (ThunarVfsInfo); + info = _thunar_vfs_slice_new0 (ThunarVfsInfo); info->path = thunar_vfs_path_ref (path); info->ref_count = 1;