From f0606d54217563a52966c7a6775247e460a027a4 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 22 Sep 2022 16:29:41 -0400 Subject: [PATCH] file-info: Add a set of attributes for large thumbnails Some applications (eg., gnome-photos) really want a large thumbnail, if one can be created. Simply falling back to a smaller one (probably created by an old nautilus), without giving the application a chance to create a bigger thumbnail, is undesirable because they will appear fuzzy. Therefore, at separate attribute sets for all the thumbnail sizes that are supported in the spec: normal/large/x-large/xx-large. The old attribute will now return by default the biggest available, as it used to be, but also including the x-large and xx-large cases. Co-Authored-by: Marco Trevisan Fixes: #621 --- docs/reference/gio/gio-sections-common.txt | 12 ++ gio/gfileinfo-priv.h | 12 ++ gio/gfileinfo.c | 12 ++ gio/gfileinfo.h | 178 ++++++++++++++++++- gio/glocalfileinfo.c | 157 +++++++++++++++-- gio/tests/file-thumbnail.c | 193 +++++++++++++++++++++ 6 files changed, 547 insertions(+), 17 deletions(-) diff --git a/docs/reference/gio/gio-sections-common.txt b/docs/reference/gio/gio-sections-common.txt index 0ef50d747..2ec1f0bb2 100644 --- a/docs/reference/gio/gio-sections-common.txt +++ b/docs/reference/gio/gio-sections-common.txt @@ -350,6 +350,18 @@ G_FILE_ATTRIBUTE_OWNER_GROUP G_FILE_ATTRIBUTE_THUMBNAIL_PATH G_FILE_ATTRIBUTE_THUMBNAILING_FAILED G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID +G_FILE_ATTRIBUTE_THUMBNAIL_PATH_NORMAL +G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_NORMAL +G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_NORMAL +G_FILE_ATTRIBUTE_THUMBNAIL_PATH_LARGE +G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_LARGE +G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_LARGE +G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XLARGE +G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XLARGE +G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XLARGE +G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XXLARGE +G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XXLARGE +G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XXLARGE G_FILE_ATTRIBUTE_PREVIEW_ICON G_FILE_ATTRIBUTE_FILESYSTEM_SIZE G_FILE_ATTRIBUTE_FILESYSTEM_FREE diff --git a/gio/gfileinfo-priv.h b/gio/gfileinfo-priv.h index 8fc085973..4d31818c3 100644 --- a/gio/gfileinfo-priv.h +++ b/gio/gfileinfo-priv.h @@ -99,6 +99,18 @@ #define G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH (10485760 + 1) #define G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED (10485760 + 2) #define G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID (10485760 + 3) +#define G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH_NORMAL (10485760 + 4) +#define G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_NORMAL (10485760 + 5) +#define G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID_NORMAL (10485760 + 6) +#define G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH_LARGE (10485760 + 7) +#define G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_LARGE (10485760 + 8) +#define G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID_LARGE (10485760 + 9) +#define G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH_XLARGE (10485760 + 10) +#define G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_XLARGE (10485760 + 11) +#define G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID_XLARGE (10485760 + 12) +#define G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH_XXLARGE (10485760 + 13) +#define G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_XXLARGE (10485760 + 14) +#define G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID_XXLARGE (10485760 + 15) #define G_FILE_ATTRIBUTE_ID_PREVIEW_ICON (11534336 + 1) #define G_FILE_ATTRIBUTE_ID_FILESYSTEM_SIZE (12582912 + 1) #define G_FILE_ATTRIBUTE_ID_FILESYSTEM_FREE (12582912 + 2) diff --git a/gio/gfileinfo.c b/gio/gfileinfo.c index f709bf4f1..43a73ee38 100644 --- a/gio/gfileinfo.c +++ b/gio/gfileinfo.c @@ -265,6 +265,18 @@ ensure_attribute_hash (void) REGISTER_ATTRIBUTE (THUMBNAIL_PATH); REGISTER_ATTRIBUTE (THUMBNAILING_FAILED); REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID); + REGISTER_ATTRIBUTE (THUMBNAIL_PATH_NORMAL); + REGISTER_ATTRIBUTE (THUMBNAILING_FAILED_NORMAL); + REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID_NORMAL); + REGISTER_ATTRIBUTE (THUMBNAIL_PATH_LARGE); + REGISTER_ATTRIBUTE (THUMBNAILING_FAILED_LARGE); + REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID_LARGE); + REGISTER_ATTRIBUTE (THUMBNAIL_PATH_XLARGE); + REGISTER_ATTRIBUTE (THUMBNAILING_FAILED_XLARGE); + REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID_XLARGE); + REGISTER_ATTRIBUTE (THUMBNAIL_PATH_XXLARGE); + REGISTER_ATTRIBUTE (THUMBNAILING_FAILED_XXLARGE); + REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID_XXLARGE); REGISTER_ATTRIBUTE (PREVIEW_ICON); REGISTER_ATTRIBUTE (FILESYSTEM_SIZE); REGISTER_ATTRIBUTE (FILESYSTEM_FREE); diff --git a/gio/gfileinfo.h b/gio/gfileinfo.h index b8123c34e..11ad4710c 100644 --- a/gio/gfileinfo.h +++ b/gio/gfileinfo.h @@ -917,7 +917,7 @@ typedef struct _GFileInfoClass GFileInfoClass; * G_FILE_ATTRIBUTE_THUMBNAIL_PATH: * * A key in the "thumbnail" namespace for getting the path to the thumbnail - * image. + * image with the biggest size available. * * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BYTE_STRING. **/ @@ -949,6 +949,182 @@ typedef struct _GFileInfoClass GFileInfoClass; */ #define G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID "thumbnail::is-valid" /* boolean */ +/** + * G_FILE_ATTRIBUTE_THUMBNAIL_PATH_NORMAL: + * + * A key in the "thumbnail" namespace for getting the path to the normal + * thumbnail image. + * + * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BYTE_STRING. + * + * Since: 2.76 + */ +#define G_FILE_ATTRIBUTE_THUMBNAIL_PATH_NORMAL "thumbnail::path-normal" /* bytestring */ +/** + * G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_NORMAL: + * + * A key in the "thumbnail" namespace for checking if thumbnailing failed + * for the normal image. + * + * This attribute is %TRUE if thumbnailing failed. + * + * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BOOLEAN. + * + * Since: 2.76 + */ +#define G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_NORMAL "thumbnail::failed-normal" /* boolean */ +/** + * G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_NORMAL: + * + * A key in the "thumbnail" namespace for checking whether the normal + * thumbnail is outdated. + * + * This attribute is %TRUE if the normal thumbnail is up-to-date with the file + * it represents, and %FALSE if the file has been modified since the thumbnail + * was generated. + * + * If %G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_NORMAL is %TRUE and this attribute + * is %FALSE, it indicates that thumbnailing may be attempted again and may + * succeed. + * + * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BOOLEAN. + * + * Since: 2.76 + */ +#define G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_NORMAL "thumbnail::is-valid-normal" /* boolean */ + +/** + * G_FILE_ATTRIBUTE_THUMBNAIL_PATH_LARGE: + * + * A key in the "thumbnail" namespace for getting the path to the large + * thumbnail image. + * + * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BYTE_STRING. + * + * Since: 2.76 + */ +#define G_FILE_ATTRIBUTE_THUMBNAIL_PATH_LARGE "thumbnail::path-large" /* bytestring */ +/** + * G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_LARGE: + * + * A key in the "thumbnail" namespace for checking if thumbnailing failed + * for the large image. + * + * This attribute is %TRUE if thumbnailing failed. + * + * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BOOLEAN. + * + * Since: 2.76 + */ +#define G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_LARGE "thumbnail::failed-large" /* boolean */ +/** + * G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_LARGE: + * + * A key in the "thumbnail" namespace for checking whether the large + * thumbnail is outdated. + * + * This attribute is %TRUE if the large thumbnail is up-to-date with the file + * it represents, and %FALSE if the file has been modified since the thumbnail + * was generated. + * + * If %G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_LARGE is %TRUE and this attribute + * is %FALSE, it indicates that thumbnailing may be attempted again and may + * succeed. + * + * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BOOLEAN. + * + * Since: 2.76 + */ +#define G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_LARGE "thumbnail::is-valid-large" /* boolean */ + +/** + * G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XLARGE: + * + * A key in the "thumbnail" namespace for getting the path to the x-large + * thumbnail image. + * + * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BYTE_STRING. + * + * Since: 2.76 + */ +#define G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XLARGE "thumbnail::path-xlarge" /* bytestring */ +/** + * G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XLARGE: + * + * A key in the "thumbnail" namespace for checking if thumbnailing failed + * for the x-large image. + * + * This attribute is %TRUE if thumbnailing failed. + * + * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BOOLEAN. + * + * Since: 2.76 + */ +#define G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XLARGE "thumbnail::failed-xlarge" /* boolean */ +/** + * G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XLARGE: + * + * A key in the "thumbnail" namespace for checking whether the x-large + * thumbnail is outdated. + * + * This attribute is %TRUE if the x-large thumbnail is up-to-date with the file + * it represents, and %FALSE if the file has been modified since the thumbnail + * was generated. + * + * If %G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XLARGE is %TRUE and this attribute + * is %FALSE, it indicates that thumbnailing may be attempted again and may + * succeed. + * + * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BOOLEAN. + * + * Since: 2.76 + */ +#define G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XLARGE "thumbnail::is-valid-xlarge" /* boolean */ + +/** + * G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XXLARGE: + * + * A key in the "thumbnail" namespace for getting the path to the xx-large + * thumbnail image. + * + * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BYTE_STRING. + * + * Since: 2.76 + */ +#define G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XXLARGE "thumbnail::path-xxlarge" /* bytestring */ +/** + * G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XXLARGE: + * + * A key in the "thumbnail" namespace for checking if thumbnailing failed + * for the xx-large image. + * + * This attribute is %TRUE if thumbnailing failed. + * + * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BOOLEAN. + * + * Since: 2.76 + */ +#define G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XXLARGE "thumbnail::failed-xxlarge" /* boolean */ +/** + * G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XXLARGE: + * + * A key in the "thumbnail" namespace for checking whether the xx-large + * thumbnail is outdated. + * + * This attribute is %TRUE if the x-large thumbnail is up-to-date with the file + * it represents, and %FALSE if the file has been modified since the thumbnail + * was generated. + * + * If %G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XXLARGE is %TRUE and this attribute + * is %FALSE, it indicates that thumbnailing may be attempted again and may + * succeed. + * + * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BOOLEAN. + * + * Since: 2.76 + */ +#define G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XXLARGE "thumbnail::is-valid-xxlarge" /* boolean */ + /* Preview */ /** diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c index 661d2266a..24c5475bb 100644 --- a/gio/glocalfileinfo.c +++ b/gio/glocalfileinfo.c @@ -1418,19 +1418,90 @@ get_content_type (const char *basename, } +typedef enum { + THUMBNAIL_SIZE_AUTO, + THUMBNAIL_SIZE_NORMAL, + THUMBNAIL_SIZE_LARGE, + THUMBNAIL_SIZE_XLARGE, + THUMBNAIL_SIZE_XXLARGE, + THUMBNAIL_SIZE_LAST, +} ThumbnailSize; + +static const char * +get_thumbnail_dirname_from_size (ThumbnailSize size) +{ + switch (size) + { + case THUMBNAIL_SIZE_AUTO: + return NULL; + break; + case THUMBNAIL_SIZE_NORMAL: + return "normal"; + break; + case THUMBNAIL_SIZE_LARGE: + return "large"; + break; + case THUMBNAIL_SIZE_XLARGE: + return "x-large"; + break; + case THUMBNAIL_SIZE_XXLARGE: + return "xx-large"; + break; + default: + g_assert_not_reached (); + } + + g_return_val_if_reached (NULL); +} + /* @stat_buf is the pre-calculated result of stat(path), or %NULL if that failed. */ static void get_thumbnail_attributes (const char *path, GFileInfo *info, - const GLocalFileStat *stat_buf) + const GLocalFileStat *stat_buf, + ThumbnailSize size) { GChecksum *checksum; + const char *dirname; char *uri; char *filename = NULL; char *basename; - const char *size_dirs[4] = { "xx-large", "x-large", "large", "normal" }; - gsize i; + guint32 failed_attr_id; + guint32 is_valid_attr_id; + guint32 path_attr_id; + switch (size) + { + case THUMBNAIL_SIZE_AUTO: + failed_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED; + is_valid_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID; + path_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH; + break; + case THUMBNAIL_SIZE_NORMAL: + failed_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_NORMAL; + is_valid_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID_NORMAL; + path_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH_NORMAL; + break; + case THUMBNAIL_SIZE_LARGE: + failed_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_LARGE; + is_valid_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID_LARGE; + path_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH_LARGE; + break; + case THUMBNAIL_SIZE_XLARGE: + failed_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_XLARGE; + is_valid_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID_XLARGE; + path_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH_XLARGE; + break; + case THUMBNAIL_SIZE_XXLARGE: + failed_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_XXLARGE; + is_valid_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID_XXLARGE; + path_attr_id = G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH_XXLARGE; + break; + default: + g_assert_not_reached (); + } + + dirname = get_thumbnail_dirname_from_size (size); uri = g_filename_to_uri (path, NULL, NULL); checksum = g_checksum_new (G_CHECKSUM_MD5); @@ -1439,21 +1510,37 @@ get_thumbnail_attributes (const char *path, basename = g_strconcat (g_checksum_get_string (checksum), ".png", NULL); g_checksum_free (checksum); - for (i = 0; i < G_N_ELEMENTS (size_dirs); i++) + if (dirname) { filename = g_build_filename (g_get_user_cache_dir (), - "thumbnails", size_dirs[i], basename, + "thumbnails", dirname, basename, NULL); - if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) - break; - g_clear_pointer (&filename, g_free); + if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) + g_clear_pointer (&filename, g_free); + } + else + { + gssize i; + + for (i = THUMBNAIL_SIZE_LAST - 1; i >= 0 ; i--) + { + filename = g_build_filename (g_get_user_cache_dir (), + "thumbnails", + get_thumbnail_dirname_from_size (i), + basename, + NULL); + if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) + break; + + g_clear_pointer (&filename, g_free); + } } if (filename) { - _g_file_info_set_attribute_byte_string_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH, filename); - _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID, + _g_file_info_set_attribute_byte_string_by_id (info, path_attr_id, filename); + _g_file_info_set_attribute_boolean_by_id (info, is_valid_attr_id, thumbnail_verify (filename, uri, stat_buf)); } else @@ -1466,11 +1553,12 @@ get_thumbnail_attributes (const char *path, if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) { - _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED, TRUE); - _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID, + _g_file_info_set_attribute_boolean_by_id (info, failed_attr_id, TRUE); + _g_file_info_set_attribute_boolean_by_id (info, is_valid_attr_id, thumbnail_verify (filename, uri, stat_buf)); } } + g_free (basename); g_free (filename); g_free (uri); @@ -2109,10 +2197,47 @@ _g_local_file_info_get (const char *basename, _g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED)) { - if (stat_ok) - get_thumbnail_attributes (path, info, &statbuf); - else - get_thumbnail_attributes (path, info, NULL); + get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_AUTO); + } + + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH_NORMAL) || + _g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID_NORMAL) || + _g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_NORMAL)) + { + get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_NORMAL); + } + + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH_LARGE) || + _g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID_LARGE) || + _g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_LARGE)) + { + get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_LARGE); + } + + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH_XLARGE) || + _g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID_XLARGE) || + _g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_XLARGE)) + { + get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_XLARGE); + } + + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH_XXLARGE) || + _g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID_XXLARGE) || + _g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED_XXLARGE)) + { + get_thumbnail_attributes (path, info, stat_ok ? &statbuf : NULL, THUMBNAIL_SIZE_XXLARGE); } vfs = g_vfs_get_default (); diff --git a/gio/tests/file-thumbnail.c b/gio/tests/file-thumbnail.c index 5fd265f36..254790bb4 100644 --- a/gio/tests/file-thumbnail.c +++ b/gio/tests/file-thumbnail.c @@ -29,6 +29,18 @@ G_FILE_ATTRIBUTE_THUMBNAIL_PATH "," \ G_FILE_ATTRIBUTE_THUMBNAILING_FAILED "," \ G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID "," \ + G_FILE_ATTRIBUTE_THUMBNAIL_PATH_NORMAL "," \ + G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_NORMAL "," \ + G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_NORMAL "," \ + G_FILE_ATTRIBUTE_THUMBNAIL_PATH_LARGE "," \ + G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_LARGE "," \ + G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_LARGE "," \ + G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XLARGE "," \ + G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XLARGE "," \ + G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XLARGE "," \ + G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XXLARGE "," \ + G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XXLARGE "," \ + G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XXLARGE "," \ ) /* Must be kept in order, for priority */ @@ -202,6 +214,48 @@ create_thumbnail_from_test_file (const gchar *source_name, return thumbnail; } +static gboolean +get_size_attributes (const char *size, + const gchar **path, + const gchar **is_valid, + const gchar **failed) +{ + if (g_str_equal (size, "normal")) + { + *path = G_FILE_ATTRIBUTE_THUMBNAIL_PATH_NORMAL; + *is_valid = G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_NORMAL; + *failed = G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_NORMAL; + return TRUE; + } + else if (g_str_equal (size, "large")) + { + *path = G_FILE_ATTRIBUTE_THUMBNAIL_PATH_LARGE; + *is_valid = G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_LARGE; + *failed = G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_LARGE; + return TRUE; + } + else if (g_str_equal (size, "x-large")) + { + *path = G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XLARGE; + *is_valid = G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XLARGE; + *failed = G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XLARGE; + return TRUE; + } + else if (g_str_equal (size, "xx-large")) + { + *path = G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XXLARGE; + *is_valid = G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XXLARGE; + *failed = G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XXLARGE; + return TRUE; + } + + *path = NULL; + *is_valid = NULL; + *failed = NULL; + + return FALSE; +} + static void test_valid_thumbnail_size (gconstpointer data) { @@ -211,6 +265,7 @@ test_valid_thumbnail_size (gconstpointer data) GError *error = NULL; GFileInfo *info; const gchar *size = data; + const gchar *path_attr, *failed_attr, *is_valid_attr; thumbnail = create_thumbnail_from_test_file ("valid.png", size, &source); info = g_file_query_info (source, THUMBNAILS_ATTRIBS, G_FILE_QUERY_INFO_NONE, @@ -227,12 +282,31 @@ test_valid_thumbnail_size (gconstpointer data) ==, g_file_peek_path (thumbnail) ); + g_clear_object (&f); /* TODO: We can't really test this without having a proper thumbnail created g_assert_true ( g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID)); */ + g_assert_true (get_size_attributes (size, &path_attr, &is_valid_attr, &failed_attr)); + + g_assert_true (g_file_info_has_attribute (info, path_attr)); + g_assert_true (g_file_info_has_attribute (info, is_valid_attr)); + g_assert_false (g_file_info_has_attribute (info, failed_attr)); + + f = g_file_new_for_path (g_file_info_get_attribute_byte_string (info, path_attr)); + g_assert_cmpstr ( + g_file_info_get_attribute_byte_string (info, path_attr), + ==, + g_file_peek_path (thumbnail) + ); + g_clear_object (&f); + + /* TODO: We can't really test this without having a proper thumbnail created + g_assert_true (g_file_info_get_attribute_boolean (info, is_valid_attr)); + */ + g_clear_object (&source); g_clear_object (&thumbnail); g_clear_error (&error); @@ -258,6 +332,22 @@ test_unknown_thumbnail_size (gconstpointer data) g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID)); g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED)); + g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH_NORMAL)); + g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_NORMAL)); + g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_NORMAL)); + + g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH_LARGE)); + g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_LARGE)); + g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_LARGE)); + + g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XLARGE)); + g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XLARGE)); + g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XLARGE)); + + g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XXLARGE)); + g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XXLARGE)); + g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XXLARGE)); + g_clear_object (&source); g_clear_object (&thumbnail); g_clear_error (&error); @@ -309,6 +399,7 @@ test_thumbnails_size_priority (void) for (i = 0; i < G_N_ELEMENTS (SIZES_NAMES); i++) { GFile *thumbnail = create_thumbnail (source, SIZES_NAMES[i]); + const gchar *path_attr, *failed_attr, *is_valid_attr; GFile *f; g_ptr_array_add (sized_thumbnails, thumbnail); @@ -327,6 +418,21 @@ test_thumbnails_size_priority (void) ==, g_file_peek_path (thumbnail) ); + g_clear_object (&f); + + g_assert_true (get_size_attributes (SIZES_NAMES[i], + &path_attr, &is_valid_attr, &failed_attr)); + + g_assert_true (g_file_info_has_attribute (info, path_attr)); + g_assert_true (g_file_info_has_attribute (info, is_valid_attr)); + g_assert_false (g_file_info_has_attribute (info, failed_attr)); + + f = g_file_new_for_path (g_file_info_get_attribute_byte_string (info, path_attr)); + g_assert_cmpstr ( + g_file_peek_path (f), + ==, + g_file_peek_path (thumbnail) + ); g_clear_object (&info); g_clear_object (&f); @@ -334,11 +440,41 @@ test_thumbnails_size_priority (void) g_assert_cmpuint (sized_thumbnails->len, ==, G_N_ELEMENTS (SIZES_NAMES)); + /* Ensuring we can access to all the thumbnails by explicit size request */ + for (i = 0; i < G_N_ELEMENTS (SIZES_NAMES); i++) + { + GFile *thumbnail = g_ptr_array_index (sized_thumbnails, i); + const gchar *path_attr, *failed_attr, *is_valid_attr; + GFile *f; + + info = g_file_query_info (source, THUMBNAILS_ATTRIBS, + G_FILE_QUERY_INFO_NONE, NULL, &error); + g_assert_no_error (error); + + g_assert_true (get_size_attributes (SIZES_NAMES[i], + &path_attr, &is_valid_attr, &failed_attr)); + + g_assert_true (g_file_info_has_attribute (info, path_attr)); + g_assert_true (g_file_info_has_attribute (info, is_valid_attr)); + g_assert_false (g_file_info_has_attribute (info, failed_attr)); + + f = g_file_new_for_path (g_file_info_get_attribute_byte_string (info, path_attr)); + g_assert_cmpstr ( + g_file_peek_path (f), + ==, + g_file_peek_path (thumbnail) + ); + g_clear_object (&f); + + g_clear_object (&info); + } + /* Now removing them in the inverse order, to check this again */ for (i = G_N_ELEMENTS (SIZES_NAMES); i > 1; i--) { GFile *thumbnail = g_ptr_array_index (sized_thumbnails, i - 1); GFile *less_priority_thumbnail = g_ptr_array_index (sized_thumbnails, i - 2); + const gchar *path_attr, *failed_attr, *is_valid_attr; GFile *f; g_file_delete (thumbnail, NULL, &error); @@ -358,6 +494,21 @@ test_thumbnails_size_priority (void) ==, g_file_peek_path (less_priority_thumbnail) ); + g_clear_object (&f); + + g_assert_true (get_size_attributes (SIZES_NAMES[i-2], + &path_attr, &is_valid_attr, &failed_attr)); + + g_assert_true (g_file_info_has_attribute (info, path_attr)); + g_assert_true (g_file_info_has_attribute (info, is_valid_attr)); + g_assert_false (g_file_info_has_attribute (info, failed_attr)); + + f = g_file_new_for_path (g_file_info_get_attribute_byte_string (info, path_attr)); + g_assert_cmpstr ( + g_file_peek_path (f), + ==, + g_file_peek_path (less_priority_thumbnail) + ); g_clear_object (&info); g_clear_object (&f); @@ -382,6 +533,28 @@ test_thumbnails_size_priority (void) g_clear_object (&info); + /* And check if we get the failed state for all explicit requests */ + for (i = 0; i < G_N_ELEMENTS (SIZES_NAMES); i++) + { + const gchar *path_attr, *failed_attr, *is_valid_attr; + + info = g_file_query_info (source, THUMBNAILS_ATTRIBS, + G_FILE_QUERY_INFO_NONE, NULL, &error); + g_assert_no_error (error); + + g_assert_true (get_size_attributes (SIZES_NAMES[i], + &path_attr, &is_valid_attr, &failed_attr)); + + g_assert_false (g_file_info_has_attribute (info, path_attr)); + g_assert_true (g_file_info_has_attribute (info, is_valid_attr)); + g_assert_true (g_file_info_has_attribute (info, failed_attr)); + + g_assert_false (g_file_info_get_attribute_boolean (info, is_valid_attr)); + g_assert_true (g_file_info_get_attribute_boolean (info, failed_attr)); + + g_clear_object (&info); + } + /* Removing the failed thumbnail too, so no thumbnail should be available */ g_file_delete (failed_thumbnail, NULL, &error); g_assert_no_error (error); @@ -394,6 +567,26 @@ test_thumbnails_size_priority (void) g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID)); g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED)); + g_clear_object (&info); + + for (i = 0; i < G_N_ELEMENTS (SIZES_NAMES); i++) + { + const gchar *path_attr, *failed_attr, *is_valid_attr; + + info = g_file_query_info (source, THUMBNAILS_ATTRIBS, + G_FILE_QUERY_INFO_NONE, NULL, &error); + g_assert_no_error (error); + + g_assert_true (get_size_attributes (SIZES_NAMES[i], + &path_attr, &is_valid_attr, &failed_attr)); + + g_assert_false (g_file_info_has_attribute (info, path_attr)); + g_assert_false (g_file_info_has_attribute (info, is_valid_attr)); + g_assert_false (g_file_info_has_attribute (info, failed_attr)); + + g_clear_object (&info); + } + g_clear_object (&source); g_clear_pointer (&sized_thumbnails, g_ptr_array_unref); g_clear_object (&failed_thumbnail);