From 2686f51c57bfd76198da9000b86a7c24d355a686 Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Mon, 29 May 2017 09:07:20 +0200 Subject: [PATCH] Checking for Document Restoring when extension has a null property ================================================================== The problem: OriginGroupExtension::OriginGroupExtension () { initExtensionType(OriginGroupExtension::getExtensionClassTypeId()); EXTENSION_ADD_PROPERTY_TYPE ( Origin, (0), 0, App::Prop_Hidden, "Origin linked to the group" ); } initializes the Origin property to null. Then Document::Restore => readObjects => addObject => slotNewObject => ViewProviderDocumentObject::updateView => ViewProviderBody::updateData => ViewProviderGeometryObject::updateData => ViewProviderDocumentObject::updateData => ViewProvider::updateData => ViewProviderOriginGroupExtension::extensionUpdateData => updateOriginSize() => OriginGroupExtension::getOrigin, the latter throws an exception because the origin property is null. Afterwards, the origin property is initialized during Document::Restore => readObjects => ExtensionContainer::Restore() => PropertyContainer::Restore() => App::PropertyLink::Restore() => App::PropertyLink::setValue() => Property::hasSetValue, which triggers an onChange: Body::onChanged => BodyBase::onChanged => Feature::onChanged => DocumentObject::onChanged => Document::onChangedProperty => Document::slotChangedObject => ViewProviderOriginGroupExtension::slotChangedObjectGui => ViewProviderOriginGroupExtension::updateOriginSize => OriginGroupExtension::getOrigin, now, the latter that is the same that was throwing the exception and generating the error message above, does not throw anymore because Origin has been initialized. When creating a new object, isNew==true; whereas when loading a file, isNew==false. Therefore, when loading a file setupObject is not executed. SetupObject, effectively initializes the extension via: Body::setupObject => DocumentObject::setupObject => OriginGroupExtension::onExtendedSetupObject. DocumentObject * Document::addObject(const char* sType, const char* pObjectName, bool isNew) { [more code here] // Call the object-specific initialization if (!d->undoing && !d->rollback && isNew) { pcObject->setupObject (); } [more code here] As DocumentObject code is generic for all objects (workbenches), by design it was chosen to initialize the object only if new. Therefore a object or an extension of a object being restored, between the addition (addObject) and the restoring of the properties, must by design expect it not to be initialized. The solution: Making use of the Restore flag at document level (the one at object level is not sufficient), no exception regarding the null property is reported during document restoring. Ticket: https://freecadweb.org/tracker/view.php?id=2530 fixes #2530 --- src/Gui/ViewProviderOriginGroupExtension.cpp | 4 +++- src/Mod/PartDesign/Gui/ViewProviderBody.cpp | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Gui/ViewProviderOriginGroupExtension.cpp b/src/Gui/ViewProviderOriginGroupExtension.cpp index 76a98a8994..5026463bc1 100644 --- a/src/Gui/ViewProviderOriginGroupExtension.cpp +++ b/src/Gui/ViewProviderOriginGroupExtension.cpp @@ -153,7 +153,9 @@ void ViewProviderOriginGroupExtension::updateOriginSize () { assert ( vp->isDerivedFrom ( Gui::ViewProviderOrigin::getClassTypeId () ) ); vpOrigin = static_cast ( vp ); } catch (const Base::Exception &ex) { - Base::Console().Error ("%s\n", ex.what() ); + // if is restoring it is normal that the origin property is null until after restored, so no need to report this. + if(!getExtendedViewProvider()->getDocument()->getDocument()->testStatus(App::Document::Restoring)) + Base::Console().Error ("%s\n", ex.what() ); return; } diff --git a/src/Mod/PartDesign/Gui/ViewProviderBody.cpp b/src/Mod/PartDesign/Gui/ViewProviderBody.cpp index 7d61851497..b8654d22e7 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderBody.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderBody.cpp @@ -398,7 +398,8 @@ void ViewProviderBody::updateOriginDatumSize () { assert ( vp->isDerivedFrom ( Gui::ViewProviderOrigin::getClassTypeId () ) ); vpOrigin = static_cast ( vp ); } catch (const Base::Exception &ex) { - Base::Console().Error ("%s\n", ex.what() ); + if(!getExtendedViewProvider()->getDocument()->getDocument()->testStatus(App::Document::Restoring)) + Base::Console().Error ("%s\n", ex.what() ); return; }