diff --git a/src/App/Document.cpp b/src/App/Document.cpp index bfe0493b41..2440a03452 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -3853,19 +3853,19 @@ bool Document::recomputeFeature(DocumentObject* Feat, bool recursive) DocumentObject * Document::addObject(const char* sType, const char* pObjectName, bool isNew, const char* viewType, bool isPartial) { - Base::BaseClass* base = static_cast(Base::Type::createInstanceByName(sType,true)); - - string ObjectName; - if (!base) - return 0; - if (!base->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { - delete base; + Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); + if (type.isBad()) { std::stringstream str; str << "'" << sType << "' is not a document object type"; throw Base::TypeError(str.str()); } - App::DocumentObject* pcObject = static_cast(base); + void* typeInstance = type.createInstance(); + if (!typeInstance) + return nullptr; + + App::DocumentObject* pcObject = static_cast(typeInstance); + pcObject->setDocument(this); // do no transactions if we do a rollback! @@ -3877,6 +3877,8 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, } // get Unique name + string ObjectName; + if (pObjectName && pObjectName[0] != '\0') ObjectName = getUniqueObjectName(pObjectName); else @@ -3933,9 +3935,8 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, std::vector Document::addObjects(const char* sType, const std::vector& objectNames, bool isNew) { - Base::Type::importModule(sType); - Base::Type type = Base::Type::fromName(sType); - if (!type.isDerivedFrom(App::DocumentObject::getClassTypeId())) { + Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); + if (type.isBad()) { std::stringstream str; str << "'" << sType << "' is not a document object type"; throw Base::TypeError(str.str()); @@ -3945,6 +3946,11 @@ std::vector Document::addObjects(const char* sType, const std: objects.resize(objectNames.size()); std::generate(objects.begin(), objects.end(), [&]{ return static_cast(type.createInstance()); }); + // the type instance could be a null pointer, it is enough to check the first element + if (!objects.empty() && !objects[0]) { + objects.clear(); + return objects; + } // get all existing object names std::vector reservedNames; diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp index 0896d182b1..3aef36a07b 100644 --- a/src/App/DocumentPyImp.cpp +++ b/src/App/DocumentPyImp.cpp @@ -218,77 +218,73 @@ PyObject* DocumentPy::addObject(PyObject *args, PyObject *kwd) kwlist, &sType,&sName,&obj,&view,&attach,&sViewType)) return NULL; - DocumentObject *pcFtr = 0; + DocumentObject *pcFtr = nullptr; if (!obj || !PyObject_IsTrue(attach)) { pcFtr = getDocumentPtr()->addObject(sType,sName,true,sViewType); } else { - Base::BaseClass* base = static_cast(Base::Type::createInstanceByName(sType,true)); - if (base) { - if (!base->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { - delete base; - std::stringstream str; - str << "'" << sType << "' is not a document object type"; - throw Base::TypeError(str.str()); - } - pcFtr = static_cast(base); + Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, DocumentObject::getClassTypeId(), true); + if (type.isBad()) { + std::stringstream str; + str << "'" << sType << "' is not a document object type"; + throw Base::TypeError(str.str()); } + pcFtr = static_cast(type.createInstance()); } - if (pcFtr) { - // Allows to hide the handling with Proxy in client python code - if (obj) { - try { - // the python binding class to the document object - Py::Object pyftr = Py::asObject(pcFtr->getPyObject()); - // 'pyobj' is the python class with the implementation for DocumentObject - Py::Object pyobj(obj); - if (pyobj.hasAttr("__object__")) { - pyobj.setAttr("__object__", pyftr); - } - pyftr.setAttr("Proxy", pyobj); - - if (PyObject_IsTrue(attach)) { - getDocumentPtr()->addObject(pcFtr,sName); - - try { - Py::Callable method(pyobj.getAttr("attach")); - if (!method.isNone()) { - Py::TupleN arg(pyftr); - method.apply(arg); - } - } - catch (Py::Exception&) { - Base::PyException e; - e.ReportException(); - } - } - - // if a document class is set we also need a view provider defined which must be - // something different to None - Py::Object pyvp; - if (view) - pyvp = Py::Object(view); - if (pyvp.isNone()) - pyvp = Py::Int(1); - // 'pyvp' is the python class with the implementation for ViewProvider - if (pyvp.hasAttr("__vobject__")) { - pyvp.setAttr("__vobject__", pyftr.getAttr("ViewObject")); - } - pyftr.getAttr("ViewObject").setAttr("Proxy", pyvp); - return Py::new_reference_to(pyftr); - } - catch (Py::Exception& e) { - e.clear(); - } - } - return pcFtr->getPyObject(); - } - else { + // the type instance could be a null pointer + if (!pcFtr) { std::stringstream str; str << "No document object found of type '" << sType << "'" << std::ends; throw Py::Exception(Base::BaseExceptionFreeCADError,str.str()); } + // Allows to hide the handling with Proxy in client python code + if (obj) { + try { + // the python binding class to the document object + Py::Object pyftr = Py::asObject(pcFtr->getPyObject()); + // 'pyobj' is the python class with the implementation for DocumentObject + Py::Object pyobj(obj); + if (pyobj.hasAttr("__object__")) { + pyobj.setAttr("__object__", pyftr); + } + pyftr.setAttr("Proxy", pyobj); + + if (PyObject_IsTrue(attach)) { + getDocumentPtr()->addObject(pcFtr,sName); + + try { + Py::Callable method(pyobj.getAttr("attach")); + if (!method.isNone()) { + Py::TupleN arg(pyftr); + method.apply(arg); + } + } + catch (Py::Exception&) { + Base::PyException e; + e.ReportException(); + } + } + + // if a document class is set we also need a view provider defined which must be + // something different to None + Py::Object pyvp; + if (view) + pyvp = Py::Object(view); + if (pyvp.isNone()) + pyvp = Py::Int(1); + // 'pyvp' is the python class with the implementation for ViewProvider + if (pyvp.hasAttr("__vobject__")) { + pyvp.setAttr("__vobject__", pyftr.getAttr("ViewObject")); + } + pyftr.getAttr("ViewObject").setAttr("Proxy", pyvp); + return Py::new_reference_to(pyftr); + } + catch (Py::Exception& e) { + e.clear(); + } + } + return pcFtr->getPyObject(); } PyObject* DocumentPy::removeObject(PyObject *args) @@ -611,15 +607,11 @@ PyObject* DocumentPy::findObjects(PyObject *args, PyObject *kwds) kwlist, &sType, &sName, &sLabel)) return nullptr; - Base::Type type = Base::Type::fromName(sType); - if (type == Base::Type::badType()) { - PyErr_Format(PyExc_TypeError, "'%s' is not a valid type", sType); - return nullptr; - } - - if (!type.isDerivedFrom(App::DocumentObject::getClassTypeId())) { - PyErr_Format(PyExc_TypeError, "Type '%s' does not inherit from 'App::DocumentObject'", sType); - return nullptr; + Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); + if (type.isBad()) { + std::stringstream str; + str << "'" << sType << "' is not a document object type"; + throw Base::TypeError(str.str()); } std::vector res; diff --git a/src/App/DynamicProperty.cpp b/src/App/DynamicProperty.cpp index a5c83b3e80..c7d8fe359a 100644 --- a/src/App/DynamicProperty.cpp +++ b/src/App/DynamicProperty.cpp @@ -181,25 +181,29 @@ Property* DynamicProperty::addDynamicProperty(PropertyContainer &pc, const char* if(Base::Tools::getIdentifier(name) != name) FC_THROWM(Base::NameError, "Invalid property name '" << name << "'"); - Base::BaseClass* base = static_cast(Base::Type::createInstanceByName(type,true)); - if (!base) - FC_THROWM(Base::RuntimeError, "Failed to create property " - << pc.getFullName() << '.' << name << " of type " << type); - if (!base->getTypeId().isDerivedFrom(Property::getClassTypeId())) { - delete base; - FC_THROWM(Base::ValueError, "Invalid type " << type << " for property " << pc.getFullName() << '.' << name); + Base::Type propType = Base::Type::getTypeIfDerivedFrom(type, App::Property::getClassTypeId(), true); + if (propType.isBad()) { + FC_THROWM(Base::ValueError, "Invalid type " + << type << " for property " << pc.getFullName() << '.' << name); } - // get unique name - Property* pcProperty = static_cast(base); + void* propInstance = propType.createInstance(); + if (!propInstance) { + FC_THROWM(Base::RuntimeError, "Failed to create property " + << pc.getFullName() << '.' << name << " of type " << type); + } + + Property* pcProperty = static_cast(propInstance); auto res = props.get<0>().emplace(pcProperty,name, nullptr, group, doc, attr, ro, hidden); pcProperty->setContainer(&pc); pcProperty->myName = res.first->name.c_str(); - if(ro) attr |= Prop_ReadOnly; - if(hidden) attr |= Prop_Hidden; + if(ro) + attr |= Prop_ReadOnly; + if(hidden) + attr |= Prop_Hidden; pcProperty->syncType(attr); pcProperty->StatusBits.set((size_t)Property::PropDynamic);