Commit 1229d8c8 authored by Michael Natterer's avatar Michael Natterer 😴 Committed by Michael Natterer
Browse files

added gimp_config_diff() which returns the difference beween two

2002-11-25  Michael Natterer  <mitch@gimp.org>

	* app/config/gimpconfig-utils.[ch]: added gimp_config_diff()
	which returns the difference beween two GimpConfig objects
	as a GList of GParamSpecs.

	* app/config/gimpconfig-params.c (gimp_param_color_cmp): compare
	the colors as integers to get rid of rounding foobar.

	* app/config/gimpconfig-serialize.c: use gimp_config_diff().

	* app/display/gimpdisplayshell-handlers.c: only need to call
	gimp_display_shell_scale_setup() on resolution change if the
	display is not in dot-for-dot mode.

	* app/display/gimpdisplayshell.c: changed a separator in the
	padding color menu.

	* app/gui/dialogs.c: made the prefs dialog a singleton again.

	* app/gui/preferences-dialog.c: Should be fully functional again:
	Apply GIMP_PARAM_CONFIRM properties on "OK". Save gimprc on "OK".
	Parse a temporaty GimpRc on dialog creation to get the current
	GIMP_PARAM_RESTART values. Use gimp_config_diff() for all config
	comparisons.
parent 91f2f3b1
2002-11-25 Michael Natterer <mitch@gimp.org>
* app/config/gimpconfig-utils.[ch]: added gimp_config_diff()
which returns the difference beween two GimpConfig objects
as a GList of GParamSpecs.
* app/config/gimpconfig-params.c (gimp_param_color_cmp): compare
the colors as integers to get rid of rounding foobar.
* app/config/gimpconfig-serialize.c: use gimp_config_diff().
* app/display/gimpdisplayshell-handlers.c: only need to call
gimp_display_shell_scale_setup() on resolution change if the
display is not in dot-for-dot mode.
* app/display/gimpdisplayshell.c: changed a separator in the
padding color menu.
* app/gui/dialogs.c: made the prefs dialog a singleton again.
* app/gui/preferences-dialog.c: Should be fully functional again:
Apply GIMP_PARAM_CONFIRM properties on "OK". Save gimprc on "OK".
Parse a temporaty GimpRc on dialog creation to get the current
GIMP_PARAM_RESTART values. Use gimp_config_diff() for all config
comparisons.
2002-11-25 Manish Singh <yosh@gimp.org>
 
* libgimpbase/gimpwire.c: using a union like that may not be
......
......@@ -147,13 +147,20 @@ gimp_param_color_values_cmp (GParamSpec *pspec,
return color1 != NULL;
else
{
gdouble intensity1 = gimp_rgb_intensity (color1);
gdouble intensity2 = gimp_rgb_intensity (color2);
if (intensity1 < intensity2)
return -1;
else
return intensity1 > intensity2;
guint32 int1, int2;
gimp_rgba_get_uchar (color1,
((guchar *) &int1) + 0,
((guchar *) &int1) + 1,
((guchar *) &int1) + 2,
((guchar *) &int1) + 3);
gimp_rgba_get_uchar (color2,
((guchar *) &int2) + 0,
((guchar *) &int2) + 1,
((guchar *) &int2) + 2,
((guchar *) &int2) + 3);
return int1 - int2;
}
}
......
......@@ -139,12 +139,11 @@ gimp_config_serialize_changed_properties (GObject *new,
gint fd,
gint indent_level)
{
GObjectClass *klass;
GParamSpec **property_specs;
guint n_property_specs;
guint i;
GString *str;
gboolean property_written = FALSE;
GObjectClass *klass;
GList *diff;
GList *list;
GString *str;
gboolean property_written = FALSE;
g_return_val_if_fail (G_IS_OBJECT (new), FALSE);
g_return_val_if_fail (G_IS_OBJECT (old), FALSE);
......@@ -153,64 +152,54 @@ gimp_config_serialize_changed_properties (GObject *new,
klass = G_OBJECT_GET_CLASS (new);
property_specs = g_object_class_list_properties (klass, &n_property_specs);
diff = gimp_config_diff (new, old, GIMP_PARAM_SERIALIZE);
if (!property_specs)
if (! diff)
return TRUE;
str = g_string_new (NULL);
for (i = 0; i < n_property_specs; i++)
for (list = diff; list; list = g_list_next (list))
{
GParamSpec *prop_spec;
GValue new_value = { 0, };
GValue old_value = { 0, };
prop_spec = property_specs[i];
GParamSpec *prop_spec;
GValue new_value = { 0, };
if (! (prop_spec->flags & GIMP_PARAM_SERIALIZE))
continue;
prop_spec = (GParamSpec *) list->data;
g_value_init (&new_value, prop_spec->value_type);
g_value_init (&old_value, prop_spec->value_type);
g_object_get_property (new, prop_spec->name, &new_value);
g_object_get_property (old, prop_spec->name, &old_value);
if (g_param_values_cmp (prop_spec, &new_value, &old_value) != 0)
{
if (property_written)
g_string_assign (str, "\n");
else
g_string_assign (str, "");
if (property_written)
g_string_assign (str, "\n");
else
g_string_assign (str, "");
gimp_config_string_indent (str, indent_level);
gimp_config_string_indent (str, indent_level);
g_string_append_printf (str, "(%s ", prop_spec->name);
g_string_append_printf (str, "(%s ", prop_spec->name);
if (gimp_config_serialize_value (&new_value, str, TRUE))
{
g_string_append (str, ")\n");
property_written = TRUE;
if (write (fd, str->str, str->len) == -1)
return FALSE;
}
else if (prop_spec->value_type != G_TYPE_STRING)
{
g_warning ("couldn't serialize property %s::%s of type %s",
g_type_name (G_TYPE_FROM_INSTANCE (new)),
prop_spec->name,
g_type_name (prop_spec->value_type));
}
if (gimp_config_serialize_value (&new_value, str, TRUE))
{
g_string_append (str, ")\n");
property_written = TRUE;
if (write (fd, str->str, str->len) == -1)
return FALSE;
}
else if (prop_spec->value_type != G_TYPE_STRING)
{
g_warning ("couldn't serialize property %s::%s of type %s",
g_type_name (G_TYPE_FROM_INSTANCE (new)),
prop_spec->name,
g_type_name (prop_spec->value_type));
}
g_value_unset (&new_value);
g_value_unset (&old_value);
}
g_free (property_specs);
g_string_free (str, TRUE);
g_list_free (diff);
return TRUE;
}
......
......@@ -30,6 +30,50 @@
#include "gimpconfig-utils.h"
GList *
gimp_config_diff (GObject *a,
GObject *b,
GParamFlags flags)
{
GParamSpec **param_specs;
guint n_param_specs;
gint i;
GList *list = NULL;
g_return_val_if_fail (G_IS_OBJECT (a), FALSE);
g_return_val_if_fail (G_IS_OBJECT (b), FALSE);
g_return_val_if_fail (G_TYPE_FROM_INSTANCE (a) == G_TYPE_FROM_INSTANCE (b),
FALSE);
param_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a),
&n_param_specs);
for (i = 0; i < n_param_specs; i++)
{
if (! flags || ((param_specs[i]->flags & flags) == flags))
{
GValue a_value = { 0, };
GValue b_value = { 0, };
g_value_init (&a_value, param_specs[i]->value_type);
g_value_init (&b_value, param_specs[i]->value_type);
g_object_get_property (a, param_specs[i]->name, &a_value);
g_object_get_property (b, param_specs[i]->name, &b_value);
if (g_param_values_cmp (param_specs[i], &a_value, &b_value))
list = g_list_prepend (list, param_specs[i]);
g_value_unset (&a_value);
g_value_unset (&b_value);
}
}
g_free (param_specs);
return g_list_reverse (list);
}
void
gimp_config_copy_properties (GObject *src,
GObject *dest)
......@@ -64,7 +108,11 @@ gimp_config_copy_properties (GObject *src,
g_object_get_property (src, prop_spec->name, &value);
g_object_set_property (dest, prop_spec->name, &value);
g_value_unset (&value);
}
g_free (property_specs);
}
gchar *
......
......@@ -23,6 +23,9 @@
#define __GIMP_CONFIG_UTILS_H__
GList * gimp_config_diff (GObject *a,
GObject *b,
GParamFlags flags);
void gimp_config_copy_properties (GObject *src,
GObject *dest);
......
......@@ -40,7 +40,7 @@ GimpDialogFactory *global_toolbox_factory = NULL;
static const GimpDialogFactoryEntry toplevel_entries[] =
{
{ "gimp-device-status-dialog", dialogs_device_status_get, 32, TRUE, TRUE, FALSE, TRUE },
{ "gimp-preferences-dialog", dialogs_preferences_get, 32, FALSE, FALSE, FALSE, TRUE },
{ "gimp-preferences-dialog", dialogs_preferences_get, 32, TRUE, FALSE, FALSE, TRUE },
{ "gimp-module-browser-dialog", dialogs_module_browser_get, 32, TRUE, FALSE, FALSE, TRUE },
{ "gimp-undo-history-dialog", dialogs_undo_history_get, 32, FALSE, FALSE, FALSE, TRUE },
{ "gimp-display-filters-dialog", dialogs_display_filters_get, 32, FALSE, FALSE, FALSE, TRUE },
......
......@@ -30,6 +30,7 @@
#include "config/gimpconfig.h"
#include "config/gimpconfig-params.h"
#include "config/gimpconfig-utils.h"
#include "config/gimprc.h"
#include "core/gimp.h"
......@@ -46,10 +47,7 @@
#include "libgimp/gimpintl.h"
/* gimprc will be parsed with a buffer size of 1024,
* so don't set this too large
*/
#define MAX_COMMENT_LENGTH 512
#define MAX_COMMENT_LENGTH 512 /* arbitrary */
/* preferences local functions */
......@@ -76,11 +74,82 @@ static void prefs_resolution_calibrate_callback (GtkWidget *widget,
static void prefs_input_dialog_able_callback (GtkWidget *widget,
GdkDevice *device,
gpointer data);
static void prefs_restart_notification (void);
/* public function */
GtkWidget *
preferences_dialog_create (Gimp *gimp)
{
GtkWidget *prefs_dialog;
GObject *config;
GObject *config_copy;
GObject *config_orig;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
config = G_OBJECT (gimp->config);
config_copy = gimp_config_duplicate (config);
config_orig = gimp_config_duplicate (config);
/* read the saved gimprc to get GIMP_PARAM_RESTART values */
{
GimpRc *gimprc;
GObject *config_saved;
GList *diff;
GList *list;
gimprc = gimp_rc_new (GIMP_RC (config)->system_gimprc,
GIMP_RC (config)->user_gimprc);
config_saved = G_OBJECT (gimprc);
diff = gimp_config_diff (config_saved, config_copy, GIMP_PARAM_RESTART);
for (list = diff; list; list = g_list_next (list))
{
GParamSpec *param_spec;
GValue value = { 0, };
param_spec = (GParamSpec *) list->data;
g_value_init (&value, param_spec->value_type);
g_object_get_property (config_saved, param_spec->name, &value);
g_object_set_property (config_copy, param_spec->name, &value);
g_value_unset (&value);
}
g_list_free (diff);
g_object_unref (gimprc);
}
g_signal_connect_object (config, "notify",
G_CALLBACK (prefs_config_notify),
config_copy, 0);
g_signal_connect_object (config_copy, "notify",
G_CALLBACK (prefs_config_copy_notify),
config, 0);
prefs_dialog = prefs_dialog_new (gimp, config_copy);
g_object_weak_ref (G_OBJECT (prefs_dialog),
(GWeakNotify) g_object_unref,
config_copy);
g_object_weak_ref (G_OBJECT (prefs_dialog),
(GWeakNotify) g_object_unref,
config_orig);
g_object_set_data (G_OBJECT (prefs_dialog), "gimp", gimp);
g_object_set_data (G_OBJECT (prefs_dialog), "config-copy", config_copy);
g_object_set_data (G_OBJECT (prefs_dialog), "config-orig", config_orig);
return prefs_dialog;
}
/* private functions */
static void
prefs_config_notify (GObject *config,
GParamSpec *param_spec,
......@@ -161,111 +230,14 @@ prefs_config_copy_notify (GObject *config_copy,
g_value_unset (&global_value);
}
GtkWidget *
preferences_dialog_create (Gimp *gimp)
{
GtkWidget *prefs_dialog;
GObject *config;
GObject *config_copy;
GObject *config_orig;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
config = G_OBJECT (gimp->config);
config_copy = gimp_config_duplicate (config);
config_orig = gimp_config_duplicate (config);
g_signal_connect_object (config, "notify",
G_CALLBACK (prefs_config_notify),
config_copy, 0);
g_signal_connect_object (config_copy, "notify",
G_CALLBACK (prefs_config_copy_notify),
config, 0);
prefs_dialog = prefs_dialog_new (gimp, config_copy);
g_object_weak_ref (G_OBJECT (prefs_dialog),
(GWeakNotify) g_object_unref,
config_copy);
g_object_weak_ref (G_OBJECT (prefs_dialog),
(GWeakNotify) g_object_unref,
config_orig);
g_object_set_data (G_OBJECT (prefs_dialog), "gimp", gimp);
g_object_set_data (G_OBJECT (prefs_dialog), "config-copy", config_copy);
g_object_set_data (G_OBJECT (prefs_dialog), "config-orig", config_orig);
return prefs_dialog;
}
/* private functions */
static void
prefs_restart_notification_save_callback (GtkWidget *widget,
gpointer data)
{
#if 0
prefs_save_callback (widget, prefs_dialog);
gtk_widget_destroy (GTK_WIDGET (data));
#endif
}
/* The user pressed OK and not Save, but has changed some settings that
* only take effect after he restarts the GIMP. Allow him to save the
* settings.
*/
static void
prefs_restart_notification (void)
{
GtkWidget *dialog;
GtkWidget *hbox;
GtkWidget *label;
dialog = gimp_dialog_new (_("Save Preferences ?"), "gimp_message",
gimp_standard_help_func,
"dialogs/preferences/preferences.html",
GTK_WIN_POS_MOUSE,
FALSE, FALSE, FALSE,
GTK_STOCK_CLOSE, gtk_widget_destroy,
NULL, 1, NULL, FALSE, TRUE,
GTK_STOCK_SAVE,
prefs_restart_notification_save_callback,
NULL, NULL, NULL, TRUE, FALSE,
NULL);
g_signal_connect (G_OBJECT (dialog), "destroy",
G_CALLBACK (gtk_main_quit),
NULL);
hbox = gtk_hbox_new (FALSE, 4);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, TRUE, FALSE, 4);
gtk_widget_show (hbox);
label = gtk_label_new (_("At least one of the changes you made will only\n"
"take effect after you restart the GIMP.\n\n"
"You may choose 'Save' now to make your changes\n"
"permanent, so you can restart GIMP or hit 'Close'\n"
"and the critical parts of your changes will not\n"
"be applied."));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, FALSE, 4);
gtk_widget_show (label);
gtk_widget_show (dialog);
gtk_main ();
}
static void
prefs_cancel_callback (GtkWidget *widget,
GtkWidget *dialog)
{
Gimp *gimp;
GObject *config_orig;
GList *diff;
GList *list;
gimp = g_object_get_data (G_OBJECT (dialog), "gimp");
config_orig = g_object_get_data (G_OBJECT (dialog), "config-orig");
......@@ -274,49 +246,34 @@ prefs_cancel_callback (GtkWidget *widget,
gtk_widget_destroy (dialog); /* destroys config_copy */
if (! gimp_config_is_equal_to (G_OBJECT (gimp->config), config_orig))
{
GParamSpec **param_specs;
guint n_param_specs;
gint i;
diff = gimp_config_diff (G_OBJECT (gimp->config), config_orig,
GIMP_PARAM_SERIALIZE);
param_specs =
g_object_class_list_properties (G_OBJECT_GET_CLASS (config_orig),
&n_param_specs);
g_object_freeze_notify (G_OBJECT (gimp->config));
g_object_freeze_notify (G_OBJECT (gimp->config));
for (list = diff; list; list = g_list_next (list))
{
GParamSpec *param_spec;
GValue value = { 0, };
for (i = 0; i < n_param_specs; i++)
{
GValue global_value = { 0, };
GValue orig_value = { 0, };
g_value_init (&global_value, param_specs[i]->value_type);
g_value_init (&orig_value, param_specs[i]->value_type);
g_object_get_property (G_OBJECT (gimp->config),
param_specs[i]->name,
&global_value);
g_object_get_property (config_orig,
param_specs[i]->name,
&orig_value);
if (g_param_values_cmp (param_specs[i], &global_value, &orig_value))
{
g_object_set_property (G_OBJECT (gimp->config),
param_specs[i]->name,
&orig_value);
}
g_value_unset (&global_value);
g_value_unset (&orig_value);
}
param_spec = (GParamSpec *) list->data;
g_value_init (&value, param_spec->value_type);
g_object_thaw_notify (G_OBJECT (gimp->config));
g_object_get_property (config_orig,
param_spec->name,
&value);
g_object_set_property (G_OBJECT (gimp->config),
param_spec->name,
&value);
g_free (param_specs);
g_value_unset (&value);
}
g_object_thaw_notify (G_OBJECT (gimp->config));
g_list_free (diff);
g_object_unref (config_orig);
}
......@@ -325,97 +282,73 @@ prefs_ok_callback (GtkWidget *widget,
GtkWidget *dialog)
{
Gimp *gimp;
GObject *config_orig;
GObject *config_copy;
GList *restart_diff;
GList *confirm_diff;
GList *list;
gimp = g_object_get_data (G_OBJECT (dialog), "gimp");
config_orig = g_object_get_data (G_OBJECT (dialog), "config-orig");
config_copy = g_object_get_data (G_OBJECT (dialog), "config-copy");
g_object_ref (config_orig);
g_object_ref (config_copy);
gtk_widget_destroy (dialog);
if (! gimp_config_is_equal_to (config_copy, config_orig))
restart_diff = gimp_config_diff (G_OBJECT (gimp->config), config_copy,
GIMP_PARAM_RESTART);
confirm_diff = gimp_config_diff (G_OBJECT (gimp->config), config_copy,
GIMP_PARAM_CONFIRM);
g_object_freeze_notify (G_OBJECT (gimp->config));
for (list = confirm_diff; list; list = g_list_next (list))
{
if (gimp_config_is_equal_to (G_OBJECT (gimp->config), config_copy))
{
g_message ("You have not changed any value that needs "
"restart or confirmation.");
}
else
GParamSpec *param_spec;
GValue value = { 0, };
param_spec = (GParamSpec *) list->data;
g_value_init (&value, param_spec->value_type);
g_object_get_property (config_copy,
param_spec->name,
&value);
g_object_set_property (G_OBJECT (gimp->config),
param_spec->name,
&value);
g_value_unset (&value);
}
g_object_thaw_notify (G_OBJECT (gimp->config));
if (restart_diff)
{
GString *string;
string = g_string_new (_("You will have to restart GIMP for\n"
"the following changes to take effect:"));
g_string_append (string, "\n\n");
for (list = restart_diff; list; list = g_list_next (list))
{
GParamSpec **param_specs;
guint n_param_specs;
GList *restart_list = NULL;
GList *confirm_list = NULL;
gint i;
param_specs =
g_object_class_list_properties (G_OBJECT_GET_CLASS (config_copy),
&n_param_specs);