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.
This commit is contained in:
Michael Natterer
2002-11-25 13:48:24 +00:00
committed by Michael Natterer
parent 91f2f3b10d
commit 1229d8c84c
15 changed files with 512 additions and 530 deletions

View File

@ -1,3 +1,29 @@
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

View File

@ -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);
guint32 int1, int2;
if (intensity1 < intensity2)
return -1;
else
return intensity1 > intensity2;
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;
}
}

View File

@ -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, };
GParamSpec *prop_spec;
GValue new_value = { 0, };
prop_spec = property_specs[i];
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;
}

View File

@ -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 *

View File

@ -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);

View File

@ -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 },

View File

@ -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))
diff = gimp_config_diff (G_OBJECT (gimp->config), config_orig,
GIMP_PARAM_SERIALIZE);
g_object_freeze_notify (G_OBJECT (gimp->config));
for (list = diff; list; list = g_list_next (list))
{
GParamSpec **param_specs;
guint n_param_specs;
gint i;
GParamSpec *param_spec;
GValue value = { 0, };
param_specs =
g_object_class_list_properties (G_OBJECT_GET_CLASS (config_orig),
&n_param_specs);
param_spec = (GParamSpec *) list->data;
g_object_freeze_notify (G_OBJECT (gimp->config));
g_value_init (&value, param_spec->value_type);
for (i = 0; i < n_param_specs; i++)
{
GValue global_value = { 0, };
GValue orig_value = { 0, };
g_object_get_property (config_orig,
param_spec->name,
&value);
g_object_set_property (G_OBJECT (gimp->config),
param_spec->name,
&value);
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);
}
g_object_thaw_notify (G_OBJECT (gimp->config));
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_specs;
guint n_param_specs;
GList *restart_list = NULL;
GList *confirm_list = NULL;
gint i;
GParamSpec *param_spec;
GValue value = { 0, };
param_specs =
g_object_class_list_properties (G_OBJECT_GET_CLASS (config_copy),
&n_param_specs);
param_spec = (GParamSpec *) list->data;
for (i = 0; i < n_param_specs; i++)
{
GValue global_value = { 0, };
GValue copy_value = { 0, };
g_value_init (&value, param_spec->value_type);
g_value_init (&global_value, param_specs[i]->value_type);
g_value_init (&copy_value, param_specs[i]->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_object_get_property (G_OBJECT (gimp->config),
param_specs[i]->name,
&global_value);
g_object_get_property (config_copy,
param_specs[i]->name,
&copy_value);
if (g_param_values_cmp (param_specs[i],
&global_value, &copy_value))
{
if (param_specs[i]->flags & GIMP_PARAM_RESTART)
{
restart_list = g_list_prepend (restart_list,
param_specs[i]);
}
else if (param_specs[i]->flags & GIMP_PARAM_CONFIRM)
{
confirm_list = g_list_prepend (confirm_list,
param_specs[i]);
}
}
g_value_unset (&global_value);
g_value_unset (&copy_value);
}
if (restart_list && confirm_list)
{
g_message ("You have changed %d values which need restart\n"
"and %d values which need confirmation.",
g_list_length (restart_list),
g_list_length (confirm_list));
}
else if (restart_list)
{
g_message ("You have changed %d values which need restart.",
g_list_length (restart_list));
}
else if (confirm_list)
{
g_message ("You have changed %d values which need confirmation.",
g_list_length (confirm_list));
}
g_list_free (restart_list);
g_list_free (confirm_list);
g_free (param_specs);
}
g_value_unset (&value);
}
g_object_unref (config_orig);
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_spec;
param_spec = (GParamSpec *) list->data;
g_string_append_printf (string, "%s\n", param_spec->name);
}
g_message (string->str);
g_string_free (string, TRUE);
}
g_list_free (confirm_diff);
g_list_free (restart_diff);
gimp_rc_save (GIMP_RC (config_copy));
g_object_unref (config_copy);
}

View File

@ -646,7 +646,6 @@ gimp_display_shell_new (GimpDisplay *gdisp,
{
static GtkItemFactoryEntry menu_items[] =
{
{ "/---", NULL, NULL, 0, "<Separator>"},
{ N_("/From Theme"), NULL,
gimp_display_shell_color_button_menu_callback,
GIMP_DISPLAY_PADDING_MODE_DEFAULT, NULL },
@ -656,6 +655,7 @@ gimp_display_shell_new (GimpDisplay *gdisp,
{ N_("/Dark Check Color"), NULL,
gimp_display_shell_color_button_menu_callback,
GIMP_DISPLAY_PADDING_MODE_DARK_CHECK, NULL },
{ "/---", NULL, NULL, 0, "<Separator>"},
{ N_("/Select Custom Color..."), NULL,
gimp_display_shell_color_button_menu_callback,
GIMP_DISPLAY_PADDING_MODE_CUSTOM, NULL },

View File

@ -302,7 +302,8 @@ static void
gimp_display_shell_resolution_changed_handler (GimpImage *gimage,
GimpDisplayShell *shell)
{
gimp_display_shell_scale_setup (shell);
if (! shell->dot_for_dot)
gimp_display_shell_scale_setup (shell);
gimp_statusbar_resize_cursor (GIMP_STATUSBAR (shell->statusbar));
}
@ -311,6 +312,7 @@ static void
gimp_display_shell_unit_changed_handler (GimpImage *gimage,
GimpDisplayShell *shell)
{
if (! shell->dot_for_dot)
gimp_display_shell_scale_setup (shell);
gimp_statusbar_resize_cursor (GIMP_STATUSBAR (shell->statusbar));
@ -419,9 +421,10 @@ gimp_display_shell_monitor_res_notify_handler (GObject *config,
shell->monitor_xres = GIMP_DISPLAY_CONFIG (config)->monitor_xres;
shell->monitor_yres = GIMP_DISPLAY_CONFIG (config)->monitor_yres;
#ifdef __GNUC__
#warning FIXME: update displays on monitor resolution change
#endif
if (! shell->dot_for_dot)
gimp_display_shell_scale_setup (shell);
gimp_statusbar_resize_cursor (GIMP_STATUSBAR (shell->statusbar));
}
static void

View File

@ -646,7 +646,6 @@ gimp_display_shell_new (GimpDisplay *gdisp,
{
static GtkItemFactoryEntry menu_items[] =
{
{ "/---", NULL, NULL, 0, "<Separator>"},
{ N_("/From Theme"), NULL,
gimp_display_shell_color_button_menu_callback,
GIMP_DISPLAY_PADDING_MODE_DEFAULT, NULL },
@ -656,6 +655,7 @@ gimp_display_shell_new (GimpDisplay *gdisp,
{ N_("/Dark Check Color"), NULL,
gimp_display_shell_color_button_menu_callback,
GIMP_DISPLAY_PADDING_MODE_DARK_CHECK, NULL },
{ "/---", NULL, NULL, 0, "<Separator>"},
{ N_("/Select Custom Color..."), NULL,
gimp_display_shell_color_button_menu_callback,
GIMP_DISPLAY_PADDING_MODE_CUSTOM, NULL },

View File

@ -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 },

View File

@ -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))
diff = gimp_config_diff (G_OBJECT (gimp->config), config_orig,
GIMP_PARAM_SERIALIZE);
g_object_freeze_notify (G_OBJECT (gimp->config));
for (list = diff; list; list = g_list_next (list))
{
GParamSpec **param_specs;
guint n_param_specs;
gint i;
GParamSpec *param_spec;
GValue value = { 0, };
param_specs =
g_object_class_list_properties (G_OBJECT_GET_CLASS (config_orig),
&n_param_specs);
param_spec = (GParamSpec *) list->data;
g_object_freeze_notify (G_OBJECT (gimp->config));
g_value_init (&value, param_spec->value_type);
for (i = 0; i < n_param_specs; i++)
{
GValue global_value = { 0, };
GValue orig_value = { 0, };
g_object_get_property (config_orig,
param_spec->name,
&value);
g_object_set_property (G_OBJECT (gimp->config),
param_spec->name,
&value);
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);
}
g_object_thaw_notify (G_OBJECT (gimp->config));
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_specs;
guint n_param_specs;
GList *restart_list = NULL;
GList *confirm_list = NULL;
gint i;
GParamSpec *param_spec;
GValue value = { 0, };
param_specs =
g_object_class_list_properties (G_OBJECT_GET_CLASS (config_copy),
&n_param_specs);
param_spec = (GParamSpec *) list->data;
for (i = 0; i < n_param_specs; i++)
{
GValue global_value = { 0, };
GValue copy_value = { 0, };
g_value_init (&value, param_spec->value_type);
g_value_init (&global_value, param_specs[i]->value_type);
g_value_init (&copy_value, param_specs[i]->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_object_get_property (G_OBJECT (gimp->config),
param_specs[i]->name,
&global_value);
g_object_get_property (config_copy,
param_specs[i]->name,
&copy_value);
if (g_param_values_cmp (param_specs[i],
&global_value, &copy_value))
{
if (param_specs[i]->flags & GIMP_PARAM_RESTART)
{
restart_list = g_list_prepend (restart_list,
param_specs[i]);
}
else if (param_specs[i]->flags & GIMP_PARAM_CONFIRM)
{
confirm_list = g_list_prepend (confirm_list,
param_specs[i]);
}
}
g_value_unset (&global_value);
g_value_unset (&copy_value);
}
if (restart_list && confirm_list)
{
g_message ("You have changed %d values which need restart\n"
"and %d values which need confirmation.",
g_list_length (restart_list),
g_list_length (confirm_list));
}
else if (restart_list)
{
g_message ("You have changed %d values which need restart.",
g_list_length (restart_list));
}
else if (confirm_list)
{
g_message ("You have changed %d values which need confirmation.",
g_list_length (confirm_list));
}
g_list_free (restart_list);
g_list_free (confirm_list);
g_free (param_specs);
}
g_value_unset (&value);
}
g_object_unref (config_orig);
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_spec;
param_spec = (GParamSpec *) list->data;
g_string_append_printf (string, "%s\n", param_spec->name);
}
g_message (string->str);
g_string_free (string, TRUE);
}
g_list_free (confirm_diff);
g_list_free (restart_diff);
gimp_rc_save (GIMP_RC (config_copy));
g_object_unref (config_copy);
}

View File

@ -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, };
GParamSpec *prop_spec;
GValue new_value = { 0, };
prop_spec = property_specs[i];
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;
}

View File

@ -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 *

View File

@ -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);