diff --git a/src/App/Property.cpp b/src/App/Property.cpp index 8c0efdbaf3..4bbd65928a 100644 --- a/src/App/Property.cpp +++ b/src/App/Property.cpp @@ -247,10 +247,22 @@ void Property::destroy(Property* p) } } +bool Property::enableNotify(bool on) +{ + bool isNotify = isNotifyEnabled(); + on ? StatusBits.reset(DisableNotify) : StatusBits.set(DisableNotify); + return isNotify; +} + +bool Property::isNotifyEnabled() const +{ + return !StatusBits.test(DisableNotify); +} + void Property::touch() { PropertyCleaner guard(this); - if (father) { + if (father && isNotifyEnabled()) { father->onEarlyChange(this); father->onChanged(this); } @@ -266,7 +278,9 @@ void Property::hasSetValue() { PropertyCleaner guard(this); if (father) { - father->onChanged(this); + if (isNotifyEnabled()) { + father->onChanged(this); + } if (!testStatus(Busy)) { Base::BitsetLocker guard(StatusBits, Busy); signalChanged(*this); diff --git a/src/App/Property.h b/src/App/Property.h index 02dc8b9de9..3e8d8e45aa 100644 --- a/src/App/Property.h +++ b/src/App/Property.h @@ -70,44 +70,27 @@ public: */ enum Status { - /// Whether a property is touched. - Touched = 0, - /// Whether a property can be modified. - Immutable = 1, - /// Whether a property is read-only for the property editor. - ReadOnly = 2, - /// Whether the property is hidden in the property editor. - Hidden = 3, - /// Whether a property is saved in the document. - Transient = 4, - /// To turn ON PropertyMaterial edit. - MaterialEdit = 5, - /// To turn OFF PropertyMaterialList edit. - NoMaterialListEdit = 6, - /// Whether a property is an output property. - Output = 7, - /// Whether a dynamic property can be removed. - LockDynamic = 8, - /// Prevents causing `Gui::Document::setModified()`. - NoModify = 9, - /// Whether to allow change in a partial document. - PartialTrigger = 10, - /// Whether to prevent to touch the owner for a recompute on property change. - NoRecompute = 11, - /// Whether a floating point number should be saved as single precision. - Single = 12, - /// For PropertyLists, whether the order of the elements is - /// relevant for the container using it. - Ordered = 13, - /// In case of expression binding, whether the expression on - /// restore and touch the object on value change. - EvalOnRestore = 14, - /// For internal use to avoid recursive signaling. - Busy = 15, - /// Whether the linked object should be copied on change of the property. - CopyOnChange = 16, - /// Whether the property editor should create a button for user defined editing. - UserEdit = 17, + Touched = 0, // touched property + Immutable = 1, // can't modify property + ReadOnly = 2, // for property editor + Hidden = 3, // for property editor + Transient = 4, // for property container save + MaterialEdit = 5, // to turn ON PropertyMaterial edit + NoMaterialListEdit = 6, // to turn OFF PropertyMaterialList edit + Output = 7, // same effect as Prop_Output + LockDynamic = 8, // prevent being removed from dynamic property + NoModify = 9, // prevent causing Gui::Document::setModified() + PartialTrigger = 10, // allow change in partial doc + NoRecompute = 11, // don't touch owner for recompute on property change + Single = 12, // for save/load of floating point numbers + Ordered = 13, // for PropertyLists whether the order of the elements is + // relevant for the container using it + EvalOnRestore = 14, // In case of expression binding, evaluate the + // expression on restore and touch the object on value change. + Busy = 15, // internal use to avoid recursive signaling + CopyOnChange = 16, // for Link to copy the linked object on change of the property with this flag + UserEdit = 17, // cause property editor to create button for user defined editing + DisableNotify = 18, // do not propagate changes of the property to its container // The following bits are corresponding to PropertyType set when the // property added. These types are meant to be static, and cannot be @@ -116,31 +99,19 @@ public: /// Mark the beginning of enum PropertyType bits. PropStaticBegin = 21, - /// Whether the property is dynamically added. - PropDynamic = 21, - /// Corresponds to Prop_NoPersist. - PropNoPersist = 22, - /// Corresponds to Prop_NoRecompute. - PropNoRecompute = 23, - /// Corresponds to Prop_ReadOnly. - PropReadOnly = 24, - /// Corresponds to Prop_Transient. - PropTransient = 25, - /// Corresponds to Prop_Hidden. - PropHidden = 26, - /// Corresponds to Prop_Output. - PropOutput = 27, - /// Mark the end of enum PropertyType bits. + PropDynamic = 21, // indicating the property is dynamically added + PropNoPersist = 22, // corresponding to Prop_NoPersist + PropNoRecompute = 23, // corresponding to Prop_NoRecompute + PropReadOnly = 24, // corresponding to Prop_ReadOnly + PropTransient = 25, // corresponding to Prop_Transient + PropHidden = 26, // corresponding to Prop_Hidden + PropOutput = 27, // corresponding to Prop_Output PropStaticEnd = 28, - /// User defined status bit. - User1 = 28, - /// User defined status bit. - User2 = 29, - /// User defined status bit. - User3 = 30, - /// User defined status bit. - User4 = 31 + User1 = 28, // user-defined status + User2 = 29, // user-defined status + User3 = 30, // user-defined status + User4 = 31 // user-defined status }; /// Construct a property. @@ -354,11 +325,16 @@ public: */ virtual void onContainerRestored() {} - /** @name Property status handling - * @{ + /** Property status handling */ - - /// Set the property touched. + //@{ + /// This method sets whether notification will be propagated on changing + /// the value of the property. The old value of the setting is returned. + bool enableNotify(bool on); + /// This method returns whether notification of changes to the property value + /// are propagated to the container. + bool isNotifyEnabled() const; + /// Set the property touched void touch(); /** diff --git a/src/Mod/PartDesign/Gui/ViewProviderBody.cpp b/src/Mod/PartDesign/Gui/ViewProviderBody.cpp index 993f8e8072..66b6c0b5f0 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderBody.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderBody.cpp @@ -263,10 +263,23 @@ void ViewProviderBody::onChanged(const App::Property* prop) { // #0002559: Body becomes visible upon changing DisplayModeBody Visibility.touch(); } - else + else { unifyVisualProperty(prop); + } + + // When changing transparency then adjust the ShapeAppearance inside onChanged() + // of the base class but don't notify its container again. This breaks the chain of + // notification and avoids the call of onChanged() with the ShapeAppearance as argument + // This fixes issue https://github.com/FreeCAD/FreeCAD/issues/18075 + if (prop == &Transparency) { + ShapeAppearance.enableNotify(false); + } PartGui::ViewProviderPartExt::onChanged(prop); + + if (prop == &Transparency) { + ShapeAppearance.enableNotify(true); + } }