Bug 731279 - Tool Preset Editor not working correctly

This fixes restoring of brush properties (size, spacing angle etc.)
from presets, which was utterly broken before. The fix consists of
two parts:

- In tool_manager_preset_changed(), always copy the brush properties
  again after setting the preview on the tool options, in order to
  override brush properites that get copied from a linked brush when
  that brush gets set on the tool options.

But no amount of copying stuff again and again would help without:

- In gimp_context_set_by_type(), don't use g_object_set() to set the
  object (brush, pattern etc.). Instead, build a GValue and call
  gimp_context_set_property(). This may seem odd, but avoids a
  g_object_freeze_notify()/thaw_notify() around the g_object_set(),
  which was causing "notify" to be emitted at the very end, after
  everything this context change has triggered. GimpContext is an
  essential core object and there is an expectation of a reasonable
  order of signal emissions and callbacks being called. The "notify"
  at the end was keeping any callbacks of the context's "foo-changed"
  signals to override anything an earlier callback had done, if a
  "notify" callback was overriding that overriding again.

This was probably the reason for a lot of odd behavior observed over
the years. In fact, I have been searching for this for at least 5
years.
This commit is contained in:
Michael Natterer 2016-10-12 20:12:08 +02:00
parent cecdbb7713
commit d1e3d7c5c7
2 changed files with 33 additions and 14 deletions

View File

@ -1940,7 +1940,9 @@ gimp_context_set_by_type (GimpContext *context,
GType type, GType type,
GimpObject *object) GimpObject *object)
{ {
GimpContextPropType prop; GimpContextPropType prop;
GParamSpec *pspec;
GValue value = G_VALUE_INIT;
g_return_if_fail (GIMP_IS_CONTEXT (context)); g_return_if_fail (GIMP_IS_CONTEXT (context));
@ -1948,9 +1950,26 @@ gimp_context_set_by_type (GimpContext *context,
g_return_if_fail (prop != -1); g_return_if_fail (prop != -1);
g_object_set (context, pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (context),
gimp_context_prop_names[prop], object, gimp_context_prop_names[prop]);
NULL);
g_return_if_fail (pspec != NULL);
g_value_init (&value, pspec->value_type);
g_value_set_object (&value, object);
/* we use gimp_context_set_property() (which in turn only calls
* gimp_context_set_foo() functions) instead of the much more obvious
* g_object_set(); this avoids g_object_freeze_notify()/thaw_notify()
* around the g_object_set() and makes GimpContext callbacks being
* called in a much more predictable order. See bug #731279.
*/
gimp_context_set_property (G_OBJECT (context),
pspec->param_id,
(const GValue *) &value,
pspec);
g_value_unset (&value);
} }
void void

View File

@ -115,7 +115,7 @@ tool_manager_init (Gimp *gimp)
tool_manager->shared_paint_options = g_object_new (GIMP_TYPE_PAINT_OPTIONS, tool_manager->shared_paint_options = g_object_new (GIMP_TYPE_PAINT_OPTIONS,
"gimp", gimp, "gimp", gimp,
"name", "tmp", "name", "tool-manager-shared-paint-options",
NULL); NULL);
g_signal_connect (user_context, "tool-changed", g_signal_connect (user_context, "tool-changed",
@ -756,23 +756,23 @@ tool_manager_preset_changed (GimpContext *user_context,
if (GIMP_IS_PAINT_OPTIONS (preset->tool_options)) if (GIMP_IS_PAINT_OPTIONS (preset->tool_options))
{ {
GimpCoreConfig *config = user_context->gimp->config; GimpToolOptions *src = preset->tool_options;
GimpToolOptions *src = preset->tool_options; GimpToolOptions *dest = tool_manager->active_tool->tool_info->tool_options;
GimpToolOptions *dest = tool_manager->active_tool->tool_info->tool_options;
/* if connect_options() did overwrite the brush options and the /* copy various data objects' additional tool options again
* preset contains a brush, use the brush options from the * manually, they might have been overwritten by e.g. the "link
* preset * brush stuff to brush defaults" logic in
* gimptooloptions-gui.c
*/ */
if (config->global_brush && preset->use_brush) if (preset->use_brush)
gimp_paint_options_copy_brush_props (GIMP_PAINT_OPTIONS (src), gimp_paint_options_copy_brush_props (GIMP_PAINT_OPTIONS (src),
GIMP_PAINT_OPTIONS (dest)); GIMP_PAINT_OPTIONS (dest));
if (config->global_dynamics && preset->use_dynamics) if (preset->use_dynamics)
gimp_paint_options_copy_dynamics_props (GIMP_PAINT_OPTIONS (src), gimp_paint_options_copy_dynamics_props (GIMP_PAINT_OPTIONS (src),
GIMP_PAINT_OPTIONS (dest)); GIMP_PAINT_OPTIONS (dest));
if (config->global_gradient && preset->use_gradient) if (preset->use_gradient)
gimp_paint_options_copy_gradient_props (GIMP_PAINT_OPTIONS (src), gimp_paint_options_copy_gradient_props (GIMP_PAINT_OPTIONS (src),
GIMP_PAINT_OPTIONS (dest)); GIMP_PAINT_OPTIONS (dest));
} }