2006-12-09 21:33:38 +00:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
2001-02-13 19:53:07 +00:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
2001-04-22 00:38:56 +00:00
|
|
|
* gimpdatafactory.c
|
2018-06-02 21:50:34 +02:00
|
|
|
* Copyright (C) 2001-2018 Michael Natterer <mitch@gimp.org>
|
2001-04-22 00:38:56 +00:00
|
|
|
*
|
2009-01-17 22:28:01 +00:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
2001-02-13 19:53:07 +00:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-17 22:28:01 +00:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2001-02-13 19:53:07 +00:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2018-07-11 23:27:07 +02:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2001-02-13 19:53:07 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2013-10-15 01:58:39 +02:00
|
|
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
2012-03-29 19:19:01 +02:00
|
|
|
#include <gegl.h>
|
2019-08-23 00:33:31 +02:00
|
|
|
#include <stdlib.h>
|
2001-02-13 19:53:07 +00:00
|
|
|
|
2002-10-23 14:55:07 +00:00
|
|
|
#include "libgimpbase/gimpbase.h"
|
2007-03-09 13:00:01 +00:00
|
|
|
#include "libgimpmath/gimpmath.h"
|
2005-01-25 19:11:26 +00:00
|
|
|
#include "libgimpconfig/gimpconfig.h"
|
2002-10-23 14:55:07 +00:00
|
|
|
|
2001-05-09 22:34:59 +00:00
|
|
|
#include "core-types.h"
|
2001-02-13 19:53:07 +00:00
|
|
|
|
2002-11-30 16:31:39 +00:00
|
|
|
#include "gimp.h"
|
2014-08-02 15:07:26 +02:00
|
|
|
#include "gimp-utils.h"
|
2018-06-03 22:28:00 +02:00
|
|
|
#include "gimpasyncset.h"
|
|
|
|
#include "gimpcancelable.h"
|
2001-07-09 19:48:30 +00:00
|
|
|
#include "gimpcontext.h"
|
2001-02-13 19:53:07 +00:00
|
|
|
#include "gimpdata.h"
|
|
|
|
#include "gimpdatafactory.h"
|
2004-05-24 10:49:34 +00:00
|
|
|
#include "gimplist.h"
|
2018-06-03 22:28:00 +02:00
|
|
|
#include "gimpuncancelablewaitable.h"
|
|
|
|
#include "gimpwaitable.h"
|
2001-02-13 19:53:07 +00:00
|
|
|
|
2003-03-25 16:38:19 +00:00
|
|
|
#include "gimp-intl.h"
|
2001-02-14 01:42:12 +00:00
|
|
|
|
2001-02-13 19:53:07 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
PROP_GIMP,
|
|
|
|
PROP_DATA_TYPE,
|
|
|
|
PROP_PATH_PROPERTY_NAME,
|
2018-06-04 12:18:13 +02:00
|
|
|
PROP_WRITABLE_PROPERTY_NAME,
|
2018-07-02 20:33:59 +02:00
|
|
|
PROP_EXT_PROPERTY_NAME,
|
2018-06-04 12:18:13 +02:00
|
|
|
PROP_NEW_FUNC,
|
|
|
|
PROP_GET_STANDARD_FUNC
|
2018-06-02 21:50:34 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct _GimpDataFactoryPrivate
|
2008-12-19 21:58:17 +00:00
|
|
|
{
|
2018-06-04 13:12:14 +02:00
|
|
|
Gimp *gimp;
|
2009-08-11 20:38:12 +02:00
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
GType data_type;
|
|
|
|
GimpContainer *container;
|
|
|
|
GimpContainer *container_obsolete;
|
2008-12-19 21:58:17 +00:00
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
gchar *path_property_name;
|
|
|
|
gchar *writable_property_name;
|
2018-07-02 20:33:59 +02:00
|
|
|
gchar *ext_property_name;
|
2018-06-04 12:18:13 +02:00
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
GimpDataNewFunc data_new_func;
|
|
|
|
GimpDataGetStandardFunc data_get_standard_func;
|
2018-06-03 22:28:00 +02:00
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
GimpAsyncSet *async_set;
|
2008-12-19 21:58:17 +00:00
|
|
|
};
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
#define GET_PRIVATE(obj) (((GimpDataFactory *) (obj))->priv)
|
|
|
|
|
|
|
|
|
|
|
|
static void gimp_data_factory_constructed (GObject *object);
|
|
|
|
static void gimp_data_factory_set_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec);
|
|
|
|
static void gimp_data_factory_get_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec);
|
|
|
|
static void gimp_data_factory_finalize (GObject *object);
|
|
|
|
|
|
|
|
static gint64 gimp_data_factory_get_memsize (GimpObject *object,
|
|
|
|
gint64 *gui_size);
|
|
|
|
|
|
|
|
static void gimp_data_factory_real_data_save (GimpDataFactory *factory);
|
app: add gimp_data_factory_data_cancel()
Add a new GimpData::data_cancel() virtual function, and a
corresponding gimp_data_factory_data_cancel() function. This
function should cancel any ongoing async operations related to the
factory (i.e., included in its async set), and wait for the
operations to finish. Provide a default implementation that simply
cancels and waits on the factory's async set.
Use this function to cancel any ongoing operations during factory
destruction, and in gimp_data_factory_data_free().
Override this function in GimpFontFactory, for which we can't
really cancel font loading, and simply cancel and clear the
factory's async set without waiting for loading to finish, making
sure that nothing happens (and, in particular, that the factory
isn't being accessed, since it might be already dead) when loading
does finish.
2018-10-01 03:30:08 -04:00
|
|
|
static void gimp_data_factory_real_data_cancel (GimpDataFactory *factory);
|
2018-06-02 21:50:34 +02:00
|
|
|
static GimpData * gimp_data_factory_real_data_duplicate (GimpDataFactory *factory,
|
|
|
|
GimpData *data);
|
|
|
|
static gboolean gimp_data_factory_real_data_delete (GimpDataFactory *factory,
|
|
|
|
GimpData *data,
|
|
|
|
gboolean delete_from_disk,
|
|
|
|
GError **error);
|
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
static void gimp_data_factory_path_notify (GObject *object,
|
2018-06-02 21:50:34 +02:00
|
|
|
const GParamSpec *pspec,
|
|
|
|
GimpDataFactory *factory);
|
2018-06-04 13:12:14 +02:00
|
|
|
static GFile * gimp_data_factory_get_save_dir (GimpDataFactory *factory,
|
2018-06-02 21:50:34 +02:00
|
|
|
GError **error);
|
|
|
|
|
2001-02-13 19:53:07 +00:00
|
|
|
|
app, libgimp*, modules: don't use g_type_class_add_private() ...
... and G_TYPE_INSTANCE_GET_PRIVATE()
g_type_class_add_private() and G_TYPE_INSTANCE_GET_PRIVATE() were
deprecated in GLib 2.58. Instead, use
G_DEFINE_[ABSTRACT_]TYPE_WITH_PRIVATE(), and
G_ADD_PRIVATE[_DYNAMIC](), and the implictly-defined
foo_get_instance_private() functions, all of which are available in
the GLib versions we depend on.
This commit only covers types registered using one of the
G_DEFINE_FOO() macros (i.e., most types), but not types with a
custom registration function, of which we still have a few -- GLib
currently only provides a (non-deprecated) public API for adding a
private struct using the G_DEFINE_FOO() macros.
Note that this commit was 99% auto-generated (because I'm not
*that* crazy :), so if there are any style mismatches... we'll have
to live with them for now.
2018-09-18 12:09:39 -04:00
|
|
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GimpDataFactory, gimp_data_factory,
|
|
|
|
GIMP_TYPE_OBJECT)
|
2005-12-10 19:24:36 +00:00
|
|
|
|
|
|
|
#define parent_class gimp_data_factory_parent_class
|
2001-02-13 19:53:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_data_factory_class_init (GimpDataFactoryClass *klass)
|
|
|
|
{
|
2004-05-24 10:49:34 +00:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
|
2001-02-13 19:53:07 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
object_class->constructed = gimp_data_factory_constructed;
|
|
|
|
object_class->set_property = gimp_data_factory_set_property;
|
|
|
|
object_class->get_property = gimp_data_factory_get_property;
|
2002-01-30 16:14:26 +00:00
|
|
|
object_class->finalize = gimp_data_factory_finalize;
|
|
|
|
|
|
|
|
gimp_object_class->get_memsize = gimp_data_factory_get_memsize;
|
2008-12-19 21:58:17 +00:00
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
klass->data_init = NULL;
|
|
|
|
klass->data_refresh = NULL;
|
2018-06-02 21:50:34 +02:00
|
|
|
klass->data_save = gimp_data_factory_real_data_save;
|
app: add gimp_data_factory_data_cancel()
Add a new GimpData::data_cancel() virtual function, and a
corresponding gimp_data_factory_data_cancel() function. This
function should cancel any ongoing async operations related to the
factory (i.e., included in its async set), and wait for the
operations to finish. Provide a default implementation that simply
cancels and waits on the factory's async set.
Use this function to cancel any ongoing operations during factory
destruction, and in gimp_data_factory_data_free().
Override this function in GimpFontFactory, for which we can't
really cancel font loading, and simply cancel and clear the
factory's async set without waiting for loading to finish, making
sure that nothing happens (and, in particular, that the factory
isn't being accessed, since it might be already dead) when loading
does finish.
2018-10-01 03:30:08 -04:00
|
|
|
klass->data_cancel = gimp_data_factory_real_data_cancel;
|
2018-06-02 21:50:34 +02:00
|
|
|
klass->data_duplicate = gimp_data_factory_real_data_duplicate;
|
|
|
|
klass->data_delete = gimp_data_factory_real_data_delete;
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class, PROP_GIMP,
|
|
|
|
g_param_spec_object ("gimp", NULL, NULL,
|
|
|
|
GIMP_TYPE_GIMP,
|
|
|
|
GIMP_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class, PROP_DATA_TYPE,
|
|
|
|
g_param_spec_gtype ("data-type", NULL, NULL,
|
|
|
|
GIMP_TYPE_DATA,
|
|
|
|
GIMP_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class, PROP_PATH_PROPERTY_NAME,
|
|
|
|
g_param_spec_string ("path-property-name",
|
|
|
|
NULL, NULL,
|
|
|
|
NULL,
|
|
|
|
GIMP_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class, PROP_WRITABLE_PROPERTY_NAME,
|
|
|
|
g_param_spec_string ("writable-property-name",
|
|
|
|
NULL, NULL,
|
|
|
|
NULL,
|
|
|
|
GIMP_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
|
2018-07-02 20:33:59 +02:00
|
|
|
g_object_class_install_property (object_class, PROP_EXT_PROPERTY_NAME,
|
|
|
|
g_param_spec_string ("ext-property-name",
|
|
|
|
NULL, NULL,
|
|
|
|
NULL,
|
|
|
|
GIMP_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
|
2018-06-04 12:18:13 +02:00
|
|
|
g_object_class_install_property (object_class, PROP_NEW_FUNC,
|
|
|
|
g_param_spec_pointer ("new-func",
|
|
|
|
NULL, NULL,
|
|
|
|
GIMP_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class, PROP_GET_STANDARD_FUNC,
|
|
|
|
g_param_spec_pointer ("get-standard-func",
|
|
|
|
NULL, NULL,
|
|
|
|
GIMP_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY));
|
2001-02-13 19:53:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_data_factory_init (GimpDataFactory *factory)
|
|
|
|
{
|
app, libgimp*, modules: don't use g_type_class_add_private() ...
... and G_TYPE_INSTANCE_GET_PRIVATE()
g_type_class_add_private() and G_TYPE_INSTANCE_GET_PRIVATE() were
deprecated in GLib 2.58. Instead, use
G_DEFINE_[ABSTRACT_]TYPE_WITH_PRIVATE(), and
G_ADD_PRIVATE[_DYNAMIC](), and the implictly-defined
foo_get_instance_private() functions, all of which are available in
the GLib versions we depend on.
This commit only covers types registered using one of the
G_DEFINE_FOO() macros (i.e., most types), but not types with a
custom registration function, of which we still have a few -- GLib
currently only provides a (non-deprecated) public API for adding a
private struct using the G_DEFINE_FOO() macros.
Note that this commit was 99% auto-generated (because I'm not
*that* crazy :), so if there are any style mismatches... we'll have
to live with them for now.
2018-09-18 12:09:39 -04:00
|
|
|
factory->priv = gimp_data_factory_get_instance_private (factory);
|
2018-06-03 22:28:00 +02:00
|
|
|
|
|
|
|
factory->priv->async_set = gimp_async_set_new ();
|
2001-02-13 19:53:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-06-02 21:50:34 +02:00
|
|
|
gimp_data_factory_constructed (GObject *object)
|
2001-02-13 19:53:07 +00:00
|
|
|
{
|
2018-06-02 21:50:34 +02:00
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (object);
|
2001-02-13 19:53:07 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
G_OBJECT_CLASS (parent_class)->constructed (object);
|
2009-08-11 20:38:12 +02:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
gimp_assert (GIMP_IS_GIMP (priv->gimp));
|
|
|
|
gimp_assert (g_type_is_a (priv->data_type, GIMP_TYPE_DATA));
|
2018-06-04 13:12:14 +02:00
|
|
|
gimp_assert (GIMP_DATA_FACTORY_GET_CLASS (object)->data_init != NULL);
|
|
|
|
gimp_assert (GIMP_DATA_FACTORY_GET_CLASS (object)->data_refresh != NULL);
|
2004-01-28 21:53:50 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
priv->container = gimp_list_new (priv->data_type, TRUE);
|
|
|
|
gimp_list_set_sort_func (GIMP_LIST (priv->container),
|
|
|
|
(GCompareFunc) gimp_data_compare);
|
|
|
|
|
|
|
|
priv->container_obsolete = gimp_list_new (priv->data_type, TRUE);
|
|
|
|
gimp_list_set_sort_func (GIMP_LIST (priv->container_obsolete),
|
|
|
|
(GCompareFunc) gimp_data_compare);
|
2001-02-13 19:53:07 +00:00
|
|
|
}
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
static void
|
|
|
|
gimp_data_factory_set_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
2002-01-30 16:14:26 +00:00
|
|
|
{
|
2018-06-02 21:50:34 +02:00
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (object);
|
2002-01-30 16:14:26 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
switch (property_id)
|
|
|
|
{
|
|
|
|
case PROP_GIMP:
|
|
|
|
priv->gimp = g_value_get_object (value); /* don't ref */
|
|
|
|
break;
|
2002-01-30 16:14:26 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
case PROP_DATA_TYPE:
|
|
|
|
priv->data_type = g_value_get_gtype (value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PROP_PATH_PROPERTY_NAME:
|
|
|
|
priv->path_property_name = g_value_dup_string (value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PROP_WRITABLE_PROPERTY_NAME:
|
|
|
|
priv->writable_property_name = g_value_dup_string (value);
|
|
|
|
break;
|
|
|
|
|
2018-07-02 20:33:59 +02:00
|
|
|
case PROP_EXT_PROPERTY_NAME:
|
|
|
|
priv->ext_property_name = g_value_dup_string (value);
|
|
|
|
break;
|
|
|
|
|
2018-06-04 12:18:13 +02:00
|
|
|
case PROP_NEW_FUNC:
|
|
|
|
priv->data_new_func = g_value_get_pointer (value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PROP_GET_STANDARD_FUNC:
|
|
|
|
priv->data_get_standard_func = g_value_get_pointer (value);
|
|
|
|
break;
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
2002-01-30 16:14:26 +00:00
|
|
|
}
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
static void
|
|
|
|
gimp_data_factory_get_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
2001-02-13 19:53:07 +00:00
|
|
|
{
|
2018-06-02 21:50:34 +02:00
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (object);
|
2001-02-13 19:53:07 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
switch (property_id)
|
|
|
|
{
|
|
|
|
case PROP_GIMP:
|
|
|
|
g_value_set_object (value, priv->gimp);
|
|
|
|
break;
|
2001-02-13 19:53:07 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
case PROP_DATA_TYPE:
|
|
|
|
g_value_set_gtype (value, priv->data_type);
|
|
|
|
break;
|
2001-02-13 19:53:07 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
case PROP_PATH_PROPERTY_NAME:
|
|
|
|
g_value_set_string (value, priv->path_property_name);
|
|
|
|
break;
|
2001-02-13 19:53:07 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
case PROP_WRITABLE_PROPERTY_NAME:
|
|
|
|
g_value_set_string (value, priv->writable_property_name);
|
|
|
|
break;
|
2001-02-14 01:42:12 +00:00
|
|
|
|
2018-07-02 20:33:59 +02:00
|
|
|
case PROP_EXT_PROPERTY_NAME:
|
|
|
|
g_value_set_string (value, priv->ext_property_name);
|
|
|
|
break;
|
|
|
|
|
2018-06-04 12:18:13 +02:00
|
|
|
case PROP_NEW_FUNC:
|
|
|
|
g_value_set_pointer (value, priv->data_new_func);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PROP_GET_STANDARD_FUNC:
|
|
|
|
g_value_set_pointer (value, priv->data_get_standard_func);
|
|
|
|
break;
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2001-02-14 01:42:12 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
static void
|
|
|
|
gimp_data_factory_finalize (GObject *object)
|
|
|
|
{
|
app: add gimp_data_factory_data_cancel()
Add a new GimpData::data_cancel() virtual function, and a
corresponding gimp_data_factory_data_cancel() function. This
function should cancel any ongoing async operations related to the
factory (i.e., included in its async set), and wait for the
operations to finish. Provide a default implementation that simply
cancels and waits on the factory's async set.
Use this function to cancel any ongoing operations during factory
destruction, and in gimp_data_factory_data_free().
Override this function in GimpFontFactory, for which we can't
really cancel font loading, and simply cancel and clear the
factory's async set without waiting for loading to finish, making
sure that nothing happens (and, in particular, that the factory
isn't being accessed, since it might be already dead) when loading
does finish.
2018-10-01 03:30:08 -04:00
|
|
|
GimpDataFactory *factory = GIMP_DATA_FACTORY (object);
|
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (object);
|
2001-02-13 19:53:07 +00:00
|
|
|
|
2018-06-03 22:28:00 +02:00
|
|
|
if (priv->async_set)
|
|
|
|
{
|
app: add gimp_data_factory_data_cancel()
Add a new GimpData::data_cancel() virtual function, and a
corresponding gimp_data_factory_data_cancel() function. This
function should cancel any ongoing async operations related to the
factory (i.e., included in its async set), and wait for the
operations to finish. Provide a default implementation that simply
cancels and waits on the factory's async set.
Use this function to cancel any ongoing operations during factory
destruction, and in gimp_data_factory_data_free().
Override this function in GimpFontFactory, for which we can't
really cancel font loading, and simply cancel and clear the
factory's async set without waiting for loading to finish, making
sure that nothing happens (and, in particular, that the factory
isn't being accessed, since it might be already dead) when loading
does finish.
2018-10-01 03:30:08 -04:00
|
|
|
gimp_data_factory_data_cancel (factory);
|
2018-06-03 22:28:00 +02:00
|
|
|
|
|
|
|
g_clear_object (&priv->async_set);
|
|
|
|
}
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
g_clear_object (&priv->container);
|
|
|
|
g_clear_object (&priv->container_obsolete);
|
|
|
|
|
|
|
|
g_clear_pointer (&priv->path_property_name, g_free);
|
|
|
|
g_clear_pointer (&priv->writable_property_name, g_free);
|
2018-07-02 20:33:59 +02:00
|
|
|
g_clear_pointer (&priv->ext_property_name, g_free);
|
2018-06-02 21:50:34 +02:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
2001-02-13 19:53:07 +00:00
|
|
|
}
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
static gint64
|
|
|
|
gimp_data_factory_get_memsize (GimpObject *object,
|
|
|
|
gint64 *gui_size)
|
2001-02-14 01:42:12 +00:00
|
|
|
{
|
2018-06-02 21:50:34 +02:00
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (object);
|
|
|
|
gint64 memsize = 0;
|
|
|
|
|
|
|
|
memsize += gimp_object_get_memsize (GIMP_OBJECT (priv->container),
|
|
|
|
gui_size);
|
|
|
|
memsize += gimp_object_get_memsize (GIMP_OBJECT (priv->container_obsolete),
|
|
|
|
gui_size);
|
|
|
|
|
|
|
|
return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
|
|
|
|
gui_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_data_factory_real_data_save (GimpDataFactory *factory)
|
2001-02-13 19:53:07 +00:00
|
|
|
{
|
2018-06-02 21:50:34 +02:00
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
|
|
|
|
GList *dirty = NULL;
|
|
|
|
GList *list;
|
|
|
|
GFile *writable_dir;
|
|
|
|
GError *error = NULL;
|
2001-02-17 21:20:10 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
for (list = GIMP_LIST (priv->container)->queue->head;
|
2015-07-21 19:24:45 +02:00
|
|
|
list;
|
|
|
|
list = g_list_next (list))
|
|
|
|
{
|
|
|
|
GimpData *data = list->data;
|
|
|
|
|
|
|
|
if (gimp_data_is_dirty (data) &&
|
|
|
|
gimp_data_is_writable (data))
|
|
|
|
{
|
|
|
|
dirty = g_list_prepend (dirty, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! dirty)
|
|
|
|
return;
|
|
|
|
|
2009-10-30 21:31:13 +01:00
|
|
|
writable_dir = gimp_data_factory_get_save_dir (factory, &error);
|
2001-02-17 21:20:10 +00:00
|
|
|
|
2004-01-28 21:53:50 +00:00
|
|
|
if (! writable_dir)
|
2009-10-30 21:31:13 +01:00
|
|
|
{
|
2018-06-02 21:50:34 +02:00
|
|
|
gimp_message (priv->gimp, NULL, GIMP_MESSAGE_ERROR,
|
2009-10-30 21:31:13 +01:00
|
|
|
_("Failed to save data:\n\n%s"),
|
|
|
|
error->message);
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
2015-07-21 19:24:45 +02:00
|
|
|
g_list_free (dirty);
|
|
|
|
|
2009-10-30 21:31:13 +01:00
|
|
|
return;
|
|
|
|
}
|
2002-12-29 18:58:24 +00:00
|
|
|
|
2015-07-21 19:24:45 +02:00
|
|
|
for (list = dirty; list; list = g_list_next (list))
|
2004-01-28 21:53:50 +00:00
|
|
|
{
|
2015-07-21 19:24:45 +02:00
|
|
|
GimpData *data = list->data;
|
|
|
|
GError *error = NULL;
|
2001-02-17 21:20:10 +00:00
|
|
|
|
2014-07-01 01:19:35 +02:00
|
|
|
if (! gimp_data_get_file (data))
|
2004-07-05 18:10:05 +00:00
|
|
|
gimp_data_create_filename (data, writable_dir);
|
2001-02-17 21:20:10 +00:00
|
|
|
|
2018-06-10 15:52:06 +02:00
|
|
|
if (factory->priv->gimp->be_verbose)
|
|
|
|
{
|
|
|
|
GFile *file = gimp_data_get_file (data);
|
|
|
|
|
|
|
|
if (file)
|
|
|
|
g_print ("Writing dirty data '%s'\n",
|
|
|
|
gimp_file_get_utf8_name (file));
|
|
|
|
}
|
|
|
|
|
2015-07-21 19:24:45 +02:00
|
|
|
if (! gimp_data_save (data, &error))
|
2004-01-28 21:53:50 +00:00
|
|
|
{
|
2015-07-21 19:24:45 +02:00
|
|
|
/* check if there actually was an error (no error
|
|
|
|
* means the data class does not implement save)
|
|
|
|
*/
|
|
|
|
if (error)
|
2002-12-02 13:39:09 +00:00
|
|
|
{
|
2018-06-02 21:50:34 +02:00
|
|
|
gimp_message (priv->gimp, NULL, GIMP_MESSAGE_ERROR,
|
2015-07-21 19:24:45 +02:00
|
|
|
_("Failed to save data:\n\n%s"),
|
|
|
|
error->message);
|
|
|
|
g_clear_error (&error);
|
2002-12-02 13:39:09 +00:00
|
|
|
}
|
|
|
|
}
|
2001-02-17 21:20:10 +00:00
|
|
|
}
|
|
|
|
|
2014-07-26 16:37:30 +02:00
|
|
|
g_object_unref (writable_dir);
|
2015-07-21 19:24:45 +02:00
|
|
|
|
|
|
|
g_list_free (dirty);
|
2001-02-13 19:53:07 +00:00
|
|
|
}
|
|
|
|
|
app: add gimp_data_factory_data_cancel()
Add a new GimpData::data_cancel() virtual function, and a
corresponding gimp_data_factory_data_cancel() function. This
function should cancel any ongoing async operations related to the
factory (i.e., included in its async set), and wait for the
operations to finish. Provide a default implementation that simply
cancels and waits on the factory's async set.
Use this function to cancel any ongoing operations during factory
destruction, and in gimp_data_factory_data_free().
Override this function in GimpFontFactory, for which we can't
really cancel font loading, and simply cancel and clear the
factory's async set without waiting for loading to finish, making
sure that nothing happens (and, in particular, that the factory
isn't being accessed, since it might be already dead) when loading
does finish.
2018-10-01 03:30:08 -04:00
|
|
|
static void
|
|
|
|
gimp_data_factory_real_data_cancel (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
|
|
|
|
|
|
|
|
gimp_cancelable_cancel (GIMP_CANCELABLE (priv->async_set));
|
|
|
|
gimp_waitable_wait (GIMP_WAITABLE (priv->async_set));
|
|
|
|
}
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
static GimpData *
|
|
|
|
gimp_data_factory_real_data_duplicate (GimpDataFactory *factory,
|
|
|
|
GimpData *data)
|
2002-12-02 13:39:09 +00:00
|
|
|
{
|
2018-06-02 21:50:34 +02:00
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
|
|
|
|
GimpData *new_data;
|
2002-12-02 13:39:09 +00:00
|
|
|
|
2005-06-08 11:27:31 +00:00
|
|
|
new_data = gimp_data_duplicate (data);
|
2002-12-02 13:39:09 +00:00
|
|
|
|
|
|
|
if (new_data)
|
|
|
|
{
|
2009-08-31 22:47:18 +02:00
|
|
|
const gchar *name = gimp_object_get_name (data);
|
2002-12-02 13:39:09 +00:00
|
|
|
gchar *ext;
|
|
|
|
gint copy_len;
|
|
|
|
gint number;
|
|
|
|
gchar *new_name;
|
|
|
|
|
|
|
|
ext = strrchr (name, '#');
|
|
|
|
copy_len = strlen (_("copy"));
|
|
|
|
|
|
|
|
if ((strlen (name) >= copy_len &&
|
|
|
|
strcmp (&name[strlen (name) - copy_len], _("copy")) == 0) ||
|
|
|
|
(ext && (number = atoi (ext + 1)) > 0 &&
|
|
|
|
((gint) (log10 (number) + 1)) == strlen (ext + 1)))
|
|
|
|
{
|
|
|
|
/* don't have redundant "copy"s */
|
|
|
|
new_name = g_strdup (name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_name = g_strdup_printf (_("%s copy"), name);
|
|
|
|
}
|
|
|
|
|
2006-04-07 10:51:22 +00:00
|
|
|
gimp_object_take_name (GIMP_OBJECT (new_data), new_name);
|
2002-12-02 13:39:09 +00:00
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
gimp_container_add (priv->container, GIMP_OBJECT (new_data));
|
2002-12-02 13:39:09 +00:00
|
|
|
g_object_unref (new_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new_data;
|
|
|
|
}
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
static gboolean
|
|
|
|
gimp_data_factory_real_data_delete (GimpDataFactory *factory,
|
|
|
|
GimpData *data,
|
|
|
|
gboolean delete_from_disk,
|
|
|
|
GError **error)
|
2004-06-01 21:37:36 +00:00
|
|
|
{
|
2018-06-04 13:12:14 +02:00
|
|
|
if (delete_from_disk && gimp_data_get_file (data))
|
|
|
|
return gimp_data_delete_from_disk (data, error);
|
2004-06-01 21:37:36 +00:00
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
return TRUE;
|
2004-06-01 21:37:36 +00:00
|
|
|
}
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
|
|
|
|
/* public functions */
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_data_factory_data_init (GimpDataFactory *factory,
|
|
|
|
GimpContext *context,
|
|
|
|
gboolean no_data)
|
|
|
|
{
|
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
|
|
|
|
gchar *signal_name;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
|
|
|
|
g_return_if_fail (GIMP_IS_CONTEXT (context));
|
|
|
|
|
2018-06-03 23:16:29 +02:00
|
|
|
/* Always freeze() and thaw() the container around initialization,
|
|
|
|
* even if no_data, the thaw() will implicitly make GimpContext
|
|
|
|
* create the standard data that serves as fallback.
|
|
|
|
*/
|
|
|
|
gimp_container_freeze (priv->container);
|
|
|
|
|
|
|
|
if (! no_data)
|
|
|
|
{
|
|
|
|
if (priv->gimp->be_verbose)
|
|
|
|
{
|
|
|
|
const gchar *name = gimp_object_get_name (factory);
|
|
|
|
|
|
|
|
g_print ("Loading '%s' data\n", name ? name : "???");
|
|
|
|
}
|
|
|
|
|
|
|
|
GIMP_DATA_FACTORY_GET_CLASS (factory)->data_init (factory, context);
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_container_thaw (priv->container);
|
2018-06-02 21:50:34 +02:00
|
|
|
|
|
|
|
signal_name = g_strdup_printf ("notify::%s", priv->path_property_name);
|
|
|
|
g_signal_connect_object (priv->gimp->config, signal_name,
|
|
|
|
G_CALLBACK (gimp_data_factory_path_notify),
|
|
|
|
factory, 0);
|
|
|
|
g_free (signal_name);
|
2018-07-02 20:33:59 +02:00
|
|
|
|
|
|
|
signal_name = g_strdup_printf ("notify::%s", priv->ext_property_name);
|
|
|
|
g_signal_connect_object (priv->gimp->extension_manager, signal_name,
|
|
|
|
G_CALLBACK (gimp_data_factory_path_notify),
|
|
|
|
factory, 0);
|
|
|
|
g_free (signal_name);
|
2018-06-02 21:50:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_data_factory_clean_cb (GimpDataFactory *factory,
|
|
|
|
GimpData *data,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
if (gimp_data_is_dirty (data))
|
|
|
|
gimp_data_clean (data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_data_factory_data_clean (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
|
|
|
|
|
|
|
|
gimp_data_factory_data_foreach (factory, TRUE,
|
|
|
|
gimp_data_factory_clean_cb, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_data_factory_data_refresh (GimpDataFactory *factory,
|
|
|
|
GimpContext *context)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
|
|
|
|
g_return_if_fail (GIMP_IS_CONTEXT (context));
|
|
|
|
|
|
|
|
GIMP_DATA_FACTORY_GET_CLASS (factory)->data_refresh (factory, context);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_data_factory_data_save (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
|
|
|
|
|
|
|
|
if (! gimp_container_is_empty (factory->priv->container))
|
|
|
|
GIMP_DATA_FACTORY_GET_CLASS (factory)->data_save (factory);
|
|
|
|
}
|
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
static void
|
|
|
|
gimp_data_factory_data_free_foreach (GimpDataFactory *factory,
|
|
|
|
GimpData *data,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
gimp_container_remove (factory->priv->container, GIMP_OBJECT (data));
|
|
|
|
}
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
void
|
|
|
|
gimp_data_factory_data_free (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
|
|
|
|
|
app: add gimp_data_factory_data_cancel()
Add a new GimpData::data_cancel() virtual function, and a
corresponding gimp_data_factory_data_cancel() function. This
function should cancel any ongoing async operations related to the
factory (i.e., included in its async set), and wait for the
operations to finish. Provide a default implementation that simply
cancels and waits on the factory's async set.
Use this function to cancel any ongoing operations during factory
destruction, and in gimp_data_factory_data_free().
Override this function in GimpFontFactory, for which we can't
really cancel font loading, and simply cancel and clear the
factory's async set without waiting for loading to finish, making
sure that nothing happens (and, in particular, that the factory
isn't being accessed, since it might be already dead) when loading
does finish.
2018-10-01 03:30:08 -04:00
|
|
|
gimp_data_factory_data_cancel (factory);
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
if (! gimp_container_is_empty (factory->priv->container))
|
2018-06-04 13:12:14 +02:00
|
|
|
{
|
|
|
|
gimp_container_freeze (factory->priv->container);
|
|
|
|
|
|
|
|
gimp_data_factory_data_foreach (factory, TRUE,
|
|
|
|
gimp_data_factory_data_free_foreach,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
gimp_container_thaw (factory->priv->container);
|
|
|
|
}
|
2018-06-02 21:50:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
GimpAsyncSet *
|
|
|
|
gimp_data_factory_get_async_set (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
|
|
|
|
|
2018-06-03 22:28:00 +02:00
|
|
|
return factory->priv->async_set;
|
2018-06-02 21:50:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gimp_data_factory_data_wait (GimpDataFactory *factory)
|
|
|
|
{
|
2018-06-03 22:28:00 +02:00
|
|
|
GimpDataFactoryPrivate *priv;
|
|
|
|
GimpWaitable *waitable;
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), FALSE);
|
|
|
|
|
2018-06-03 22:28:00 +02:00
|
|
|
priv = GET_PRIVATE (factory);
|
|
|
|
|
|
|
|
/* don't allow cancellation for now */
|
|
|
|
waitable = gimp_uncancelable_waitable_new (GIMP_WAITABLE (priv->async_set));
|
|
|
|
|
|
|
|
gimp_wait (priv->gimp, waitable,
|
|
|
|
_("Loading fonts (this may take a while...)"));
|
|
|
|
|
|
|
|
g_object_unref (waitable);
|
|
|
|
|
|
|
|
return TRUE;
|
2018-06-02 21:50:34 +02:00
|
|
|
}
|
|
|
|
|
app: add gimp_data_factory_data_cancel()
Add a new GimpData::data_cancel() virtual function, and a
corresponding gimp_data_factory_data_cancel() function. This
function should cancel any ongoing async operations related to the
factory (i.e., included in its async set), and wait for the
operations to finish. Provide a default implementation that simply
cancels and waits on the factory's async set.
Use this function to cancel any ongoing operations during factory
destruction, and in gimp_data_factory_data_free().
Override this function in GimpFontFactory, for which we can't
really cancel font loading, and simply cancel and clear the
factory's async set without waiting for loading to finish, making
sure that nothing happens (and, in particular, that the factory
isn't being accessed, since it might be already dead) when loading
does finish.
2018-10-01 03:30:08 -04:00
|
|
|
void
|
|
|
|
gimp_data_factory_data_cancel (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
|
|
|
|
|
|
|
|
GIMP_DATA_FACTORY_GET_CLASS (factory)->data_cancel (factory);
|
|
|
|
}
|
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
gboolean
|
|
|
|
gimp_data_factory_has_data_new_func (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), FALSE);
|
|
|
|
|
|
|
|
return factory->priv->data_new_func != NULL;
|
|
|
|
}
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
GimpData *
|
|
|
|
gimp_data_factory_data_new (GimpDataFactory *factory,
|
|
|
|
GimpContext *context,
|
|
|
|
const gchar *name)
|
|
|
|
{
|
2018-06-04 13:12:14 +02:00
|
|
|
GimpDataFactoryPrivate *priv;
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
|
|
|
|
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
|
|
|
|
g_return_val_if_fail (name != NULL, NULL);
|
|
|
|
g_return_val_if_fail (*name != '\0', NULL);
|
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
priv = GET_PRIVATE (factory);
|
|
|
|
|
|
|
|
if (priv->data_new_func)
|
|
|
|
{
|
|
|
|
GimpData *data = priv->data_new_func (context, name);
|
|
|
|
|
|
|
|
if (data)
|
|
|
|
{
|
|
|
|
gimp_container_add (priv->container, GIMP_OBJECT (data));
|
|
|
|
g_object_unref (data);
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_warning ("%s: GimpDataFactory::data_new_func() returned NULL",
|
|
|
|
G_STRFUNC);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
GimpData *
|
|
|
|
gimp_data_factory_data_get_standard (GimpDataFactory *factory,
|
|
|
|
GimpContext *context)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
|
|
|
|
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
|
|
|
|
|
|
|
|
if (factory->priv->data_get_standard_func)
|
|
|
|
return factory->priv->data_get_standard_func (context);
|
|
|
|
|
|
|
|
return NULL;
|
2018-06-02 21:50:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
GimpData *
|
|
|
|
gimp_data_factory_data_duplicate (GimpDataFactory *factory,
|
|
|
|
GimpData *data)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA (data), NULL);
|
|
|
|
|
|
|
|
return GIMP_DATA_FACTORY_GET_CLASS (factory)->data_duplicate (factory, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gimp_data_factory_data_delete (GimpDataFactory *factory,
|
|
|
|
GimpData *data,
|
|
|
|
gboolean delete_from_disk,
|
|
|
|
GError **error)
|
|
|
|
{
|
2018-06-04 13:12:14 +02:00
|
|
|
GimpDataFactoryPrivate *priv;
|
|
|
|
gboolean retval = TRUE;
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), FALSE);
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
|
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
priv = GET_PRIVATE (factory);
|
2018-06-02 21:50:34 +02:00
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
if (gimp_container_have (priv->container, GIMP_OBJECT (data)))
|
|
|
|
{
|
|
|
|
g_object_ref (data);
|
2001-02-14 01:42:12 +00:00
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
gimp_container_remove (priv->container, GIMP_OBJECT (data));
|
2001-02-14 01:42:12 +00:00
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
retval = GIMP_DATA_FACTORY_GET_CLASS (factory)->data_delete (factory, data,
|
|
|
|
delete_from_disk,
|
|
|
|
error);
|
|
|
|
|
|
|
|
g_object_unref (data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
2001-02-14 01:42:12 +00:00
|
|
|
}
|
|
|
|
|
2004-01-28 21:53:50 +00:00
|
|
|
gboolean
|
2006-10-09 18:49:15 +00:00
|
|
|
gimp_data_factory_data_save_single (GimpDataFactory *factory,
|
|
|
|
GimpData *data,
|
|
|
|
GError **error)
|
2004-01-28 21:53:50 +00:00
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), FALSE);
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
|
2006-10-09 18:49:15 +00:00
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
2004-01-28 21:53:50 +00:00
|
|
|
|
2009-10-31 18:48:38 +01:00
|
|
|
if (! gimp_data_is_dirty (data))
|
2004-01-28 21:53:50 +00:00
|
|
|
return TRUE;
|
|
|
|
|
2014-07-01 01:19:35 +02:00
|
|
|
if (! gimp_data_get_file (data))
|
2004-10-04 09:39:27 +00:00
|
|
|
{
|
2014-07-26 16:37:30 +02:00
|
|
|
GFile *writable_dir;
|
2009-10-30 21:31:13 +01:00
|
|
|
GError *my_error = NULL;
|
|
|
|
|
|
|
|
writable_dir = gimp_data_factory_get_save_dir (factory, &my_error);
|
2004-01-28 21:53:50 +00:00
|
|
|
|
2004-10-04 09:39:27 +00:00
|
|
|
if (! writable_dir)
|
2006-10-09 18:49:15 +00:00
|
|
|
{
|
|
|
|
g_set_error (error, GIMP_DATA_ERROR, 0,
|
|
|
|
_("Failed to save data:\n\n%s"),
|
2009-10-30 21:31:13 +01:00
|
|
|
my_error->message);
|
|
|
|
g_clear_error (&my_error);
|
|
|
|
|
2006-10-09 18:49:15 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2004-01-28 21:53:50 +00:00
|
|
|
|
2004-10-04 09:39:27 +00:00
|
|
|
gimp_data_create_filename (data, writable_dir);
|
|
|
|
|
2014-07-26 16:37:30 +02:00
|
|
|
g_object_unref (writable_dir);
|
2004-10-04 09:39:27 +00:00
|
|
|
}
|
|
|
|
|
2009-10-31 18:48:38 +01:00
|
|
|
if (! gimp_data_is_writable (data))
|
2004-10-04 09:39:27 +00:00
|
|
|
return FALSE;
|
2004-01-28 21:53:50 +00:00
|
|
|
|
2018-06-10 15:52:06 +02:00
|
|
|
if (factory->priv->gimp->be_verbose)
|
|
|
|
{
|
|
|
|
GFile *file = gimp_data_get_file (data);
|
|
|
|
|
|
|
|
if (file)
|
|
|
|
g_print ("Writing dirty data '%s'\n",
|
|
|
|
gimp_file_get_utf8_name (file));
|
|
|
|
}
|
|
|
|
|
2006-10-09 18:49:15 +00:00
|
|
|
if (! gimp_data_save (data, error))
|
2004-01-28 21:53:50 +00:00
|
|
|
{
|
|
|
|
/* check if there actually was an error (no error
|
|
|
|
* means the data class does not implement save)
|
|
|
|
*/
|
2006-10-09 18:49:15 +00:00
|
|
|
if (! error)
|
|
|
|
g_set_error (error, GIMP_DATA_ERROR, 0,
|
|
|
|
_("Failed to save data:\n\n%s"),
|
|
|
|
"Data class does not implement saving");
|
2004-01-28 21:53:50 +00:00
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-06-04 12:44:50 +02:00
|
|
|
void
|
|
|
|
gimp_data_factory_data_foreach (GimpDataFactory *factory,
|
|
|
|
gboolean skip_internal,
|
|
|
|
GimpDataForeachFunc callback,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GList *list;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
|
|
|
|
g_return_if_fail (callback != NULL);
|
|
|
|
|
|
|
|
list = GIMP_LIST (factory->priv->container)->queue->head;
|
|
|
|
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
GList *next = g_list_next (list);
|
|
|
|
|
2018-10-01 02:25:22 -04:00
|
|
|
if (! (skip_internal && gimp_data_is_internal (list->data)))
|
|
|
|
callback (factory, list->data, user_data);
|
2018-06-04 12:44:50 +02:00
|
|
|
|
|
|
|
list = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-04 13:12:14 +02:00
|
|
|
Gimp *
|
|
|
|
gimp_data_factory_get_gimp (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
|
|
|
|
|
|
|
|
return factory->priv->gimp;
|
|
|
|
}
|
|
|
|
|
2012-10-07 00:17:01 +02:00
|
|
|
GType
|
|
|
|
gimp_data_factory_get_data_type (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), G_TYPE_NONE);
|
|
|
|
|
|
|
|
return gimp_container_get_children_type (factory->priv->container);
|
|
|
|
}
|
|
|
|
|
2008-12-19 21:58:17 +00:00
|
|
|
GimpContainer *
|
|
|
|
gimp_data_factory_get_container (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
|
|
|
|
|
|
|
|
return factory->priv->container;
|
|
|
|
}
|
|
|
|
|
2009-08-11 20:38:12 +02:00
|
|
|
GimpContainer *
|
|
|
|
gimp_data_factory_get_container_obsolete (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
|
|
|
|
|
|
|
|
return factory->priv->container_obsolete;
|
|
|
|
}
|
|
|
|
|
2018-06-03 20:42:21 +02:00
|
|
|
GList *
|
|
|
|
gimp_data_factory_get_data_path (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
|
|
|
|
gchar *path = NULL;
|
|
|
|
GList *list = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
|
|
|
|
|
|
|
|
g_object_get (priv->gimp->config,
|
|
|
|
priv->path_property_name, &path,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (path)
|
|
|
|
{
|
|
|
|
list = gimp_config_path_expand_to_files (path, NULL);
|
|
|
|
g_free (path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
GList *
|
|
|
|
gimp_data_factory_get_data_path_writable (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
|
|
|
|
gchar *path = NULL;
|
|
|
|
GList *list = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
|
|
|
|
|
|
|
|
g_object_get (priv->gimp->config,
|
|
|
|
priv->writable_property_name, &path,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (path)
|
|
|
|
{
|
|
|
|
list = gimp_config_path_expand_to_files (path, NULL);
|
|
|
|
g_free (path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2018-07-02 20:33:59 +02:00
|
|
|
const GList *
|
|
|
|
gimp_data_factory_get_data_path_ext (GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
|
|
|
|
GList *list = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
|
|
|
|
|
|
|
|
g_object_get (priv->gimp->extension_manager,
|
|
|
|
priv->ext_property_name, &list,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2004-01-28 21:53:50 +00:00
|
|
|
|
|
|
|
/* private functions */
|
|
|
|
|
2018-06-02 21:50:34 +02:00
|
|
|
static void
|
|
|
|
gimp_data_factory_path_notify (GObject *object,
|
|
|
|
const GParamSpec *pspec,
|
|
|
|
GimpDataFactory *factory)
|
|
|
|
{
|
|
|
|
GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
|
|
|
|
|
|
|
|
gimp_set_busy (priv->gimp);
|
|
|
|
|
|
|
|
gimp_data_factory_data_refresh (factory, gimp_get_user_context (priv->gimp));
|
|
|
|
|
|
|
|
gimp_unset_busy (priv->gimp);
|
|
|
|
}
|
|
|
|
|
2014-07-26 16:37:30 +02:00
|
|
|
static GFile *
|
2009-10-30 21:31:13 +01:00
|
|
|
gimp_data_factory_get_save_dir (GimpDataFactory *factory,
|
|
|
|
GError **error)
|
2004-01-28 21:53:50 +00:00
|
|
|
{
|
2014-07-26 16:37:30 +02:00
|
|
|
GList *path;
|
|
|
|
GList *writable_path;
|
|
|
|
GFile *writable_dir = NULL;
|
2004-01-28 21:53:50 +00:00
|
|
|
|
2018-06-03 20:42:21 +02:00
|
|
|
path = gimp_data_factory_get_data_path (factory);
|
|
|
|
writable_path = gimp_data_factory_get_data_path_writable (factory);
|
2004-01-28 21:53:50 +00:00
|
|
|
|
2009-10-30 21:31:13 +01:00
|
|
|
if (writable_path)
|
2004-01-28 21:53:50 +00:00
|
|
|
{
|
2014-07-26 16:37:30 +02:00
|
|
|
GList *list;
|
|
|
|
gboolean found_any = FALSE;
|
2009-10-30 21:31:13 +01:00
|
|
|
|
2014-07-26 16:37:30 +02:00
|
|
|
for (list = writable_path; list; list = g_list_next (list))
|
2004-01-28 21:53:50 +00:00
|
|
|
{
|
2014-07-26 16:37:30 +02:00
|
|
|
GList *found = g_list_find_custom (path, list->data,
|
|
|
|
(GCompareFunc) gimp_file_compare);
|
2009-10-30 21:31:13 +01:00
|
|
|
if (found)
|
|
|
|
{
|
2014-07-26 16:37:30 +02:00
|
|
|
GFile *dir = found->data;
|
2009-10-30 21:31:13 +01:00
|
|
|
|
|
|
|
found_any = TRUE;
|
|
|
|
|
2014-07-26 16:37:30 +02:00
|
|
|
if (g_file_query_file_type (dir, G_FILE_QUERY_INFO_NONE,
|
|
|
|
NULL) != G_FILE_TYPE_DIRECTORY)
|
2009-10-30 21:31:13 +01:00
|
|
|
{
|
|
|
|
/* error out only if this is the last chance */
|
|
|
|
if (! list->next)
|
|
|
|
{
|
|
|
|
g_set_error (error, GIMP_DATA_ERROR, 0,
|
|
|
|
_("You have a writable data folder "
|
|
|
|
"configured (%s), but this folder does "
|
|
|
|
"not exist. Please create the folder or "
|
2013-12-10 14:48:08 +13:00
|
|
|
"fix your configuration in the "
|
2009-12-26 20:46:19 +01:00
|
|
|
"Preferences dialog's 'Folders' section."),
|
2014-07-26 16:37:30 +02:00
|
|
|
gimp_file_get_utf8_name (dir));
|
2009-10-30 21:31:13 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-07-26 16:37:30 +02:00
|
|
|
writable_dir = g_object_ref (dir);
|
2009-10-30 21:31:13 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-01-28 21:53:50 +00:00
|
|
|
}
|
2009-10-30 21:31:13 +01:00
|
|
|
|
|
|
|
if (! writable_dir && ! found_any)
|
|
|
|
{
|
|
|
|
g_set_error (error, GIMP_DATA_ERROR, 0,
|
|
|
|
_("You have a writable data folder configured, but this "
|
2009-12-26 20:46:19 +01:00
|
|
|
"folder is not part of your data search path. You "
|
|
|
|
"probably edited the gimprc file manually, "
|
|
|
|
"please fix it in the Preferences dialog's 'Folders' "
|
2009-10-30 21:31:13 +01:00
|
|
|
"section."));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_set_error (error, GIMP_DATA_ERROR, 0,
|
|
|
|
_("You don't have any writable data folder configured."));
|
2004-01-28 21:53:50 +00:00
|
|
|
}
|
|
|
|
|
2017-07-15 18:38:01 +02:00
|
|
|
g_list_free_full (path, (GDestroyNotify) g_object_unref);
|
2014-07-26 16:37:30 +02:00
|
|
|
g_list_free_full (writable_path, (GDestroyNotify) g_object_unref);
|
2004-01-28 21:53:50 +00:00
|
|
|
|
|
|
|
return writable_dir;
|
|
|
|
}
|