Commit d5552daf authored by Sven Neumann's avatar Sven Neumann Committed by Sven Neumann

libgimpthumb/gimpthumb-utils.c libgimpthumb/gimpthumb-utils.[ch] added

2004-10-10  Sven Neumann  <sven@gimp.org>

	* libgimpthumb/gimpthumb-utils.c
	* libgimpthumb/gimpthumb-utils.[ch]
	* libgimpthumb/gimpthumbnail.c: added support for local thumbnails
	as introduced by version 0.7 of the thumbnail spec. Untested, but
	at least the API is there.
parent cbfc867d
2004-10-10 Sven Neumann <sven@gimp.org>
* libgimpthumb/gimpthumb-utils.c
* libgimpthumb/gimpthumb-utils.[ch]
* libgimpthumb/gimpthumbnail.c: added support for local thumbnails
as introduced by version 0.7 of the thumbnail spec. Untested, but
at least the API is there.
2004-10-10 DindinX <dindinx@gimp.org>
* plug-ins/common/AlienMap2.c: ported to GimpAspectPreview, and some
......
2004-10-10 Sven Neumann <sven@gimp.org>
* libgimpthumb/libgimpthumb-sections.txt
* libgimpthumb/tmpl/gimpthumb-utils.sgml
* libgimpthumb/tmpl/gimpthumbnail.sgml: updated for new API.
2004-10-06 Michael Natterer <mitch@gimp.org>
* libgimp/tmpl/gimpgradient.sgml: s/gimpgradientedit/gimpgradient/
......
......@@ -11,6 +11,7 @@ gimp_thumbnail_peek_thumb
gimp_thumbnail_load_thumb
gimp_thumbnail_save_thumb
gimp_thumbnail_save_failure
gimp_thumbnail_save_thumb_local
<SUBSECTION Standard>
GimpThumbnailClass
GIMP_THUMBNAIL
......@@ -30,6 +31,9 @@ gimp_thumb_find_thumb
gimp_thumb_file_test
gimp_thumb_ensure_thumb_dir
gimp_thumb_get_thumb_dir
gimp_thumb_name_from_uri_local
gimp_thumb_ensure_thumb_dir_local
gimp_thumb_get_thumb_dir_local
</SECTION>
<SECTION>
......
......@@ -75,3 +75,34 @@ Utility functions provided and used by libgimpthumb
@Returns:
<!-- ##### FUNCTION gimp_thumb_name_from_uri_local ##### -->
<para>
</para>
@uri:
@size:
@Returns:
<!-- ##### FUNCTION gimp_thumb_ensure_thumb_dir_local ##### -->
<para>
</para>
@dirname:
@size:
@error:
@Returns:
<!-- ##### FUNCTION gimp_thumb_get_thumb_dir_local ##### -->
<para>
</para>
@dirname:
@size:
@Returns:
......@@ -163,3 +163,15 @@ using object properties.
@Returns:
<!-- ##### FUNCTION gimp_thumbnail_save_thumb_local ##### -->
<para>
</para>
@thumbnail:
@pixbuf:
@software:
@error:
@Returns:
......@@ -48,19 +48,22 @@
#include "libgimp/libgimp-intl.h"
static gint gimp_thumb_size (GimpThumbSize size);
static const gchar * gimp_thumb_png_name (const gchar *uri);
static void gimp_thumb_exit (void);
static gint gimp_thumb_size (GimpThumbSize size);
static gchar * gimp_thumb_png_lookup (const gchar *name,
const gchar *basedir,
GimpThumbSize *size);
static const gchar * gimp_thumb_png_name (const gchar *uri);
static void gimp_thumb_exit (void);
static gboolean gimp_thumb_initialized = FALSE;
static gint thumb_num_sizes = 0;
static gint *thumb_sizes = NULL;
static gchar *thumb_dir = NULL;
static gchar **thumb_subdirs = NULL;
static gchar *thumb_fail_subdir = NULL;
static gboolean gimp_thumb_initialized = FALSE;
static gint thumb_num_sizes = 0;
static gint *thumb_sizes = NULL;
static const gchar **thumb_sizenames = NULL;
static gchar *thumb_dir = NULL;
static gchar **thumb_subdirs = NULL;
static gchar *thumb_fail_subdir = NULL;
/**
......@@ -110,20 +113,24 @@ gimp_thumb_init (const gchar *creator,
thumb_num_sizes = enum_class->n_values;
thumb_sizes = g_new (gint, thumb_num_sizes);
thumb_sizenames = g_new (const gchar *, thumb_num_sizes);
thumb_subdirs = g_new (gchar *, thumb_num_sizes);
for (i = 0, enum_value = enum_class->values;
i < enum_class->n_values;
i++, enum_value++)
{
thumb_sizes[i] = enum_value->value;
thumb_subdirs[i] = g_build_filename (thumb_dir,
enum_value->value_nick, NULL);
thumb_sizes[i] = enum_value->value;
thumb_sizenames[i] = enum_value->value_nick;
thumb_subdirs[i] = g_build_filename (thumb_dir,
enum_value->value_nick, NULL);
}
thumb_fail_subdir = thumb_subdirs[0];
thumb_subdirs[0] = g_build_filename (thumb_fail_subdir, creator, NULL);
g_type_class_unref (enum_class);
gimp_thumb_initialized = TRUE;
return gimp_thumb_initialized;
......@@ -133,7 +140,7 @@ gimp_thumb_init (const gchar *creator,
* gimp_thumb_get_thumb_dir:
* @size: a GimpThumbSize
*
* Retrieve the name of a thumbnail folder for a specific size. The
* Retrieve the name of the thumbnail folder for a specific size. The
* returned pointer will become invalid if gimp_thumb_init() is used
* again. It must not be changed or freed.
*
......@@ -149,6 +156,32 @@ gimp_thumb_get_thumb_dir (GimpThumbSize size)
return thumb_subdirs[size];
}
/**
* gimp_thumb_get_thumb_dir_local:
* @dirname:
* @size: a GimpThumbSize
*
* Retrieve the name of the local thumbnail folder for a specific
* size. Unlike gimp_thumb_get_thumb_dir() the returned string is not
* constant and should be free'd when it is not any longer needed.
*
* Return value: the thumbnail directory in the encoding of the filesystem
*
* Since: GIMP 2.2
**/
gchar *
gimp_thumb_get_thumb_dir_local (const gchar *dirname,
GimpThumbSize size)
{
g_return_val_if_fail (gimp_thumb_initialized, FALSE);
g_return_val_if_fail (dirname != NULL, NULL);
g_return_val_if_fail (size > GIMP_THUMB_SIZE_FAIL, NULL);
size = gimp_thumb_size (size);
return g_build_filename (dirname, thumb_sizenames[size], NULL);
}
/**
* gimp_thumb_ensure_thumb_dir:
* @size: a GimpThumbSize
......@@ -169,32 +202,100 @@ gboolean
gimp_thumb_ensure_thumb_dir (GimpThumbSize size,
GError **error)
{
gint i;
g_return_val_if_fail (gimp_thumb_initialized, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
i = gimp_thumb_size (size);
size = gimp_thumb_size (size);
if (g_file_test (thumb_subdirs[i], G_FILE_TEST_IS_DIR))
if (g_file_test (thumb_subdirs[size], G_FILE_TEST_IS_DIR))
return TRUE;
if (g_file_test (thumb_dir, G_FILE_TEST_IS_DIR) ||
(mkdir (thumb_dir, S_IRUSR | S_IWUSR | S_IXUSR) == 0))
{
if (i == 0)
if (size == 0)
mkdir (thumb_fail_subdir, S_IRUSR | S_IWUSR | S_IXUSR);
mkdir (thumb_subdirs[i], S_IRUSR | S_IWUSR | S_IXUSR);
mkdir (thumb_subdirs[size], S_IRUSR | S_IWUSR | S_IXUSR);
}
if (g_file_test (thumb_subdirs[i], G_FILE_TEST_IS_DIR))
if (g_file_test (thumb_subdirs[size], G_FILE_TEST_IS_DIR))
return TRUE;
g_set_error (error,
GIMP_THUMB_ERROR, GIMP_THUMB_ERROR_MKDIR,
_("Failed to create thumbnail folder '%s'."),
thumb_subdirs[i]);
thumb_subdirs[size]);
return FALSE;
}
/**
* gimp_thumb_ensure_thumb_dir_local:
* @dirname:
* @size: a GimpThumbSize
* @error: return location for possible errors
*
* This function checks if the directory that is required to store
* local thumbnails for a particular @size exist and attempts to
* create it if necessary.
*
* You shouldn't have to call this function directly since
* gimp_thumbnail_save_thumb_local() will do this for you.
*
* Return value: %TRUE is the directory exists, %FALSE if it could not
* be created
*
* Since: GIMP 2.2
**/
gboolean
gimp_thumb_ensure_thumb_dir_local (const gchar *dirname,
GimpThumbSize size,
GError **error)
{
gchar *basedir;
gchar *subdir;
g_return_val_if_fail (gimp_thumb_initialized, FALSE);
g_return_val_if_fail (dirname != NULL, FALSE);
g_return_val_if_fail (g_path_is_absolute (dirname), FALSE);
g_return_val_if_fail (size > GIMP_THUMB_SIZE_FAIL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
size = gimp_thumb_size (size);
subdir = g_build_filename (dirname,
".thumblocal", thumb_sizenames[size],
NULL);
if (g_file_test (subdir, G_FILE_TEST_IS_DIR))
{
g_free (subdir);
return TRUE;
}
basedir = g_build_filename (dirname, ".thumblocal", NULL);
if (g_file_test (basedir, G_FILE_TEST_IS_DIR) ||
(mkdir (thumb_dir, S_IRUSR | S_IWUSR | S_IXUSR) == 0))
{
mkdir (subdir, S_IRUSR | S_IWUSR | S_IXUSR);
}
g_free (basedir);
if (g_file_test (subdir, G_FILE_TEST_IS_DIR))
{
g_free (subdir);
return TRUE;
}
g_set_error (error,
GIMP_THUMB_ERROR, GIMP_THUMB_ERROR_MKDIR,
_("Failed to create thumbnail folder '%s'."),
subdir);
g_free (subdir);
return FALSE;
}
......@@ -207,24 +308,78 @@ gimp_thumb_ensure_thumb_dir (GimpThumbSize size,
* belongs to an image file located at the given @uri.
*
* Return value: a newly allocated filename in the encoding of the
* filesystem or %NULL if you attempt to create thumbnails
* for files in the thumbnail directory.
* filesystem or %NULL if @uri points to the global
* thumbnail repository.
**/
gchar *
gimp_thumb_name_from_uri (const gchar *uri,
GimpThumbSize size)
{
gint i;
g_return_val_if_fail (gimp_thumb_initialized, NULL);
g_return_val_if_fail (uri != NULL, NULL);
if (strstr (uri, thumb_dir))
return NULL;
size = gimp_thumb_size (size);
return g_build_filename (thumb_subdirs[size],
gimp_thumb_png_name (uri),
NULL);
}
/**
* gimp_thumb_name_from_uri_local:
* @uri: an escaped URI in UTF-8 encoding
* @size: a #GimpThumbSize
*
* Creates the name of a local thumbnail file of the specified @size
* that belongs to an image file located at the given @uri. Local
* thumbnails have been introduced with version 0.7 of the spec.
*
* Return value: a newly allocated filename in the encoding of the
* filesystem or %NULL if @uri is a remote file or
* points to the global thumbnail repository.
*
* Since: GIMP 2.2
**/
gchar *
gimp_thumb_name_from_uri_local (const gchar *uri,
GimpThumbSize size)
{
gchar *filename;
gchar *result = NULL;
g_return_val_if_fail (gimp_thumb_initialized, NULL);
g_return_val_if_fail (uri != NULL, NULL);
g_return_val_if_fail (size > GIMP_THUMB_SIZE_FAIL, NULL);
if (strstr (uri, thumb_dir))
return NULL;
i = gimp_thumb_size (size);
filename = g_filename_from_uri (uri, NULL, NULL);
if (filename)
{
const gchar *baseuri = strrchr (uri, '/');
if (baseuri && baseuri[0] && baseuri[1])
{
gchar *dirname = g_path_get_dirname (filename);
gint i = gimp_thumb_size (size);
result = g_build_filename (dirname,
".thumblocal", thumb_sizenames[i],
gimp_thumb_png_name (uri),
NULL);
return g_build_filename (thumb_subdirs[i], gimp_thumb_png_name (uri), NULL);
g_free (dirname);
}
g_free (filename);
}
return result;
}
/**
......@@ -235,9 +390,14 @@ gimp_thumb_name_from_uri (const gchar *uri,
* This function attempts to locate a thumbnail for the given
* @url. First it tries the size that is stored at @size. If no
* thumbnail of that size is found, it will look for a larger
* thumbnail, then falling back to a smaller size. If a thumbnail is
* found, it's size is written to the variable pointer to by @size
* and the file location is returned.
* thumbnail, then falling back to a smaller size.
*
* If the global thumbnail repository doesn't provide a thumbnail but
* a local thumbnail repository exists for the folder the image is
* located in, the same search is done among the local thumbnails.
*
* If a thumbnail is found, it's size is written to the variable
* pointer to by @size and the file location is returned.
*
* Return value: a newly allocated string in the encoding of the
* filesystem or %NULL if no thumbnail for @uri was found
......@@ -246,48 +406,38 @@ gchar *
gimp_thumb_find_thumb (const gchar *uri,
GimpThumbSize *size)
{
const gchar *name;
gchar *thumb_name;
gint i, n;
gchar *result;
g_return_val_if_fail (gimp_thumb_initialized, NULL);
g_return_val_if_fail (uri != NULL, NULL);
g_return_val_if_fail (size != NULL, NULL);
g_return_val_if_fail (*size > GIMP_THUMB_SIZE_FAIL, NULL);
name = gimp_thumb_png_name (uri);
i = n = gimp_thumb_size (*size);
result = gimp_thumb_png_lookup (gimp_thumb_png_name (uri), NULL, size);
for (; i < thumb_num_sizes; i++)
if (! result)
{
thumb_name = g_build_filename (thumb_subdirs[i], name, NULL);
gchar *filename = g_filename_from_uri (uri, NULL, NULL);
if (gimp_thumb_file_test (thumb_name, NULL, NULL, NULL) ==
GIMP_THUMB_FILE_TYPE_REGULAR)
if (filename)
{
*size = thumb_sizes[i];
return thumb_name;
}
const gchar *baseuri = strrchr (uri, '/');
g_free (thumb_name);
}
if (baseuri && baseuri[0] && baseuri[1])
{
gchar *dirname = g_path_get_dirname (filename);
for (i = n - 1; i >= 0; i--)
{
thumb_name = g_build_filename (thumb_subdirs[i], name, NULL);
result = gimp_thumb_png_lookup (gimp_thumb_png_name (baseuri + 1),
dirname, size);
if (gimp_thumb_file_test (thumb_name, NULL, NULL, NULL) ==
GIMP_THUMB_FILE_TYPE_REGULAR)
{
*size = thumb_sizes[i];
return thumb_name;
}
g_free (dirname);
}
g_free (thumb_name);
g_free (filename);
}
}
return NULL;
return result;
}
/**
......@@ -346,6 +496,7 @@ gimp_thumb_exit (void)
g_free (thumb_dir);
g_free (thumb_sizes);
g_free (thumb_sizenames);
for (i = 0; i < thumb_num_sizes; i++)
g_free (thumb_subdirs[i]);
g_free (thumb_subdirs);
......@@ -353,6 +504,7 @@ gimp_thumb_exit (void)
thumb_num_sizes = 0;
thumb_sizes = NULL;
thumb_sizenames = NULL;
thumb_dir = NULL;
thumb_subdirs = NULL;
thumb_fail_subdir = NULL;
......@@ -378,6 +530,92 @@ gimp_thumb_size (GimpThumbSize size)
return i;
}
static gchar *
gimp_thumb_png_lookup (const gchar *name,
const gchar *basedir,
GimpThumbSize *size)
{
gchar *thumb_name = NULL;
gchar **subdirs = NULL;
gint i, n;
if (basedir)
{
gchar *dir = g_build_filename (basedir, ".thumblocal", NULL);
if (g_file_test (basedir, G_FILE_TEST_IS_DIR))
{
gint i;
subdirs = g_new (gchar *, thumb_num_sizes);
subdirs[0] = NULL; /* GIMP_THUMB_SIZE_FAIL */
for (i = 1; i < thumb_num_sizes; i++)
subdirs[i] = g_build_filename (dir, thumb_sizenames[i], NULL);
}
g_free (dir);
}
else
{
subdirs = thumb_subdirs;
}
if (! subdirs)
return NULL;
i = n = gimp_thumb_size (*size);
for (; i < thumb_num_sizes; i++)
{
if (! subdirs[i])
continue;
thumb_name = g_build_filename (subdirs[i], name, NULL);
if (gimp_thumb_file_test (thumb_name,
NULL, NULL,
NULL) == GIMP_THUMB_FILE_TYPE_REGULAR)
{
*size = thumb_sizes[i];
goto finish;
}
g_free (thumb_name);
}
for (i = n - 1; i >= 0; i--)
{
if (! subdirs[i])
continue;
thumb_name = g_build_filename (subdirs[i], name, NULL);
if (gimp_thumb_file_test (thumb_name,
NULL, NULL,
NULL) == GIMP_THUMB_FILE_TYPE_REGULAR)
{
*size = thumb_sizes[i];
goto finish;
}
g_free (thumb_name);
}
thumb_name = NULL;
finish:
if (basedir)
{
for (i = 0; i < thumb_num_sizes; i++)
g_free (subdirs[i]);
g_free (subdirs);
}
return thumb_name;
}
static const gchar *
gimp_thumb_png_name (const gchar *uri)
{
......
......@@ -29,22 +29,30 @@
G_BEGIN_DECLS
gboolean gimp_thumb_init (const gchar *creator,
const gchar *thumb_basedir);
const gchar * gimp_thumb_get_thumb_dir (GimpThumbSize size);
gboolean gimp_thumb_ensure_thumb_dir (GimpThumbSize size,
GError **error);
gchar * gimp_thumb_name_from_uri (const gchar *uri,
GimpThumbSize size);
gchar * gimp_thumb_find_thumb (const gchar *uri,
GimpThumbSize *size);
GimpThumbFileType gimp_thumb_file_test (const gchar *filename,
gint64 *mtime,
gint64 *size,
gint *err_no);
gboolean gimp_thumb_init (const gchar *creator,
const gchar *thumb_basedir);
const gchar * gimp_thumb_get_thumb_dir (GimpThumbSize size);
gboolean gimp_thumb_ensure_thumb_dir (GimpThumbSize size,
GError **error);
gchar * gimp_thumb_name_from_uri (const gchar *uri,
GimpThumbSize size);
gchar * gimp_thumb_get_thumb_dir_local (const gchar *dirname,
GimpThumbSize size);
gboolean gimp_thumb_ensure_thumb_dir_local (const gchar *dirname,
GimpThumbSize size,
GError **error);
gchar * gimp_thumb_name_from_uri_local (const gchar *uri,
GimpThumbSize size);
gchar * gimp_thumb_find_thumb (const gchar *uri,
GimpThumbSize *size);
GimpThumbFileType gimp_thumb_file_test (const gchar *filename,
gint64 *mtime,
gint64 *size,
gint *err_no);
G_END_DECLS
......
EXPORTS
gimp_thumb_ensure_thumb_dir
gimp_thumb_get_thumb_dir
gimp_thumb_ensure_thumb_dir_local
gimp_thumb_error_quark
gimp_thumb_file_test
gimp_thumb_find_thumb
gimp_thumb_get_thumb_dir
gimp_thumb_get_thumb_dir_local
gimp_thumb_init
gimp_thumb_name_from_uri
gimp_thumb_name_from_uri_local
gimp_thumb_size_get_type
gimp_thumb_state_get_type
gimp_thumbnail_get_type
......@@ -15,6 +18,7 @@ EXPORTS
gimp_thumbnail_peek_thumb
gimp_thumbnail_save_failure
gimp_thumbnail_save_thumb
gimp_thumbnail_save_thumb_local
gimp_thumbnail_set_filename
gimp_thumbnail_set_from_thumb
gimp_thumbnail_set_uri
......@@ -44,7 +44,7 @@
#include "libgimp/libgimp-intl.h"
/* #define GIMP_THUMB_DEBUG */
#define GIMP_THUMB_DEBUG
#if defined (GIMP_THUMB_DEBUG) && defined (__GNUC__)
......@@ -84,26 +84,32 @@ enum
};
static void gimp_thumbnail_class_init (GimpThumbnailClass *klass);
static void gimp_thumbnail_init (GimpThumbnail *thumbnail);
static void gimp_thumbnail_finalize (GObject *object);
static void gimp_thumbnail_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_thumbnail_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_thumbnail_reset_info (GimpThumbnail *thumbnail);
static void gimp_thumbnail_update_image (GimpThumbnail *thumbnail);
static void gimp_thumbnail_update_thumb (GimpThumbnail *thumbnail,
GimpThumbSize size);
static void gimp_thumbnail_class_init (GimpThumbnailClass *klass);
static void gimp_thumbnail_init (GimpThumbnail *thumbnail);
static void gimp_thumbnail_finalize (GObject *object);
static void gimp_thumbnail_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_thumbnail_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_thumbnail_reset_info (GimpThumbnail *thumbnail);
static void gimp_thumbnail_update_image (GimpThumbnail *thumbnail);
static void gimp_thumbnail_update_thumb (GimpThumbnail *thumbnail,
GimpThumbSize size);
static gboolean gimp_thumbnail_save (GimpThumbnail *thumbnail,
GimpThumbSize size,
const gchar *filename,
GdkPixbuf *pixbuf,
const gchar *software,
GError **error);
#ifdef GIMP_THUMB_DEBUG
static void gimp_thumbnail_debug_notify (GObject *object,
GParamSpec *pspec);
static void gimp_thumbnail_debug_notify (GObject *object,
GParamSpec *pspec);
#endif
......@@ -749,6 +755,143 @@ gimp_thumbnail_set_info_from_pixbuf (GimpThumbnail *thumbnail,
g_object_thaw_notify (G_OBJECT (thumbnail));
}
static gboolean
gimp_thumbnail_save (GimpThumbnail *thumbnail,
GimpThumbSize size,
const gchar *filename,
GdkPixbuf *pixbuf,
const gchar *software,
GError **error)
{
const gchar *keys[12];
gchar *values[12];
gboolean success;
gint i = 0;
keys[i] = TAG_DESCRIPTION;
values[i] = g_strdup_printf ("Thumbnail of %s", thumbnail->image_uri);
i++;
keys[i] = TAG_SOFTWARE;
values[i] = g_strdup (software);
i++;
keys[i] = TAG_THUMB_URI;
values[i] = g_strdup (thumbnail->image_uri);
i++;
keys[i] = TAG_THUMB_MTIME;
values[i] = g_strdup_printf ("%" G_GINT64_FORMAT, thumbnail->image_mtime);
i++;