From 789f11f6baa2fa80278147fd8fd8ccdbd1c64acb Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Wed, 4 Mar 2026 14:14:29 +0100 Subject: [PATCH] Gui: Prevent unhandled exception adding properties This commit prevents unhandled exceptions to be thrown in the Add Property dialog. When the user provides a valid name, for example 'Abc' and then an invalid name, for example 'Abc^', an exception is thrown that is caught by Qt's notify which may lead to a crash. This is caused by the fact that the editor is still bound to the old property that has been removed. The main idea was to preserve values that were provided by the user as long as possible, also when a property name changes. This design goal tried to preserve the user provided value even if the property name is not valid. Although the underlying property item is explicitly unbound in that situation, the editor is not. The solution is to also explicitly unbind the editor if there is an editor that can have bindings. Unbinding an editor does not automatically hide the f(x) symbol in the editor (leading to errors on unbound editors), so this commit also adds a bit of logic to hide the f(x) symbol when an editor is unbound. (cherry picked from commit a102c8a359514f013d835b17158db9a0eb78a623) --- src/Gui/Dialogs/DlgAddProperty.cpp | 3 +++ src/Gui/ExpressionBinding.cpp | 6 ++++++ src/Gui/ExpressionBinding.h | 3 ++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Gui/Dialogs/DlgAddProperty.cpp b/src/Gui/Dialogs/DlgAddProperty.cpp index dd1ec93f6b..0e0ecb7b0b 100644 --- a/src/Gui/Dialogs/DlgAddProperty.cpp +++ b/src/Gui/Dialogs/DlgAddProperty.cpp @@ -802,6 +802,9 @@ bool DlgAddProperty::clearBoundProperty() if (App::Property* prop = propertyItem->getFirstProperty()) { propertyItem->unbind(); + if (auto* eb = dynamic_cast(editor.get())) { + eb->unbind(); + } propertyItem->removeProperty(prop); container->removeDynamicProperty(prop->getName()); closeTransaction(TransactionOption::Abort); diff --git a/src/Gui/ExpressionBinding.cpp b/src/Gui/ExpressionBinding.cpp index 9799f16a70..5e04b45ef5 100644 --- a/src/Gui/ExpressionBinding.cpp +++ b/src/Gui/ExpressionBinding.cpp @@ -334,6 +334,12 @@ QPixmap ExpressionWidget::getIcon(const char* name, const QSize& size) const return icon; } +void ExpressionWidget::unbind() +{ + iconLabel->hide(); + ExpressionBinding::unbind(); +} + void ExpressionWidget::makeLabel(QLineEdit* le) { defaultPalette = le->palette(); diff --git a/src/Gui/ExpressionBinding.h b/src/Gui/ExpressionBinding.h index 1ab3be6762..ac3cebc8c1 100644 --- a/src/Gui/ExpressionBinding.h +++ b/src/Gui/ExpressionBinding.h @@ -50,7 +50,7 @@ public: virtual void bind(const App::ObjectIdentifier& _path); virtual void bind(const App::Property& prop); bool isBound() const; - void unbind(); + virtual void unbind(); virtual bool apply(const std::string& propName); virtual bool apply(); bool hasExpression() const; @@ -100,6 +100,7 @@ class GuiExport ExpressionWidget: public ExpressionBinding public: ExpressionWidget(); QPixmap getIcon(const char* name, const QSize& size) const; + void unbind() override; protected: void makeLabel(QLineEdit* parent);