gimp/app/config/gimprc.c

542 lines
14 KiB
C
Raw Normal View History

/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* GimpRc, the object for GIMPs user configuration file gimprc.
* Copyright (C) 2001-2002 Sven Neumann <sven@gimp.org>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <glib-object.h>
#ifdef G_OS_WIN32
#include <io.h>
#endif
#include "libgimpbase/gimpbase.h"
#include "libgimpbase/gimpbase.h"
Finally landed the new GimpConfig based gimprc parser. It's not finished 2002-11-18 Sven Neumann <sven@gimp.org> Finally landed the new GimpConfig based gimprc parser. It's not finished yet but we need to start somewhere. This release removes the old gimprc.[ch] files. The gimprc format changes slightly, but the changes are minimal. The Preferences dialog is temporarily disabled since it still needs to be ported. If you are are afraid, stay away from CVS for a few days ;-) * app/Makefile.am * app/gimprc.[ch]: removed the old gimprc system. * app/base/Makefile.am * app/base/base-config.[ch]: removed these files in favor of config/gimpbaseconfig.[ch]. * app/core/Makefile.am * app/core/gimpcoreconfig.[ch]: removed these files in favor of config/gimpcoreconfig.[ch]. * app/config/Makefile.am * app/config/config-types.h: moved typedefs into this new file. * app/config/gimpbaseconfig.[ch] * app/config/gimpcoreconfig.[ch] * app/config/gimpdisplayconfig.[ch] * app/config/gimpguiconfig.[ch] * app/config/gimprc.[ch] * app/config/test-config.c: brought into shape for real use. * app/base/base-types.h: include config/config-types.h here. Added a global GimpBaseConfig *base_config variable to ease migration. * app/gui/Makefile.am: temporarily disabled the preferences dialog. * app/app_procs.c * app/undo.c * app/undo_history.c * app/base/base.[ch] * app/base/gimphistogram.c * app/base/pixel-processor.c * app/base/temp-buf.c * app/base/tile-cache.c * app/core/core-types.h * app/core/gimp-documents.c * app/core/gimp.c * app/core/gimpbrush.c * app/core/gimpbrushgenerated.c * app/core/gimpcontext.c * app/core/gimpdrawable-transform.c * app/core/gimpimage-new.c * app/core/gimpimage.c * app/core/gimpimagefile.c * app/core/gimpmodules.c * app/core/gimppattern.c * app/display/Makefile.am * app/display/gimpdisplay-handlers.c * app/display/gimpdisplay.[ch] * app/display/gimpdisplayshell-callbacks.c * app/display/gimpdisplayshell-handlers.c * app/display/gimpdisplayshell-layer-select.c * app/display/gimpdisplayshell-render.c * app/display/gimpdisplayshell-scale.c * app/display/gimpdisplayshell-scroll.c * app/display/gimpdisplayshell-selection.c * app/display/gimpdisplayshell.[ch] * app/display/gimpnavigationview.c * app/file/file-save.c * app/gui/device-status-dialog.c * app/gui/dialogs-constructors.c * app/gui/file-commands.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/file-save-dialog.c * app/gui/gui.c * app/gui/menus.c * app/gui/paths-dialog.c * app/gui/resize-dialog.c * app/gui/session.c * app/gui/test-commands.c * app/gui/tips-dialog.c * app/gui/tips-dialog.h * app/gui/user-install-dialog.c * app/gui/view-commands.c * app/paint/gimppaintcore.c * app/plug-in/plug-in.c * app/plug-in/plug-ins.c * app/tools/gimpbezierselecttool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpcolorpickertool.c * app/tools/gimpcroptool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpfuzzyselecttool.c * app/tools/gimpinktool.c * app/tools/gimpmagnifytool.c * app/tools/gimpmeasuretool.c * app/tools/gimppainttool.c * app/tools/gimppathtool.c * app/tools/gimptexttool.[ch] * app/tools/selection_options.c * app/tools/tools.c * app/tools/transform_options.c * app/widgets/gimphelp.c * app/widgets/gimpitemfactory.c * app/widgets/gimpselectioneditor.c * app/xcf/xcf-load.c * tools/pdbgen/pdb/fileops.pdb * tools/pdbgen/pdb/gimprc.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/transform_tools.pdb: use the new config system instead of the old gimprc stuff. * etc/gimprc.in * etc/gimprc_user.in: adapted to the new gimprc format. Will update the man-page later... * app/pdb/fileops_cmds.c * app/pdb/gimprc_cmds.c * app/pdb/image_cmds.c * app/pdb/layer_cmds.c * app/pdb/transform_tools_cmds.c * libgimp/gimpgimprc_pdb.c: regenerated.
2002-11-19 04:50:31 +08:00
#include "config-types.h"
#include "gimpconfig.h"
#include "gimpconfig-deserialize.h"
#include "gimpconfig-params.h"
#include "gimpconfig-serialize.h"
#include "gimpconfig-utils.h"
#include "gimprc.h"
#include "libgimp/gimpintl.h"
enum {
PROP_0,
PROP_SYSTEM_GIMPRC,
PROP_USER_GIMPRC
};
static void gimp_rc_class_init (GimpRcClass *klass);
static void gimp_rc_config_iface_init (gpointer iface,
gpointer iface_data);
static void gimp_rc_init (GimpRc *rc);
static void gimp_rc_dispose (GObject *object);
static void gimp_rc_finalize (GObject *object);
static void gimp_rc_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_rc_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static gboolean gimp_rc_serialize (GObject *object,
gint fd,
gint indent_level,
gpointer data);
static gboolean gimp_rc_deserialize (GObject *object,
GScanner *scanner,
gint nest_level,
gpointer data);
static GObject * gimp_rc_duplicate (GObject *object);
static void gimp_rc_load (GimpRc *rc);
static gboolean gimp_rc_idle_save (GimpRc *rc);
static void gimp_rc_notify (GimpRc *rc,
GParamSpec *param,
gpointer data);
static GObjectClass *parent_class = NULL;
GType
gimp_rc_get_type (void)
{
static GType rc_type = 0;
if (! rc_type)
{
static const GTypeInfo rc_info =
{
sizeof (GimpRcClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gimp_rc_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GimpRc),
0, /* n_preallocs */
(GInstanceInitFunc) gimp_rc_init
};
static const GInterfaceInfo rc_iface_info =
{
gimp_rc_config_iface_init,
NULL, /* iface_finalize */
NULL /* iface_data */
};
rc_type = g_type_register_static (GIMP_TYPE_GUI_CONFIG,
"GimpRc", &rc_info, 0);
g_type_add_interface_static (rc_type,
GIMP_TYPE_CONFIG_INTERFACE,
&rc_iface_info);
}
return rc_type;
}
static void
gimp_rc_class_init (GimpRcClass *klass)
{
GObjectClass *object_class;
parent_class = g_type_class_peek_parent (klass);
object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gimp_rc_dispose;
object_class->finalize = gimp_rc_finalize;
object_class->set_property = gimp_rc_set_property;
object_class->get_property = gimp_rc_get_property;
g_object_class_install_property (object_class, PROP_SYSTEM_GIMPRC,
g_param_spec_string ("system-gimprc",
NULL, NULL, NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class, PROP_USER_GIMPRC,
g_param_spec_string ("user-gimprc",
NULL, NULL, NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
}
static void
gimp_rc_init (GimpRc *rc)
{
rc->system_gimprc = NULL;
rc->user_gimprc = NULL;
rc->verbose = FALSE;
rc->autosave = FALSE;
rc->save_idle_id = 0;
}
static void
gimp_rc_dispose (GObject *object)
{
GimpRc *rc = GIMP_RC (object);
if (rc->save_idle_id)
gimp_rc_idle_save (rc);
}
static void
gimp_rc_finalize (GObject *object)
{
GimpRc *rc = (GimpRc *) object;
if (rc->system_gimprc)
{
g_free (rc->system_gimprc);
rc->system_gimprc = NULL;
}
if (rc->user_gimprc)
{
g_free (rc->user_gimprc);
rc->user_gimprc = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gimp_rc_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpRc *rc = GIMP_RC (object);
const gchar *filename = NULL;
switch (property_id)
{
case PROP_SYSTEM_GIMPRC:
case PROP_USER_GIMPRC:
filename = g_value_get_string (value);
break;
}
switch (property_id)
{
case PROP_SYSTEM_GIMPRC:
g_free (rc->system_gimprc);
if (filename)
rc->system_gimprc = g_strdup (filename);
else
rc->system_gimprc = g_build_filename (gimp_sysconf_directory (),
"gimprc", NULL);
break;
case PROP_USER_GIMPRC:
g_free (rc->user_gimprc);
if (filename)
rc->user_gimprc = g_strdup (filename);
else
rc->user_gimprc = gimp_personal_rc_file ("gimprc");
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_rc_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpRc *rc = GIMP_RC (object);
switch (property_id)
{
case PROP_SYSTEM_GIMPRC:
g_value_set_string (value, rc->system_gimprc);
break;
case PROP_USER_GIMPRC:
g_value_set_string (value, rc->user_gimprc);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_rc_config_iface_init (gpointer iface,
gpointer iface_data)
{
GimpConfigInterface *config_iface = (GimpConfigInterface *) iface;
config_iface->serialize = gimp_rc_serialize;
config_iface->deserialize = gimp_rc_deserialize;
config_iface->duplicate = gimp_rc_duplicate;
}
static gboolean
gimp_rc_serialize (GObject *object,
gint fd,
gint indent_level,
gpointer data)
{
if (!gimp_config_serialize_unknown_tokens (object, fd, indent_level))
return FALSE;
if (write (fd, "\n", 1) < 0)
return FALSE;
if (data && GIMP_IS_RC (data))
return gimp_config_serialize_changed_properties (object, G_OBJECT (data),
fd, indent_level);
else
return gimp_config_serialize_properties (object, fd, indent_level);
}
static gboolean
gimp_rc_deserialize (GObject *object,
GScanner *scanner,
added "gint nest_level" to the deserialization functions, so nested calls 2002-05-27 Michael Natterer <mitch@gimp.org> * app/config/gimpconfig.[ch]: added "gint nest_level" to the deserialization functions, so nested calls to deserialize() don't error on the trailing ')'. Made the scanner config parse one-character identifiers and allow G_CSET_A_2_Z for all identifiers. Added gimp_config_deserialize_return() because returning the correct return value from a deserialize() function is not trivial any more with nested calls. * app/config/gimpconfig-deserialize.[ch] * app/config/gimprc.c * app/core/gimpdocumentlist.c * app/core/gimpparasitelist.c: use the new return value utility function and made the main parsing loops simpler. * app/core/gimpunits.c: made the main parsing loops consistent with the stuff that uses GimpConfig. * app/config/gimpconfig-deserialize.c * app/config/gimpconfig-serialize.c: call the (de)serialize_property() functions only if the property's class implements the method itself (does *not* inherit it from one of it's parents). * app/core/gimpcontainer.c: implemented deserialization of containers. For each child entry encountered in the input, check if it's already contained in the container and create it if not. If a "gimp" pointer is passed as user_data pass it as construct property to g_object_new() when creating the object. * app/core/gimpcontext.c: changed deserialization of brush, pattern etc. to honor "no_data". * app/widgets/gimpdeviceinfo.c: added a "gimp" construct_only property which overrides GimpContext's "gimp" property. Moved all initialisation code from gimp_device_info_new() to gimp_device_info_set_property(PROP_GIMP) so it is properly performed if the object is created by GimpContainer's deserialize() implementation. * app/widgets/gimpdevices.c: made gimp_devices_restore_test() work.
2002-05-27 22:04:21 +08:00
gint nest_level,
gpointer data)
{
return gimp_config_deserialize_properties (object,
scanner, nest_level, TRUE);
}
static void
gimp_rc_duplicate_unknown_token (const gchar *key,
const gchar *value,
gpointer user_data)
{
gimp_config_add_unknown_token (G_OBJECT (user_data), key, value);
}
static GObject *
gimp_rc_duplicate (GObject *object)
{
GObject *dup = g_object_new (GIMP_TYPE_RC, NULL);
gimp_config_copy_properties (object, dup);
gimp_config_foreach_unknown_token (object,
gimp_rc_duplicate_unknown_token, dup);
return dup;
}
static void
gimp_rc_load (GimpRc *rc)
{
GError *error = NULL;
g_return_if_fail (GIMP_IS_RC (rc));
if (rc->verbose)
g_print (_("Parsing '%s'\n"), rc->system_gimprc);
if (! gimp_config_deserialize (G_OBJECT (rc),
rc->system_gimprc, NULL, &error))
{
if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT)
g_message (error->message);
g_clear_error (&error);
}
if (rc->verbose)
g_print (_("Parsing '%s'\n"), rc->user_gimprc);
if (! gimp_config_deserialize (G_OBJECT (rc),
rc->user_gimprc, NULL, &error))
{
if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT)
g_message (error->message);
g_clear_error (&error);
}
}
static gboolean
gimp_rc_idle_save (GimpRc *rc)
{
gimp_rc_save (rc);
rc->save_idle_id = 0;
return FALSE;
}
static void
gimp_rc_notify (GimpRc *rc,
GParamSpec *param,
gpointer data)
{
if (!rc->autosave)
return;
if (!rc->save_idle_id)
rc->save_idle_id = g_idle_add ((GSourceFunc) gimp_rc_idle_save, rc);
}
/**
* gimp_rc_new:
* @system_gimprc: the name of the system-wide gimprc file or %NULL to
* use the standard location
* @user_gimprc: the name of the user gimprc file or %NULL to use the
* standard location
* @verbose:
*
* Creates a new GimpRc object and loads the system-wide and the user
* configuration files.
*
* Returns: the new #GimpRc.
*/
GimpRc *
gimp_rc_new (const gchar *system_gimprc,
const gchar *user_gimprc,
gboolean verbose)
{
GimpRc *rc;
rc = GIMP_RC (g_object_new (GIMP_TYPE_RC,
"system-gimprc", system_gimprc,
"user-gimprc", user_gimprc,
NULL));
rc->verbose = verbose ? TRUE : FALSE;
g_return_val_if_fail (GIMP_IS_RC (rc), NULL);
gimp_rc_load (rc);
return rc;
}
void
gimp_rc_set_autosave (GimpRc *rc,
gboolean autosave)
{
g_return_if_fail (GIMP_IS_RC (rc));
autosave = autosave ? TRUE : FALSE;
if (rc->autosave == autosave)
return;
if (autosave)
g_signal_connect (G_OBJECT (rc), "notify",
G_CALLBACK (gimp_rc_notify),
NULL);
else
g_signal_handlers_disconnect_by_func (G_OBJECT (rc),
gimp_rc_notify, NULL);
rc->autosave = autosave;
}
/**
* gimp_rc_query:
* @rc: a #GimpRc object.
* @key: a string used as a key for the lookup.
*
* This function looks up @key in the object properties of @rc. If
* there's a matching property, a string representation of its value
* is returned. If no property is found, the list of unknown tokens
* attached to the @rc object is searched.
*
* Return value: a newly allocated string representing the value or %NULL
* if the key couldn't be found.
**/
gchar *
gimp_rc_query (GimpRc *rc,
const gchar *key)
{
GObjectClass *klass;
GObject *rc_object;
GParamSpec **property_specs;
GParamSpec *prop_spec;
guint i, n_property_specs;
gchar *retval = NULL;
g_return_val_if_fail (GIMP_IS_RC (rc), NULL);
g_return_val_if_fail (key != NULL, NULL);
rc_object = G_OBJECT (rc);
klass = G_OBJECT_GET_CLASS (rc);
property_specs = g_object_class_list_properties (klass, &n_property_specs);
if (!property_specs)
return NULL;
for (i = 0, prop_spec = NULL; i < n_property_specs && !prop_spec; i++)
{
prop_spec = property_specs[i];
if (! (prop_spec->flags & GIMP_PARAM_SERIALIZE) ||
strcmp (prop_spec->name, key))
{
prop_spec = NULL;
}
}
if (prop_spec)
{
GString *str = g_string_new (NULL);
GValue value = { 0, };
g_value_init (&value, prop_spec->value_type);
g_object_get_property (rc_object, prop_spec->name, &value);
if (gimp_config_serialize_value (&value, str, FALSE))
retval = g_string_free (str, FALSE);
else
g_string_free (str, TRUE);
g_value_unset (&value);
}
else
{
retval = g_strdup (gimp_config_lookup_unknown_token (rc_object, key));
}
g_free (property_specs);
return retval;
}
Finally landed the new GimpConfig based gimprc parser. It's not finished 2002-11-18 Sven Neumann <sven@gimp.org> Finally landed the new GimpConfig based gimprc parser. It's not finished yet but we need to start somewhere. This release removes the old gimprc.[ch] files. The gimprc format changes slightly, but the changes are minimal. The Preferences dialog is temporarily disabled since it still needs to be ported. If you are are afraid, stay away from CVS for a few days ;-) * app/Makefile.am * app/gimprc.[ch]: removed the old gimprc system. * app/base/Makefile.am * app/base/base-config.[ch]: removed these files in favor of config/gimpbaseconfig.[ch]. * app/core/Makefile.am * app/core/gimpcoreconfig.[ch]: removed these files in favor of config/gimpcoreconfig.[ch]. * app/config/Makefile.am * app/config/config-types.h: moved typedefs into this new file. * app/config/gimpbaseconfig.[ch] * app/config/gimpcoreconfig.[ch] * app/config/gimpdisplayconfig.[ch] * app/config/gimpguiconfig.[ch] * app/config/gimprc.[ch] * app/config/test-config.c: brought into shape for real use. * app/base/base-types.h: include config/config-types.h here. Added a global GimpBaseConfig *base_config variable to ease migration. * app/gui/Makefile.am: temporarily disabled the preferences dialog. * app/app_procs.c * app/undo.c * app/undo_history.c * app/base/base.[ch] * app/base/gimphistogram.c * app/base/pixel-processor.c * app/base/temp-buf.c * app/base/tile-cache.c * app/core/core-types.h * app/core/gimp-documents.c * app/core/gimp.c * app/core/gimpbrush.c * app/core/gimpbrushgenerated.c * app/core/gimpcontext.c * app/core/gimpdrawable-transform.c * app/core/gimpimage-new.c * app/core/gimpimage.c * app/core/gimpimagefile.c * app/core/gimpmodules.c * app/core/gimppattern.c * app/display/Makefile.am * app/display/gimpdisplay-handlers.c * app/display/gimpdisplay.[ch] * app/display/gimpdisplayshell-callbacks.c * app/display/gimpdisplayshell-handlers.c * app/display/gimpdisplayshell-layer-select.c * app/display/gimpdisplayshell-render.c * app/display/gimpdisplayshell-scale.c * app/display/gimpdisplayshell-scroll.c * app/display/gimpdisplayshell-selection.c * app/display/gimpdisplayshell.[ch] * app/display/gimpnavigationview.c * app/file/file-save.c * app/gui/device-status-dialog.c * app/gui/dialogs-constructors.c * app/gui/file-commands.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/file-save-dialog.c * app/gui/gui.c * app/gui/menus.c * app/gui/paths-dialog.c * app/gui/resize-dialog.c * app/gui/session.c * app/gui/test-commands.c * app/gui/tips-dialog.c * app/gui/tips-dialog.h * app/gui/user-install-dialog.c * app/gui/view-commands.c * app/paint/gimppaintcore.c * app/plug-in/plug-in.c * app/plug-in/plug-ins.c * app/tools/gimpbezierselecttool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpcolorpickertool.c * app/tools/gimpcroptool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpfuzzyselecttool.c * app/tools/gimpinktool.c * app/tools/gimpmagnifytool.c * app/tools/gimpmeasuretool.c * app/tools/gimppainttool.c * app/tools/gimppathtool.c * app/tools/gimptexttool.[ch] * app/tools/selection_options.c * app/tools/tools.c * app/tools/transform_options.c * app/widgets/gimphelp.c * app/widgets/gimpitemfactory.c * app/widgets/gimpselectioneditor.c * app/xcf/xcf-load.c * tools/pdbgen/pdb/fileops.pdb * tools/pdbgen/pdb/gimprc.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/transform_tools.pdb: use the new config system instead of the old gimprc stuff. * etc/gimprc.in * etc/gimprc_user.in: adapted to the new gimprc format. Will update the man-page later... * app/pdb/fileops_cmds.c * app/pdb/gimprc_cmds.c * app/pdb/image_cmds.c * app/pdb/layer_cmds.c * app/pdb/transform_tools_cmds.c * libgimp/gimpgimprc_pdb.c: regenerated.
2002-11-19 04:50:31 +08:00
void
gimp_rc_save (GimpRc *rc)
{
GimpRc *global;
const gchar *top =
"# GIMP gimprc\n"
"#\n"
"# This is your personal gimprc file. Any variable defined in this file\n"
"# takes precedence over the value defined in the system-wide gimprc:\n"
"# ";
const gchar *bottom =
"\n"
"# Most values can be set within The GIMP by changing some options in\n"
"# the Preferences dialog.\n";
const gchar *footer =
"# end of gimprc\n";
gchar *header;
GError *error = NULL;
g_return_if_fail (GIMP_IS_RC (rc));
global = g_object_new (GIMP_TYPE_RC, NULL);
gimp_config_deserialize (G_OBJECT (global), rc->system_gimprc, NULL, NULL);
header = g_strconcat (top, rc->system_gimprc, bottom, NULL);
if (rc->verbose)
g_print (_("Saving '%s'\n"), rc->user_gimprc);
if (! gimp_config_serialize (G_OBJECT (rc),
rc->user_gimprc, header, footer, global,
&error))
{
g_message (error->message);
g_error_free (error);
}
g_free (header);
g_object_unref (global);
}