app: save custom gradient across sessions
Add a framework for saving and restoring internal data objects, in gimp-internal-data.c. Internal data objects are saved in separate files under a new "internal-data" subdirectory of the user's gimp directory. The internal data is saved, restored, and cleared together with the tool options. Use this to save and restore the custom gradient. In the future, we might add similar writable internal data objects that we'd want to save.
This commit is contained in:
@ -44,6 +44,8 @@ libappcore_a_sources = \
|
|||||||
gimp-gradients.h \
|
gimp-gradients.h \
|
||||||
gimp-gui.c \
|
gimp-gui.c \
|
||||||
gimp-gui.h \
|
gimp-gui.h \
|
||||||
|
gimp-internal-data.c \
|
||||||
|
gimp-internal-data.h \
|
||||||
gimp-memsize.c \
|
gimp-memsize.c \
|
||||||
gimp-memsize.h \
|
gimp-memsize.h \
|
||||||
gimp-modules.c \
|
gimp-modules.c \
|
||||||
|
311
app/core/gimp-internal-data.c
Normal file
311
app/core/gimp-internal-data.c
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
/* GIMP - The GNU Image Manipulation Program
|
||||||
|
* Copyright (C) 1995-2002 Spencer Kimball, Peter Mattis, and others
|
||||||
|
*
|
||||||
|
* gimp-internal-data.c
|
||||||
|
* Copyright (C) 2017 Ell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (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
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
#include <gegl.h>
|
||||||
|
|
||||||
|
#include "libgimpbase/gimpbase.h"
|
||||||
|
|
||||||
|
#include "core-types.h"
|
||||||
|
|
||||||
|
#include "gimp.h"
|
||||||
|
#include "gimp-gradients.h"
|
||||||
|
#include "gimp-internal-data.h"
|
||||||
|
#include "gimpdata.h"
|
||||||
|
#include "gimpdatafactory.h"
|
||||||
|
#include "gimperror.h"
|
||||||
|
#include "gimpgradient-load.h"
|
||||||
|
|
||||||
|
#include "gimp-intl.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define GIMP_INTERNAL_DATA_DIRECTORY "internal-data"
|
||||||
|
|
||||||
|
|
||||||
|
typedef GimpData * (* GimpDataGetFunc) (Gimp *gimp);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _GimpInternalDataFile GimpInternalDataFile;
|
||||||
|
|
||||||
|
struct _GimpInternalDataFile
|
||||||
|
{
|
||||||
|
const gchar *name;
|
||||||
|
GimpDataGetFunc get_func;
|
||||||
|
GimpDataLoadFunc load_func;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* local function prototypes */
|
||||||
|
|
||||||
|
static gboolean gimp_internal_data_create_directory (GError **error);
|
||||||
|
|
||||||
|
static GFile * gimp_internal_data_get_file (const GimpInternalDataFile *data_file);
|
||||||
|
|
||||||
|
static gboolean gimp_internal_data_load_data_file (Gimp *gimp,
|
||||||
|
const GimpInternalDataFile *data_file,
|
||||||
|
GError **error);
|
||||||
|
static gboolean gimp_internal_data_save_data_file (Gimp *gimp,
|
||||||
|
const GimpInternalDataFile *data_file,
|
||||||
|
GError **error);
|
||||||
|
static gboolean gimp_internal_data_delete_data_file (Gimp *gimp,
|
||||||
|
const GimpInternalDataFile *data_file,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
/* static variables */
|
||||||
|
|
||||||
|
static const GimpInternalDataFile internal_data_files[] = {
|
||||||
|
/* Custom gradient */
|
||||||
|
{
|
||||||
|
.name = "custom" GIMP_GRADIENT_FILE_EXTENSION,
|
||||||
|
.get_func = (GimpDataGetFunc) gimp_gradients_get_custom,
|
||||||
|
.load_func = gimp_gradient_load
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* public functions */
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gimp_internal_data_load (Gimp *gimp,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (internal_data_files); i++)
|
||||||
|
{
|
||||||
|
const GimpInternalDataFile *data_file = &internal_data_files[i];
|
||||||
|
|
||||||
|
if (! gimp_internal_data_load_data_file (gimp, data_file, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gimp_internal_data_save (Gimp *gimp,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
if (! gimp_internal_data_create_directory (error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (internal_data_files); i++)
|
||||||
|
{
|
||||||
|
const GimpInternalDataFile *data_file = &internal_data_files[i];
|
||||||
|
|
||||||
|
if (! gimp_internal_data_save_data_file (gimp, data_file, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gimp_internal_data_clear (Gimp *gimp,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (internal_data_files); i++)
|
||||||
|
{
|
||||||
|
const GimpInternalDataFile *data_file = &internal_data_files[i];
|
||||||
|
|
||||||
|
if (! gimp_internal_data_delete_data_file (gimp, data_file, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* private functions */
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gimp_internal_data_create_directory (GError **error)
|
||||||
|
{
|
||||||
|
GFile *directory;
|
||||||
|
GError *my_error = NULL;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
|
directory = gimp_directory_file (GIMP_INTERNAL_DATA_DIRECTORY, NULL);
|
||||||
|
|
||||||
|
success = g_file_make_directory (directory, NULL, &my_error);
|
||||||
|
|
||||||
|
g_object_unref (directory);
|
||||||
|
|
||||||
|
if (! success)
|
||||||
|
{
|
||||||
|
if (my_error->code == G_IO_ERROR_EXISTS)
|
||||||
|
{
|
||||||
|
g_clear_error (&my_error);
|
||||||
|
success = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_propagate_error (error, my_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GFile *
|
||||||
|
gimp_internal_data_get_file (const GimpInternalDataFile *data_file)
|
||||||
|
{
|
||||||
|
return gimp_directory_file (GIMP_INTERNAL_DATA_DIRECTORY,
|
||||||
|
data_file->name,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gimp_internal_data_load_data_file (Gimp *gimp,
|
||||||
|
const GimpInternalDataFile *data_file,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GFile *file;
|
||||||
|
GInputStream *input;
|
||||||
|
GimpData *data;
|
||||||
|
GList *list;
|
||||||
|
GError *my_error = NULL;
|
||||||
|
|
||||||
|
file = gimp_internal_data_get_file (data_file);
|
||||||
|
|
||||||
|
if (gimp->be_verbose)
|
||||||
|
g_print ("Parsing '%s'\n", gimp_file_get_utf8_name (file));
|
||||||
|
|
||||||
|
input = G_INPUT_STREAM (g_file_read (file, NULL, &my_error));
|
||||||
|
|
||||||
|
if (! input)
|
||||||
|
{
|
||||||
|
g_object_unref (file);
|
||||||
|
|
||||||
|
if (my_error->code == G_IO_ERROR_NOT_FOUND)
|
||||||
|
{
|
||||||
|
g_clear_error (&my_error);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_propagate_error (error, my_error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list = data_file->load_func (gimp->user_context, file, input, error);
|
||||||
|
|
||||||
|
g_object_unref (input);
|
||||||
|
g_object_unref (file);
|
||||||
|
|
||||||
|
if (! list)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
data = data_file->get_func (gimp);
|
||||||
|
|
||||||
|
gimp_data_copy (data, GIMP_DATA (list->data));
|
||||||
|
|
||||||
|
g_list_free_full (list, g_object_unref);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gimp_internal_data_save_data_file (Gimp *gimp,
|
||||||
|
const GimpInternalDataFile *data_file,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GFile *file;
|
||||||
|
GOutputStream *output;
|
||||||
|
GimpData *data;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
|
file = gimp_internal_data_get_file (data_file);
|
||||||
|
|
||||||
|
if (gimp->be_verbose)
|
||||||
|
g_print ("Writing '%s'\n", gimp_file_get_utf8_name (file));
|
||||||
|
|
||||||
|
output = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE,
|
||||||
|
G_FILE_CREATE_REPLACE_DESTINATION,
|
||||||
|
NULL, error));
|
||||||
|
|
||||||
|
g_object_unref (file);
|
||||||
|
|
||||||
|
if (! output)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
data = data_file->get_func (gimp);
|
||||||
|
|
||||||
|
/* we bypass gimp_data_save() and call the data's save() virtual function
|
||||||
|
* directly, since gimp_data_save() is a nop for internal data.
|
||||||
|
*
|
||||||
|
* FIXME: we save the data whether it's dirty or not, since it might not
|
||||||
|
* exist on disk. currently, we only use this for cheap data, such as
|
||||||
|
* gradients, so this is not a big concern, but if we save more expensive
|
||||||
|
* data in the future, we should fix this.
|
||||||
|
*/
|
||||||
|
g_assert (GIMP_DATA_GET_CLASS (data)->save);
|
||||||
|
success = GIMP_DATA_GET_CLASS (data)->save (data, output, error);
|
||||||
|
|
||||||
|
g_object_unref (output);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gimp_internal_data_delete_data_file (Gimp *gimp,
|
||||||
|
const GimpInternalDataFile *data_file,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GFile *file;
|
||||||
|
GError *my_error = NULL;
|
||||||
|
gboolean success = TRUE;
|
||||||
|
|
||||||
|
file = gimp_internal_data_get_file (data_file);
|
||||||
|
|
||||||
|
if (gimp->be_verbose)
|
||||||
|
g_print ("Deleting '%s'\n", gimp_file_get_utf8_name (file));
|
||||||
|
|
||||||
|
if (! g_file_delete (file, NULL, &my_error) &&
|
||||||
|
my_error->code != G_IO_ERROR_NOT_FOUND)
|
||||||
|
{
|
||||||
|
success = FALSE;
|
||||||
|
|
||||||
|
g_set_error (error, GIMP_ERROR, GIMP_FAILED,
|
||||||
|
_("Deleting \"%s\" failed: %s"),
|
||||||
|
gimp_file_get_utf8_name (file), my_error->message);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_error (&my_error);
|
||||||
|
g_object_unref (file);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
34
app/core/gimp-internal-data.h
Normal file
34
app/core/gimp-internal-data.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/* GIMP - The GNU Image Manipulation Program
|
||||||
|
* Copyright (C) 1995-2002 Spencer Kimball, Peter Mattis, and others
|
||||||
|
*
|
||||||
|
* gimp-internal-data.h
|
||||||
|
* Copyright (C) 2017 Ell
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (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
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GIMP_INTERNAL_DATA__
|
||||||
|
#define __GIMP_INTERNAL_DATA__
|
||||||
|
|
||||||
|
|
||||||
|
gboolean gimp_internal_data_load (Gimp *gimp,
|
||||||
|
GError **error);
|
||||||
|
gboolean gimp_internal_data_save (Gimp *gimp,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean gimp_internal_data_clear (Gimp *gimp,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __GIMP_INTERNAL_DATA__ */
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "core/gimp.h"
|
#include "core/gimp.h"
|
||||||
#include "core/gimp-contexts.h"
|
#include "core/gimp-contexts.h"
|
||||||
|
#include "core/gimp-internal-data.h"
|
||||||
#include "core/gimplist.h"
|
#include "core/gimplist.h"
|
||||||
#include "core/gimptoolinfo.h"
|
#include "core/gimptoolinfo.h"
|
||||||
#include "core/gimptooloptions.h"
|
#include "core/gimptooloptions.h"
|
||||||
@ -326,6 +327,12 @@ gimp_tools_restore (Gimp *gimp)
|
|||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! gimp_internal_data_load (gimp, &error))
|
||||||
|
{
|
||||||
|
gimp_message_literal (gimp, NULL, GIMP_MESSAGE_WARNING, error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
|
||||||
/* make sure there is always a tool active, so broken config files
|
/* make sure there is always a tool active, so broken config files
|
||||||
* can't leave us with no initial tool
|
* can't leave us with no initial tool
|
||||||
*/
|
*/
|
||||||
@ -407,6 +414,13 @@ gimp_tools_save (Gimp *gimp,
|
|||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! gimp_internal_data_save (gimp, &error))
|
||||||
|
{
|
||||||
|
gimp_message_literal (gimp, NULL, GIMP_MESSAGE_WARNING,
|
||||||
|
error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
|
||||||
gimp_tool_options_create_folder ();
|
gimp_tool_options_create_folder ();
|
||||||
|
|
||||||
for (list = gimp_get_tool_info_iter (gimp);
|
for (list = gimp_get_tool_info_iter (gimp);
|
||||||
@ -453,6 +467,9 @@ gimp_tools_clear (Gimp *gimp,
|
|||||||
if (success)
|
if (success)
|
||||||
success = gimp_contexts_clear (gimp, error);
|
success = gimp_contexts_clear (gimp, error);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
success = gimp_internal_data_clear (gimp, error);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
tool_options_deleted = TRUE;
|
tool_options_deleted = TRUE;
|
||||||
|
|
||||||
|
@ -106,6 +106,7 @@ app/core/gimp-data-factories.c
|
|||||||
app/core/gimp-edit.c
|
app/core/gimp-edit.c
|
||||||
app/core/gimp-gradients.c
|
app/core/gimp-gradients.c
|
||||||
app/core/gimp-gui.c
|
app/core/gimp-gui.c
|
||||||
|
app/core/gimp-internal-data.c
|
||||||
app/core/gimp-modules.c
|
app/core/gimp-modules.c
|
||||||
app/core/gimp-palettes.c
|
app/core/gimp-palettes.c
|
||||||
app/core/gimp-tags.c
|
app/core/gimp-tags.c
|
||||||
|
Reference in New Issue
Block a user