mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-21 03:52:33 +00:00
app/core/gimpdata.[ch] applied a heavily modified version of the patch
2005-10-31 Sven Neumann <sven@gimp.org> * app/core/gimpdata.[ch] * app/core/gimpdatafactory.c: applied a heavily modified version of the patch provided by Shlomi Fish in bug #311740. Introduces a cache to speed up reloading of data files. * app/actions/data-commands.c: set gimp busy while refreshing data factories. * app/widgets/gimpwidgets-utils.c (gimp_widget_accel_changed): free the return value of gimp_get_accel_string().
This commit is contained in:
parent
2b6a5f453a
commit
c00173ccd0
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
|||
2005-10-31 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/core/gimpdata.[ch]
|
||||
* app/core/gimpdatafactory.c: applied a heavily modified version
|
||||
of the patch provided by Shlomi Fish in bug #311740. Introduces a
|
||||
cache to speed up reloading of data files.
|
||||
|
||||
* app/actions/data-commands.c: set gimp busy while refreshing data
|
||||
factories.
|
||||
|
||||
* app/widgets/gimpwidgets-utils.c (gimp_widget_accel_changed):
|
||||
free the return value of gimp_get_accel_string().
|
||||
|
||||
2005-10-31 Michael Natterer <mitch@gimp.org>
|
||||
|
||||
* app/widgets/gimpviewablebutton.[ch] (gimp_viewable_button_new):
|
||||
|
|
|
@ -228,8 +228,12 @@ data_refresh_cmd_callback (GtkAction *action,
|
|||
gpointer user_data)
|
||||
{
|
||||
GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data);
|
||||
Gimp *gimp;
|
||||
return_if_no_gimp (gimp, user_data);
|
||||
|
||||
gimp_set_busy (gimp);
|
||||
gimp_data_factory_data_refresh (view->factory);
|
||||
gimp_unset_busy (gimp);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -177,6 +177,7 @@ gimp_data_init (GimpData *data,
|
|||
data->dirty = TRUE;
|
||||
data->internal = FALSE;
|
||||
data->freeze_count = 0;
|
||||
data->mtime = 0;
|
||||
|
||||
/* look at the passed class pointer, not at GIMP_DATA_GET_CLASS(data)
|
||||
* here, because the latter is always GimpDataClass itself
|
||||
|
@ -335,7 +336,14 @@ gimp_data_save (GimpData *data,
|
|||
success = GIMP_DATA_GET_CLASS (data)->save (data, error);
|
||||
|
||||
if (success)
|
||||
data->dirty = FALSE;
|
||||
{
|
||||
struct stat filestat;
|
||||
|
||||
g_stat (data->filename, &filestat);
|
||||
|
||||
data->mtime = filestat.st_mtime;
|
||||
data->dirty = FALSE;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#ifndef __GIMP_DATA_H__
|
||||
#define __GIMP_DATA_H__
|
||||
|
||||
#include <time.h> /* time_t */
|
||||
|
||||
#include "gimpviewable.h"
|
||||
|
||||
|
@ -56,6 +57,7 @@ struct _GimpData
|
|||
guint dirty : 1;
|
||||
guint internal : 1;
|
||||
gint freeze_count;
|
||||
time_t mtime;
|
||||
};
|
||||
|
||||
struct _GimpDataClass
|
||||
|
|
|
@ -42,21 +42,21 @@
|
|||
|
||||
#define WRITABLE_PATH_KEY "gimp-data-factory-writable-path"
|
||||
|
||||
static void gimp_data_factory_class_init (GimpDataFactoryClass *klass);
|
||||
static void gimp_data_factory_init (GimpDataFactory *factory);
|
||||
|
||||
static void gimp_data_factory_class_init (GimpDataFactoryClass *klass);
|
||||
static void gimp_data_factory_init (GimpDataFactory *factory);
|
||||
static void gimp_data_factory_finalize (GObject *object);
|
||||
|
||||
static void gimp_data_factory_finalize (GObject *object);
|
||||
static void gimp_data_factory_data_load (GimpDataFactory *factory,
|
||||
GHashTable *cache);
|
||||
|
||||
static void gimp_data_factory_data_load (GimpDataFactory *factory);
|
||||
static gint64 gimp_data_factory_get_memsize (GimpObject *object,
|
||||
gint64 *gui_size);
|
||||
|
||||
static gint64 gimp_data_factory_get_memsize (GimpObject *object,
|
||||
gint64 *gui_size);
|
||||
|
||||
static gchar * gimp_data_factory_get_save_dir (GimpDataFactory *factory);
|
||||
static void gimp_data_factory_load_data (const GimpDatafileData *file_data,
|
||||
gpointer user_data);
|
||||
static gchar * gimp_data_factory_get_save_dir (GimpDataFactory *factory);
|
||||
|
||||
static void gimp_data_factory_load_data (const GimpDatafileData *file_data,
|
||||
gpointer data);
|
||||
|
||||
static GimpObjectClass *parent_class = NULL;
|
||||
|
||||
|
@ -213,28 +213,102 @@ gimp_data_factory_data_init (GimpDataFactory *factory,
|
|||
g_print ("%s: loading data\n", name ? name : "???");
|
||||
}
|
||||
|
||||
gimp_data_factory_data_load (factory);
|
||||
gimp_data_factory_data_load (factory, NULL);
|
||||
}
|
||||
|
||||
gimp_container_thaw (factory->container);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_data_factory_data_refresh (GimpDataFactory *factory)
|
||||
typedef struct
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
|
||||
GimpDataFactory *factory;
|
||||
GHashTable *cache;
|
||||
} GimpDataLoadContext;
|
||||
|
||||
typedef struct data_load_context_struct data_load_context;
|
||||
|
||||
static gboolean
|
||||
gimp_data_factory_refresh_cache_remove (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
for (list = value; list; list = g_list_next (list))
|
||||
g_object_unref (list->data);
|
||||
|
||||
g_list_free (value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_data_factory_data_move_to_cache (GimpDataFactory *factory,
|
||||
gpointer object,
|
||||
gpointer data)
|
||||
{
|
||||
GHashTable *cache = data;
|
||||
GList *list;
|
||||
const gchar *filename = GIMP_DATA (object)->filename;
|
||||
|
||||
g_object_ref (object);
|
||||
|
||||
gimp_container_remove (factory->container, GIMP_OBJECT (object));
|
||||
|
||||
list = g_hash_table_lookup (cache, filename);
|
||||
list = g_list_prepend (list, object);
|
||||
|
||||
g_hash_table_insert (cache, (gpointer) filename, list);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_data_factory_data_foreach (GimpDataFactory *factory,
|
||||
void (*callback) (GimpDataFactory *factory,
|
||||
gpointer expr,
|
||||
gpointer context),
|
||||
gpointer context)
|
||||
{
|
||||
GimpList *list;
|
||||
|
||||
if (gimp_container_is_empty (factory->container))
|
||||
return;
|
||||
|
||||
list = GIMP_LIST (factory->container);
|
||||
|
||||
gimp_container_freeze (factory->container);
|
||||
|
||||
gimp_data_factory_data_save (factory);
|
||||
gimp_data_factory_data_free (factory);
|
||||
gimp_data_factory_data_load (factory);
|
||||
if (list->list)
|
||||
{
|
||||
if (GIMP_DATA (list->list->data)->internal)
|
||||
{
|
||||
/* if there are internal objects in the list, skip them */
|
||||
GList *glist;
|
||||
|
||||
for (glist = list->list; glist; glist = g_list_next (glist))
|
||||
{
|
||||
if (glist->next && ! GIMP_DATA (glist->next->data)->internal)
|
||||
{
|
||||
while (glist->next)
|
||||
callback (factory, glist->next->data, context);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise delete everything */
|
||||
while (list->list)
|
||||
callback (factory, list->list->data, context);
|
||||
}
|
||||
}
|
||||
|
||||
gimp_container_thaw (factory->container);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_data_factory_data_load (GimpDataFactory *factory)
|
||||
gimp_data_factory_data_load (GimpDataFactory *factory,
|
||||
GHashTable *cache)
|
||||
{
|
||||
gchar *path;
|
||||
gchar *writable_path;
|
||||
|
@ -246,8 +320,12 @@ gimp_data_factory_data_load (GimpDataFactory *factory)
|
|||
|
||||
if (path && strlen (path))
|
||||
{
|
||||
GList *writable_list = NULL;
|
||||
gchar *tmp;
|
||||
GList *writable_list = NULL;
|
||||
gchar *tmp;
|
||||
GimpDataLoadContext context;
|
||||
|
||||
context.factory = factory;
|
||||
context.cache = cache;
|
||||
|
||||
tmp = gimp_config_path_expand (path, TRUE, NULL);
|
||||
g_free (path);
|
||||
|
@ -261,14 +339,12 @@ gimp_data_factory_data_load (GimpDataFactory *factory)
|
|||
|
||||
writable_list = gimp_path_parse (writable_path, 16, TRUE, NULL);
|
||||
|
||||
g_object_set_data (G_OBJECT (factory), WRITABLE_PATH_KEY,
|
||||
writable_list);
|
||||
g_object_set_data (G_OBJECT (factory),
|
||||
WRITABLE_PATH_KEY, writable_list);
|
||||
}
|
||||
|
||||
gimp_datafiles_read_directories (path,
|
||||
G_FILE_TEST_EXISTS,
|
||||
gimp_data_factory_load_data,
|
||||
factory);
|
||||
gimp_datafiles_read_directories (path, G_FILE_TEST_EXISTS,
|
||||
gimp_data_factory_load_data, &context);
|
||||
|
||||
if (writable_path)
|
||||
{
|
||||
|
@ -281,6 +357,49 @@ gimp_data_factory_data_load (GimpDataFactory *factory)
|
|||
g_free (writable_path);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_data_factory_data_reload (GimpDataFactory *factory)
|
||||
{
|
||||
|
||||
GHashTable *cache;
|
||||
|
||||
g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
|
||||
|
||||
cache = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
gimp_data_factory_data_foreach (factory,
|
||||
gimp_data_factory_data_move_to_cache, cache);
|
||||
|
||||
/* Now the cache contains a filename => list-of-objects mapping of
|
||||
* the old objects. So we should now traverse the directory and for
|
||||
* each file load it only if it's mtime is newer.
|
||||
*
|
||||
* Once a file was added, it is removed from the cache, so the only
|
||||
* objects remaining there will be those that are not present on the
|
||||
* disk (that have to be destroyed)
|
||||
*/
|
||||
gimp_data_factory_data_load (factory, cache);
|
||||
|
||||
/* Now all the data is loaded. Free what remains in the cache. */
|
||||
g_hash_table_foreach_remove (cache,
|
||||
gimp_data_factory_refresh_cache_remove, NULL);
|
||||
g_hash_table_destroy (cache);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_data_factory_data_refresh (GimpDataFactory *factory)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
|
||||
|
||||
gimp_container_freeze (factory->container);
|
||||
|
||||
gimp_data_factory_data_save (factory);
|
||||
|
||||
gimp_data_factory_data_reload (factory);
|
||||
|
||||
gimp_container_thaw (factory->container);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_data_factory_data_save (GimpDataFactory *factory)
|
||||
{
|
||||
|
@ -319,8 +438,7 @@ gimp_data_factory_data_save (GimpDataFactory *factory)
|
|||
*/
|
||||
if (error)
|
||||
{
|
||||
g_message (_("Warning: Failed to save data:\n\n%s"),
|
||||
error->message);
|
||||
g_message (_("Failed to save data:\n\n%s"), error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
|
@ -332,55 +450,19 @@ gimp_data_factory_data_save (GimpDataFactory *factory)
|
|||
g_free (writable_dir);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_data_factory_remove_cb (GimpDataFactory *factory,
|
||||
gpointer data,
|
||||
gpointer context)
|
||||
{
|
||||
gimp_container_remove (factory->container, GIMP_OBJECT (data));
|
||||
}
|
||||
|
||||
void
|
||||
gimp_data_factory_data_free (GimpDataFactory *factory)
|
||||
{
|
||||
GimpList *list;
|
||||
|
||||
g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
|
||||
|
||||
if (gimp_container_is_empty (factory->container))
|
||||
return;
|
||||
|
||||
list = GIMP_LIST (factory->container);
|
||||
|
||||
gimp_container_freeze (factory->container);
|
||||
|
||||
if (list->list)
|
||||
{
|
||||
if (GIMP_DATA (list->list->data)->internal)
|
||||
{
|
||||
/* if there are internal objects in the list, skip them */
|
||||
|
||||
GList *glist;
|
||||
|
||||
for (glist = list->list; glist; glist = g_list_next (glist))
|
||||
{
|
||||
if (glist->next && ! GIMP_DATA (glist->next->data)->internal)
|
||||
{
|
||||
while (glist->next)
|
||||
{
|
||||
gimp_container_remove (factory->container,
|
||||
GIMP_OBJECT (glist->next->data));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise delete everything */
|
||||
|
||||
while (list->list)
|
||||
{
|
||||
gimp_container_remove (factory->container,
|
||||
GIMP_OBJECT (list->list->data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gimp_container_thaw (factory->container);
|
||||
return gimp_data_factory_data_foreach (factory,
|
||||
gimp_data_factory_remove_cb, NULL);
|
||||
}
|
||||
|
||||
GimpData *
|
||||
|
@ -529,8 +611,7 @@ gimp_data_factory_data_save_single (GimpDataFactory *factory,
|
|||
*/
|
||||
if (error)
|
||||
{
|
||||
g_message (_("Warning: Failed to save data:\n\n%s"),
|
||||
error->message);
|
||||
g_message (_("Failed to save data:\n\n%s"), error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
|
@ -592,72 +673,88 @@ gimp_data_factory_get_save_dir (GimpDataFactory *factory)
|
|||
|
||||
static void
|
||||
gimp_data_factory_load_data (const GimpDatafileData *file_data,
|
||||
gpointer user_data)
|
||||
gpointer data)
|
||||
{
|
||||
GimpDataFactory *factory = GIMP_DATA_FACTORY (user_data);
|
||||
gint i;
|
||||
GimpDataLoadContext *context = data;
|
||||
GimpDataFactory *factory = context->factory;
|
||||
GHashTable *cache = context->cache;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < factory->n_loader_entries; i++)
|
||||
{
|
||||
if (factory->loader_entries[i].extension)
|
||||
{
|
||||
if (gimp_datafiles_check_extension (file_data->filename,
|
||||
factory->loader_entries[i].extension))
|
||||
{
|
||||
goto insert;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto insert;
|
||||
}
|
||||
if (! factory->loader_entries[i].extension ||
|
||||
gimp_datafiles_check_extension (file_data->filename,
|
||||
factory->loader_entries[i].extension))
|
||||
goto insert;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
insert:
|
||||
{
|
||||
GList *data_list;
|
||||
GError *error = NULL;
|
||||
GList *cached_data;
|
||||
gboolean load_from_disk = TRUE;
|
||||
|
||||
data_list = factory->loader_entries[i].load_func (file_data->filename,
|
||||
&error);
|
||||
|
||||
if (! data_list)
|
||||
if (cache &&
|
||||
(cached_data = g_hash_table_lookup (cache, file_data->filename)))
|
||||
{
|
||||
g_message (_("Warning: Failed to load data:\n\n%s"),
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
else
|
||||
{
|
||||
GList *writable_list;
|
||||
GList *list;
|
||||
gboolean writable;
|
||||
gboolean deletable;
|
||||
GimpData *data = cached_data->data;
|
||||
|
||||
writable_list = g_object_get_data (G_OBJECT (factory),
|
||||
WRITABLE_PATH_KEY);
|
||||
load_from_disk = (data->mtime == 0 || data->mtime != file_data->mtime);
|
||||
|
||||
deletable = (g_list_length (data_list) == 1 &&
|
||||
g_list_find_custom (writable_list, file_data->dirname,
|
||||
(GCompareFunc) strcmp) != NULL);
|
||||
|
||||
writable = (deletable && factory->loader_entries[i].writable);
|
||||
|
||||
for (list = data_list; list; list = g_list_next (list))
|
||||
if (! load_from_disk)
|
||||
{
|
||||
GimpData *data = list->data;
|
||||
GList *list;
|
||||
|
||||
gimp_data_set_filename (data, file_data->filename,
|
||||
writable, deletable);
|
||||
data->dirty = FALSE;
|
||||
|
||||
gimp_container_add (factory->container, GIMP_OBJECT (data));
|
||||
g_object_unref (data);
|
||||
for (list = cached_data; list; list = g_list_next (list))
|
||||
gimp_container_add (factory->container, GIMP_OBJECT (list->data));
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free (data_list);
|
||||
if (load_from_disk)
|
||||
{
|
||||
GList *data_list;
|
||||
GError *error = NULL;
|
||||
|
||||
data_list = factory->loader_entries[i].load_func (file_data->filename,
|
||||
&error);
|
||||
|
||||
if (G_LIKELY (data_list))
|
||||
{
|
||||
GList *writable_list;
|
||||
GList *list;
|
||||
gboolean writable;
|
||||
gboolean deletable;
|
||||
|
||||
writable_list = g_object_get_data (G_OBJECT (factory),
|
||||
WRITABLE_PATH_KEY);
|
||||
|
||||
deletable = (g_list_length (data_list) == 1 &&
|
||||
g_list_find_custom (writable_list, file_data->dirname,
|
||||
(GCompareFunc) strcmp) != NULL);
|
||||
|
||||
writable = (deletable && factory->loader_entries[i].writable);
|
||||
|
||||
for (list = data_list; list; list = g_list_next (list))
|
||||
{
|
||||
GimpData *data = list->data;
|
||||
|
||||
gimp_data_set_filename (data, file_data->filename,
|
||||
writable, deletable);
|
||||
data->mtime = file_data->mtime;
|
||||
data->dirty = FALSE;
|
||||
|
||||
gimp_container_add (factory->container, GIMP_OBJECT (data));
|
||||
g_object_unref (data);
|
||||
}
|
||||
|
||||
g_list_free (data_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_message (_("Failed to load data:\n\n%s"), error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -966,11 +966,12 @@ gimp_widget_accel_changed (GtkAccelGroup *accel_group,
|
|||
accel_key->accel_key &&
|
||||
accel_key->accel_flags & GTK_ACCEL_VISIBLE)
|
||||
{
|
||||
tooltip = g_strconcat (orig_tooltip,
|
||||
" ",
|
||||
gimp_get_accel_string (accel_key->accel_key,
|
||||
accel_key->accel_mods),
|
||||
NULL);
|
||||
gchar *tmp = gimp_get_accel_string (accel_key->accel_key,
|
||||
accel_key->accel_mods);
|
||||
|
||||
tooltip = g_strconcat (orig_tooltip, " ", tmp, NULL);
|
||||
|
||||
g_free (tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue