mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-02 17:26:17 +01:00
Merge branch 'more-gio-thumbnail-sizes' into 'main'
glocalfileinfo: Add support for xx-large and x-large thumbnails Closes #2767 See merge request GNOME/glib!2941
This commit is contained in:
commit
5d504709ab
@ -1426,8 +1426,10 @@ get_thumbnail_attributes (const char *path,
|
||||
{
|
||||
GChecksum *checksum;
|
||||
char *uri;
|
||||
char *filename;
|
||||
char *filename = NULL;
|
||||
char *basename;
|
||||
const char *size_dirs[4] = { "xx-large", "x-large", "large", "normal" };
|
||||
gsize i;
|
||||
|
||||
uri = g_filename_to_uri (path, NULL, NULL);
|
||||
|
||||
@ -1437,11 +1439,18 @@ 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++)
|
||||
{
|
||||
filename = g_build_filename (g_get_user_cache_dir (),
|
||||
"thumbnails", "large", basename,
|
||||
"thumbnails", size_dirs[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,
|
||||
@ -1449,20 +1458,6 @@ get_thumbnail_attributes (const char *path,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (filename);
|
||||
filename = g_build_filename (g_get_user_cache_dir (),
|
||||
"thumbnails", "normal", basename,
|
||||
NULL);
|
||||
|
||||
if (g_file_test (filename, G_FILE_TEST_IS_REGULAR))
|
||||
{
|
||||
_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,
|
||||
thumbnail_verify (filename, uri, stat_buf));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (filename);
|
||||
filename = g_build_filename (g_get_user_cache_dir (),
|
||||
"thumbnails", "fail",
|
||||
"gnome-thumbnail-factory",
|
||||
@ -1476,7 +1471,6 @@ get_thumbnail_attributes (const char *path,
|
||||
thumbnail_verify (filename, uri, stat_buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
g_free (basename);
|
||||
g_free (filename);
|
||||
g_free (uri);
|
||||
|
426
gio/tests/file-thumbnail.c
Normal file
426
gio/tests/file-thumbnail.c
Normal file
@ -0,0 +1,426 @@
|
||||
/* Unit tests for GFile thumbnails
|
||||
* GIO - GLib Input, Output and Streaming Library
|
||||
*
|
||||
* Copyright (C) 2022 Marco Trevisan
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Marco Trevisan <marco.trevisan@canonical.com>
|
||||
*/
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#define THUMBNAIL_FAIL_SIZE "fail"
|
||||
|
||||
#define THUMBNAILS_ATTRIBS ( \
|
||||
G_FILE_ATTRIBUTE_THUMBNAIL_PATH "," \
|
||||
G_FILE_ATTRIBUTE_THUMBNAILING_FAILED "," \
|
||||
G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID "," \
|
||||
)
|
||||
|
||||
/* Must be kept in order, for priority */
|
||||
static const char * SIZES_NAMES[] = {
|
||||
"normal",
|
||||
"large",
|
||||
"x-large",
|
||||
"xx-large",
|
||||
};
|
||||
|
||||
static GFile *
|
||||
get_thumbnail_src_file (const gchar *name)
|
||||
{
|
||||
const gchar *thumbnail_path;
|
||||
thumbnail_path = g_test_get_filename (G_TEST_DIST, "thumbnails",
|
||||
name, NULL);
|
||||
|
||||
g_assert_true (g_file_test (thumbnail_path, G_FILE_TEST_IS_REGULAR));
|
||||
|
||||
return g_file_new_for_path (thumbnail_path);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_thumbnail_basename (GFile *source)
|
||||
{
|
||||
GChecksum *checksum;
|
||||
gchar *uri = g_file_get_uri (source);
|
||||
gchar *basename;
|
||||
|
||||
checksum = g_checksum_new (G_CHECKSUM_MD5);
|
||||
g_checksum_update (checksum, (const guchar *) uri, strlen (uri));
|
||||
|
||||
basename = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
|
||||
|
||||
g_checksum_free (checksum);
|
||||
g_free (uri);
|
||||
|
||||
return basename;
|
||||
}
|
||||
|
||||
static GFile *
|
||||
get_expected_thumbnail_file (GFile *source,
|
||||
const gchar *size)
|
||||
{
|
||||
GFile *file;
|
||||
gchar *basename;
|
||||
|
||||
basename = get_thumbnail_basename (source);
|
||||
file = g_file_new_build_filename (g_get_user_cache_dir (),
|
||||
"thumbnails",
|
||||
size,
|
||||
basename,
|
||||
NULL);
|
||||
g_free (basename);
|
||||
return file;
|
||||
}
|
||||
|
||||
static GFile *
|
||||
get_failed_thumbnail_file (GFile *source)
|
||||
{
|
||||
GFile *file;
|
||||
gchar *basename;
|
||||
|
||||
basename = get_thumbnail_basename (source);
|
||||
file = g_file_new_build_filename (g_get_user_cache_dir (),
|
||||
"thumbnails", THUMBNAIL_FAIL_SIZE,
|
||||
"gnome-thumbnail-factory",
|
||||
basename,
|
||||
NULL);
|
||||
g_free (basename);
|
||||
return file;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_thumbnail_exists (GFile *source,
|
||||
const gchar *size)
|
||||
{
|
||||
GFile *thumbnail;
|
||||
gboolean ret;
|
||||
|
||||
thumbnail = get_expected_thumbnail_file (source, size);
|
||||
g_assert_nonnull (thumbnail);
|
||||
|
||||
ret = g_file_query_exists (thumbnail, NULL);
|
||||
g_clear_object (&thumbnail);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_failed_thumbnail_exists (GFile *source)
|
||||
{
|
||||
GFile *thumbnail;
|
||||
gboolean ret;
|
||||
|
||||
thumbnail = get_failed_thumbnail_file (source);
|
||||
g_assert_nonnull (thumbnail);
|
||||
|
||||
ret = g_file_query_exists (thumbnail, NULL);
|
||||
g_clear_object (&thumbnail);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GFile *
|
||||
create_thumbnail (GFile *source,
|
||||
const gchar *size)
|
||||
{
|
||||
GFile *thumbnail;
|
||||
GFile *thumbnail_dir;
|
||||
GError *error = NULL;
|
||||
gchar *thumbnail_path;
|
||||
|
||||
/* TODO: This is just a stub implementation to create a fake thumbnail file
|
||||
* We should implement a real thumbnail generator, but we don't care here.
|
||||
*/
|
||||
|
||||
if (!size || g_strcmp0 (size, THUMBNAIL_FAIL_SIZE) == 0)
|
||||
thumbnail = get_failed_thumbnail_file (source);
|
||||
else
|
||||
thumbnail = get_expected_thumbnail_file (source, size);
|
||||
|
||||
thumbnail_dir = g_file_get_parent (thumbnail);
|
||||
|
||||
if (!g_file_query_exists (thumbnail_dir, NULL))
|
||||
{
|
||||
g_file_make_directory_with_parents (thumbnail_dir, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
g_file_copy (source, thumbnail, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_true (g_file_query_exists (thumbnail, NULL));
|
||||
thumbnail_path = g_file_get_path (thumbnail);
|
||||
g_test_message ("Created test thumbnail at %s", thumbnail_path);
|
||||
|
||||
g_clear_object (&thumbnail_dir);
|
||||
g_clear_error (&error);
|
||||
g_free (thumbnail_path);
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
static GFile *
|
||||
create_thumbnail_from_test_file (const gchar *source_name,
|
||||
const gchar *size,
|
||||
GFile **out_source)
|
||||
{
|
||||
GFile *thumbnail;
|
||||
GFile *source = get_thumbnail_src_file (source_name);
|
||||
|
||||
thumbnail = create_thumbnail (source, size);
|
||||
|
||||
if (!size || g_strcmp0 (size, THUMBNAIL_FAIL_SIZE) == 0)
|
||||
{
|
||||
g_assert_true (check_failed_thumbnail_exists (source));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_false (check_failed_thumbnail_exists (source));
|
||||
g_assert_true (check_thumbnail_exists (source, size));
|
||||
}
|
||||
|
||||
if (out_source)
|
||||
*out_source = g_steal_pointer (&source);
|
||||
|
||||
g_clear_object (&source);
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
static void
|
||||
test_valid_thumbnail_size (gconstpointer data)
|
||||
{
|
||||
GFile *source;
|
||||
GFile *thumbnail;
|
||||
GError *error = NULL;
|
||||
GFileInfo *info;
|
||||
const gchar *size = data;
|
||||
char *thumbnail_path;
|
||||
|
||||
thumbnail = create_thumbnail_from_test_file ("valid.png", size, &source);
|
||||
info = g_file_query_info (source, THUMBNAILS_ATTRIBS, G_FILE_QUERY_INFO_NONE,
|
||||
NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
thumbnail_path = g_file_get_path (thumbnail);
|
||||
|
||||
g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
|
||||
g_assert_true (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_cmpstr (
|
||||
g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH),
|
||||
==,
|
||||
thumbnail_path
|
||||
);
|
||||
|
||||
/* 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_clear_object (&source);
|
||||
g_clear_object (&thumbnail);
|
||||
g_clear_error (&error);
|
||||
g_clear_object (&info);
|
||||
g_free (thumbnail_path);
|
||||
}
|
||||
|
||||
static void
|
||||
test_unknown_thumbnail_size (gconstpointer data)
|
||||
{
|
||||
GFile *source;
|
||||
GFile *thumbnail;
|
||||
GError *error = NULL;
|
||||
GFileInfo *info;
|
||||
const gchar *size = data;
|
||||
|
||||
thumbnail = create_thumbnail_from_test_file ("valid.png", size, &source);
|
||||
info = g_file_query_info (source, THUMBNAILS_ATTRIBS, G_FILE_QUERY_INFO_NONE,
|
||||
NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
|
||||
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 (&source);
|
||||
g_clear_object (&thumbnail);
|
||||
g_clear_error (&error);
|
||||
g_clear_object (&info);
|
||||
}
|
||||
|
||||
static void
|
||||
test_failed_thumbnail (void)
|
||||
{
|
||||
GFile *source;
|
||||
GFile *thumbnail;
|
||||
GError *error = NULL;
|
||||
GFileInfo *info;
|
||||
|
||||
thumbnail = create_thumbnail_from_test_file ("valid.png", NULL, &source);
|
||||
info = g_file_query_info (source, THUMBNAILS_ATTRIBS, G_FILE_QUERY_INFO_NONE,
|
||||
NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
|
||||
g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
|
||||
g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
|
||||
|
||||
g_assert_false (
|
||||
g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
|
||||
g_assert_true (
|
||||
g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
|
||||
|
||||
g_clear_object (&source);
|
||||
g_clear_object (&thumbnail);
|
||||
g_clear_error (&error);
|
||||
g_clear_object (&info);
|
||||
}
|
||||
|
||||
static void
|
||||
test_thumbnails_size_priority (void)
|
||||
{
|
||||
GPtrArray *sized_thumbnails;
|
||||
GError *error = NULL;
|
||||
GFileInfo *info;
|
||||
GFile *source;
|
||||
GFile *failed_thumbnail;
|
||||
gsize i;
|
||||
|
||||
failed_thumbnail = create_thumbnail_from_test_file ("valid.png", NULL, &source);
|
||||
sized_thumbnails = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
|
||||
/* Checking that each thumbnail with higher priority override the previous */
|
||||
for (i = 0; i < G_N_ELEMENTS (SIZES_NAMES); i++)
|
||||
{
|
||||
GFile *thumbnail = create_thumbnail (source, SIZES_NAMES[i]);
|
||||
gchar *thumbnail_path = g_file_get_path (thumbnail);
|
||||
|
||||
g_ptr_array_add (sized_thumbnails, thumbnail);
|
||||
|
||||
info = g_file_query_info (source, THUMBNAILS_ATTRIBS,
|
||||
G_FILE_QUERY_INFO_NONE, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
|
||||
g_assert_true (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_cmpstr (
|
||||
g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH),
|
||||
==,
|
||||
thumbnail_path
|
||||
);
|
||||
|
||||
g_free (thumbnail_path);
|
||||
g_clear_object (&info);
|
||||
}
|
||||
|
||||
g_assert_cmpuint (sized_thumbnails->len, ==, G_N_ELEMENTS (SIZES_NAMES));
|
||||
|
||||
/* 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);
|
||||
gchar *thumbnail_path = g_file_get_path (less_priority_thumbnail);
|
||||
|
||||
g_file_delete (thumbnail, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
info = g_file_query_info (source, THUMBNAILS_ATTRIBS,
|
||||
G_FILE_QUERY_INFO_NONE, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
|
||||
g_assert_true (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_cmpstr (
|
||||
g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH),
|
||||
==,
|
||||
thumbnail_path
|
||||
);
|
||||
|
||||
g_free (thumbnail_path);
|
||||
g_clear_object (&info);
|
||||
}
|
||||
|
||||
/* And now let's remove the last valid one, so that failed should have priority */
|
||||
g_file_delete (G_FILE (g_ptr_array_index (sized_thumbnails, 0)), NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
info = g_file_query_info (source, THUMBNAILS_ATTRIBS, G_FILE_QUERY_INFO_NONE,
|
||||
NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
|
||||
g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
|
||||
g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
|
||||
|
||||
g_assert_false (
|
||||
g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
|
||||
g_assert_true (
|
||||
g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
|
||||
|
||||
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);
|
||||
|
||||
info = g_file_query_info (source, THUMBNAILS_ATTRIBS, G_FILE_QUERY_INFO_NONE,
|
||||
NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
|
||||
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 (&source);
|
||||
g_clear_pointer (&sized_thumbnails, g_ptr_array_unref);
|
||||
g_clear_object (&failed_thumbnail);
|
||||
g_clear_error (&error);
|
||||
g_clear_object (&info);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
gsize i;
|
||||
|
||||
g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (SIZES_NAMES); i++)
|
||||
{
|
||||
gchar *test_path;
|
||||
|
||||
test_path = g_strconcat ("/file-thumbnail/valid/", SIZES_NAMES[i], NULL);
|
||||
g_test_add_data_func (test_path, SIZES_NAMES[i], test_valid_thumbnail_size);
|
||||
g_free (test_path);
|
||||
}
|
||||
|
||||
g_test_add_data_func ("/file-thumbnail/unknown/super-large", "super-large", test_unknown_thumbnail_size);
|
||||
g_test_add_func ("/file-thumbnail/fail", test_failed_thumbnail);
|
||||
g_test_add_func ("/file-thumbnail/size-priority", test_thumbnails_size_priority);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
@ -63,6 +63,7 @@ gio_tests = {
|
||||
'data-input-stream' : {},
|
||||
'data-output-stream' : {},
|
||||
'error': {},
|
||||
'file-thumbnail' : {},
|
||||
'fileattributematcher' : {},
|
||||
'filter-streams' : {},
|
||||
'giomodule' : {
|
||||
|
Loading…
Reference in New Issue
Block a user