From a8d0accdad9aa9ad6eb0cd6aa1d919cc2d2105a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Tr=C3=B6ger?= Date: Thu, 2 Jun 2016 06:29:05 +0200 Subject: [PATCH] Extensions: special calls for document object extensions --- src/App/Application.cpp | 2 +- src/App/CMakeLists.txt | 5 + src/App/DocumentObject.cpp | 43 ++- src/App/DocumentObject.cpp.orig | 416 +++++++++++++++++++++++ src/App/DocumentObject.h | 6 +- src/App/DocumentObjectExtension.cpp | 79 +++++ src/App/DocumentObjectExtension.h | 65 ++++ src/App/DocumentObjectExtensionPy.xml | 18 + src/App/DocumentObjectExtensionPyImp.cpp | 50 +++ src/App/DocumentObjectGroup.cpp | 8 +- src/App/DocumentObjectGroup.h | 4 +- src/App/Extension.cpp | 11 + src/App/Extension.h | 24 +- src/App/ExtensionContainerPyImp.cpp | 2 - src/App/ExtensionPy.xml | 2 +- src/App/OriginGroup.cpp | 27 +- src/App/OriginGroup.h | 8 +- 17 files changed, 732 insertions(+), 38 deletions(-) create mode 100644 src/App/DocumentObject.cpp.orig create mode 100644 src/App/DocumentObjectExtension.cpp create mode 100644 src/App/DocumentObjectExtension.h create mode 100644 src/App/DocumentObjectExtensionPy.xml create mode 100644 src/App/DocumentObjectExtensionPyImp.cpp diff --git a/src/App/Application.cpp b/src/App/Application.cpp index afcb866bb..5514d8031 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -1137,9 +1137,9 @@ void Application::initTypes(void) // Extension classes App ::Extension ::init(); + App ::DocumentObjectExtension ::init(); App ::GroupExtension ::init(); App ::GeoFeatureGroupExtension ::init(); - //App ::GeoFeatureGroupPython ::init(); App ::OriginGroupExtension ::init(); // Document classes diff --git a/src/App/CMakeLists.txt b/src/App/CMakeLists.txt index 30ce7369f..85f0125d1 100644 --- a/src/App/CMakeLists.txt +++ b/src/App/CMakeLists.txt @@ -55,6 +55,7 @@ generate_from_xml(DocumentPy) generate_from_xml(DocumentObjectPy) generate_from_xml(ExtensionPy) generate_from_xml(ExtensionContainerPy) +generate_from_xml(DocumentObjectExtensionPy) generate_from_xml(GroupExtensionPy) generate_from_xml(DocumentObjectGroupPy) generate_from_xml(GeoFeaturePy) @@ -72,6 +73,7 @@ generate_from_py(FreeCADTest TestScript.h) SET(FreeCADApp_XML_SRCS ExtensionPy.xml ExtensionContainerPy.xml + DocumentObjectExtensionPy.xml GroupExtensionPy.xml DocumentObjectGroupPy.xml DocumentObjectPy.xml @@ -93,6 +95,8 @@ SET(Document_CPP_SRCS DocumentObject.cpp Extension.cpp ExtensionPyImp.cpp + DocumentObjectExtension.cpp + DocumentObjectExtensionPyImp.cpp ExtensionContainerPyImp.cpp GroupExtensionPyImp.cpp DocumentObjectFileIncluded.cpp @@ -132,6 +136,7 @@ SET(Document_HPP_SRCS Document.h DocumentObject.h Extension.h + DocumentObjectExtension.h DocumentObjectFileIncluded.h DocumentObjectGroup.h DocumentObserver.h diff --git a/src/App/DocumentObject.cpp b/src/App/DocumentObject.cpp index fc61eaef7..7a0a70562 100644 --- a/src/App/DocumentObject.cpp +++ b/src/App/DocumentObject.cpp @@ -33,6 +33,7 @@ #include "DocumentObjectGroup.h" #include "PropertyLinks.h" #include "PropertyExpressionEngine.h" +#include "DocumentObjectExtension.h" #include #include #include @@ -92,12 +93,28 @@ App::DocumentObjectExecReturn *DocumentObject::recompute(void) DocumentObjectExecReturn *DocumentObject::execute(void) { + //call all extensions + auto vector = getExtensionsDerivedFromType(); + for(auto ext : vector) + if(ext->extensionMustExecute()) + ext->extensionExecute(); + return StdReturn; } short DocumentObject::mustExecute(void) const { - return (isTouched() ? 1 : 0); + if(isTouched()) + return 1; + + //ask all extensions + auto vector = getExtensionsDerivedFromType(); + for(auto ext : vector) + if(ext->extensionMustExecute()) + return 1; + + return 0; + } const char* DocumentObject::getStatusString(void) const @@ -370,3 +387,27 @@ void DocumentObject::connectRelabelSignals() onDeletedObjectConnection.disconnect(); } } + +void DocumentObject::onSettingDocument() { + + //call all extensions + auto vector = getExtensionsDerivedFromType(); + for(auto ext : vector) + ext->onExtendedSettingDocument(); +} + +void DocumentObject::setupObject() { + + //call all extensions + auto vector = getExtensionsDerivedFromType(); + for(auto ext : vector) + ext->onExtendedSetupObject(); +} + +void DocumentObject::unsetupObject() { + + //call all extensions + auto vector = getExtensionsDerivedFromType(); + for(auto ext : vector) + ext->onExtendedUnsetupObject(); +} diff --git a/src/App/DocumentObject.cpp.orig b/src/App/DocumentObject.cpp.orig new file mode 100644 index 000000000..c40e2db59 --- /dev/null +++ b/src/App/DocumentObject.cpp.orig @@ -0,0 +1,416 @@ +/*************************************************************************** + * Copyright (c) Jürgen Riegel (juergen.riegel@web.de) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include + +#include "Document.h" +#include "DocumentObject.h" +#include "DocumentObjectGroup.h" +#include "PropertyLinks.h" +#include "PropertyExpressionEngine.h" +<<<<<<< d634f3384aa4e6436c7df203435de3895700be84 +#include +======= +#include "DocumentObjectExtension.h" +>>>>>>> Special calls for document object extensions +#include +#include + +using namespace App; + + +PROPERTY_SOURCE(App::DocumentObject, App::TransactionalObject) + +DocumentObjectExecReturn *DocumentObject::StdReturn = 0; + +//=========================================================================== +// DocumentObject +//=========================================================================== + +DocumentObject::DocumentObject(void) + : ExpressionEngine(),_pDoc(0),pcNameInDocument(0) +{ + // define Label of type 'Output' to avoid being marked as touched after relabeling + ADD_PROPERTY_TYPE(Label,("Unnamed"),"Base",Prop_Output,"User name of the object (UTF8)"); + ADD_PROPERTY_TYPE(ExpressionEngine,(),"Base",Prop_Hidden,"Property expressions"); +} + +DocumentObject::~DocumentObject(void) +{ + if (!PythonObject.is(Py::_None())){ + // Remark: The API of Py::Object has been changed to set whether the wrapper owns the passed + // Python object or not. In the constructor we forced the wrapper to own the object so we need + // not to dec'ref the Python object any more. + // But we must still invalidate the Python object because it need not to be + // destructed right now because the interpreter can own several references to it. + Base::PyObjectBase* obj = (Base::PyObjectBase*)PythonObject.ptr(); + // Call before decrementing the reference counter, otherwise a heap error can occur + obj->setInvalid(); + } +} + +namespace App { +class ObjectExecution +{ +public: + ObjectExecution(DocumentObject* o) : obj(o) + { obj->StatusBits.set(3); } + ~ObjectExecution() + { obj->StatusBits.reset(3); } +private: + DocumentObject* obj; +}; +} + +App::DocumentObjectExecReturn *DocumentObject::recompute(void) +{ + // set/unset the execution bit + ObjectExecution exe(this); + return this->execute(); +} + +DocumentObjectExecReturn *DocumentObject::execute(void) +{ + //call all extensions + auto vector = getExtensionsDerivedFromType(); + for(auto ext : vector) + if(ext->extensionMustExecute()) + ext->extensionExecute(); + + return StdReturn; +} + +short DocumentObject::mustExecute(void) const +{ + if(isTouched()) + return 1; + + //ask all extensions + auto vector = getExtensionsDerivedFromType(); + for(auto ext : vector) + if(ext->extensionMustExecute()) + return 1; + + return 0; + +} + +const char* DocumentObject::getStatusString(void) const +{ + if (isError()) { + const char* text = getDocument()->getErrorDescription(this); + return text ? text : "Error"; + } + else if (isTouched()) + return "Touched"; + else + return "Valid"; +} + +const char *DocumentObject::getNameInDocument(void) const +{ + // Note: It can happen that we query the internal name of an object even if it is not + // part of a document (anymore). This is the case e.g. if we have a reference in Python + // to an object that has been removed from the document. In this case we should rather + // return 0. + //assert(pcNameInDocument); + if (!pcNameInDocument) return 0; + return pcNameInDocument->c_str(); +} + +bool DocumentObject::isAttachedToDocument() const +{ + return (pcNameInDocument != 0); +} + +const char* DocumentObject::detachFromDocument() +{ + const std::string* name = pcNameInDocument; + pcNameInDocument = 0; + return name ? name->c_str() : 0; +} + +std::vector DocumentObject::getOutList(void) const +{ + std::vector List; + std::vector ret; + getPropertyList(List); + for (std::vector::const_iterator It = List.begin();It != List.end(); ++It) { + if ((*It)->isDerivedFrom(PropertyLinkList::getClassTypeId())) { + const std::vector &OutList = static_cast(*It)->getValues(); + for (std::vector::const_iterator It2 = OutList.begin();It2 != OutList.end(); ++It2) { + if (*It2) + ret.push_back(*It2); + } + } + else if ((*It)->isDerivedFrom(PropertyLinkSubList::getClassTypeId())) { + const std::vector &OutList = static_cast(*It)->getValues(); + for (std::vector::const_iterator It2 = OutList.begin();It2 != OutList.end(); ++It2) { + if (*It2) + ret.push_back(*It2); + } + } + else if ((*It)->isDerivedFrom(PropertyLink::getClassTypeId())) { + if (static_cast(*It)->getValue()) + ret.push_back(static_cast(*It)->getValue()); + } + else if ((*It)->isDerivedFrom(PropertyLinkSub::getClassTypeId())) { + if (static_cast(*It)->getValue()) + ret.push_back(static_cast(*It)->getValue()); + } + } + + // Get document objects that this document object relies on + ExpressionEngine.getDocumentObjectDeps(ret); + + return ret; +} + +std::vector DocumentObject::getInList(void) const +{ + if (_pDoc) + return _pDoc->getInList(this); + else + return std::vector(); +} + +DocumentObjectGroup* DocumentObject::getGroup() const +{ + return dynamic_cast(GroupExtension::getGroupOfObject(this)); +} + +bool DocumentObject::testIfLinkDAGCompatible(DocumentObject *linkTo) const +{ + std::vector linkTo_in_vector; + linkTo_in_vector.push_back(linkTo); + return this->testIfLinkDAGCompatible(linkTo_in_vector); +} + +bool DocumentObject::testIfLinkDAGCompatible(const std::vector &linksTo) const +{ + Document* doc = this->getDocument(); + if (!doc) + throw Base::Exception("DocumentObject::testIfLinkIsDAG: object is not in any document."); + std::vector deplist = doc->getDependencyList(linksTo); + if( std::find(deplist.begin(),deplist.end(),this) != deplist.end() ) + //found this in dependency list + return false; + else + return true; +} + +bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSubList &linksTo) const +{ + const std::vector &linksTo_in_vector = linksTo.getValues(); + return this->testIfLinkDAGCompatible(linksTo_in_vector); +} + +bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSub &linkTo) const +{ + std::vector linkTo_in_vector; + linkTo_in_vector.reserve(1); + linkTo_in_vector.push_back(linkTo.getValue()); + return this->testIfLinkDAGCompatible(linkTo_in_vector); +} + +void DocumentObject::onLostLinkToObject(DocumentObject*) +{ + +} + +App::Document *DocumentObject::getDocument(void) const +{ + return _pDoc; +} + +void DocumentObject::setDocument(App::Document* doc) +{ + _pDoc=doc; + onSettingDocument(); +} + +void DocumentObject::onBeforeChange(const Property* prop) +{ + + // Store current name in oldLabel, to be able to easily retrieve old name of document object later + // when renaming expressions. + if (prop == &Label) + oldLabel = Label.getStrValue(); + + if (_pDoc) + onBeforeChangeProperty(_pDoc, prop); +} + +/// get called by the container when a Property was changed +void DocumentObject::onChanged(const Property* prop) +{ + if (_pDoc) + _pDoc->onChangedProperty(this,prop); + + if (prop == &Label && _pDoc && oldLabel != Label.getStrValue()) + _pDoc->signalRelabelObject(*this); + + if (prop->getType() & Prop_Output) + return; + // set object touched + StatusBits.set(0); +} + +PyObject *DocumentObject::getPyObject(void) +{ + if (PythonObject.is(Py::_None())) { + // ref counter is set to 1 + PythonObject = Py::Object(new DocumentObjectPy(this),true); + } + return Py::new_reference_to(PythonObject); +} + +std::vector DocumentObject::getPySubObjects(const std::vector&) const +{ + // default implementation returns nothing + return std::vector(); +} + +void DocumentObject::touch(void) +{ + StatusBits.set(0); +} + +/** + * @brief Check whether the document object is touched or not. + * @return true if document object is touched, false if not. + */ + +bool DocumentObject::isTouched() const +{ + return ExpressionEngine.isTouched() || StatusBits.test(0); +} + +void DocumentObject::Save (Base::Writer &writer) const +{ + writer.ObjectName = this->getNameInDocument(); + App::PropertyContainer::Save(writer); +} + +/** + * @brief Associate the expression \expr with the object identifier \a path in this document object. + * @param path Target object identifier for the result of the expression + * @param expr Expression tree + * @param comment Optional comment describing the expression + */ + +void DocumentObject::setExpression(const ObjectIdentifier &path, boost::shared_ptr expr, const char * comment) +{ + ExpressionEngine.setValue(path, expr, comment); + connectRelabelSignals(); +} + +/** + * @brief Get expression information associated with \a path. + * @param path Object identifier + * @return Expression info, containing expression and optional comment. + */ + +const PropertyExpressionEngine::ExpressionInfo DocumentObject::getExpression(const ObjectIdentifier &path) const +{ + boost::any value = ExpressionEngine.getPathValue(path); + + if (value.type() == typeid(PropertyExpressionEngine::ExpressionInfo)) + return boost::any_cast(value); + else + return PropertyExpressionEngine::ExpressionInfo(); +} + +/** + * @brief Invoke ExpressionEngine's renameObjectIdentifier, to possibly rewrite expressions using + * the \a paths map with current and new identifiers. + * + * @param paths + */ + +void DocumentObject::renameObjectIdentifiers(const std::map &paths) +{ + ExpressionEngine.renameObjectIdentifiers(paths); +} + +/** + * @brief Helper function that sets up a signal to track document object renames. + */ + +void DocumentObject::connectRelabelSignals() +{ + // Only keep signal if the ExpressionEngine has at least one expression + if (ExpressionEngine.numExpressions() > 0) { + + // Not already connected? + if (!onRelabledObjectConnection.connected()) + onRelabledObjectConnection = getDocument()->signalRelabelObject.connect(boost::bind(&PropertyExpressionEngine::slotObjectRenamed, &ExpressionEngine, _1)); + + // Connect to signalDeletedObject, to properly track deletion of other objects that might be referenced in an expression + if (!onDeletedObjectConnection.connected()) + onDeletedObjectConnection = getDocument()->signalDeletedObject.connect(boost::bind(&PropertyExpressionEngine::slotObjectDeleted, &ExpressionEngine, _1)); + + try { + // Crude method to resolve all expression dependencies + ExpressionEngine.execute(); + } + catch (...) { + // Ignore any error + } + } + else { + // Disconnect signals; nothing to track now + onRelabledObjectConnection.disconnect(); + onRelabledDocumentConnection.disconnect(); + onDeletedObjectConnection.disconnect(); + } +} + +void DocumentObject::onSettingDocument() { + + //call all extensions + auto vector = getExtensionsDerivedFromType(); + for(auto ext : vector) + ext->onExtendedSettingDocument(); +} + +void DocumentObject::setupObject() { + + //call all extensions + auto vector = getExtensionsDerivedFromType(); + for(auto ext : vector) + ext->onExtendedSetupObject(); +} + +void DocumentObject::unsetupObject() { + + //call all extensions + auto vector = getExtensionsDerivedFromType(); + for(auto ext : vector) + ext->onExtendedUnsetupObject(); +} diff --git a/src/App/DocumentObject.h b/src/App/DocumentObject.h index 3eb57bdd8..f6741985e 100644 --- a/src/App/DocumentObject.h +++ b/src/App/DocumentObject.h @@ -233,11 +233,11 @@ protected: /// get called after a document has been fully restored virtual void onDocumentRestored() {} /// get called after setting the document - virtual void onSettingDocument() {} + virtual void onSettingDocument(); /// get called after a brand new object was created - virtual void setupObject() {} + virtual void setupObject(); /// get called when object is going to be removed from the document - virtual void unsetupObject() {} + virtual void unsetupObject(); /// python object of this class and all descendend protected: // attributes diff --git a/src/App/DocumentObjectExtension.cpp b/src/App/DocumentObjectExtension.cpp new file mode 100644 index 000000000..c3071880c --- /dev/null +++ b/src/App/DocumentObjectExtension.cpp @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (c) Stefan Tröger (stefantroeger@gmx.net) 2016 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +#endif + +#include "DocumentObjectExtension.h" +#include "DocumentObjectExtensionPy.h" + +using namespace App; + +PROPERTY_SOURCE(App::DocumentObjectExtension, App::Extension) + +DocumentObjectExtension::DocumentObjectExtension() +{ + initExtension(App::DocumentObjectExtension::getClassTypeId()); +} + +DocumentObjectExtension::~DocumentObjectExtension() +{ + +} + +short int DocumentObjectExtension::extensionMustExecute(void) const { + + return 0; +} + +App::DocumentObjectExecReturn* DocumentObjectExtension::extensionExecute(void) { + + return App::DocumentObject::StdReturn; +} + +void DocumentObjectExtension::onExtendedSettingDocument() { + +} + +void DocumentObjectExtension::onExtendedSetupObject() { + +} + +void DocumentObjectExtension::onExtendedUnsetupObject() { + +} + +PyObject* DocumentObjectExtension::getExtensionPyObject(void) { + + if (ExtensionPythonObject.is(Py::_None())){ + // ref counter is set to 1 + ExtensionPythonObject = Py::Object(new DocumentObjectExtensionPy(this),true); + } + return Py::new_reference_to(ExtensionPythonObject); +} + + diff --git a/src/App/DocumentObjectExtension.h b/src/App/DocumentObjectExtension.h new file mode 100644 index 000000000..ea67518d3 --- /dev/null +++ b/src/App/DocumentObjectExtension.h @@ -0,0 +1,65 @@ +/*************************************************************************** + * Copyright (c) Stefan Tröger (stefantroeger@gmx.net) 2016 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef APP_DOCUMENTOBJECTEXTENSION_H +#define APP_DOCUMENTOBJECTEXTENSION_H + +#include "Extension.h" +#include "DocumentObject.h" + +namespace App { + +/** + * @brief Extension with special document object calls + * + */ +class AppExport DocumentObjectExtension : public App::Extension +{ + + //The cass does not have properties itself, but it is important to provide the property access + //functions. see cpp file for details + PROPERTY_HEADER(App::DocumentObjectExtension ); + +public: + + DocumentObjectExtension (); + virtual ~DocumentObjectExtension (); + + //override if execution is nesseccary + virtual short extensionMustExecute(void) const; + virtual App::DocumentObjectExecReturn *extensionExecute(void); + + + /// get called after setting the document + virtual void onExtendedSettingDocument(); + /// get called after a brand new object was created + virtual void onExtendedSetupObject(); + /// get called when object is going to be removed from the document + virtual void onExtendedUnsetupObject(); + + virtual PyObject* getExtensionPyObject(void); +}; + +} //App + +#endif // APP_DOCUMENTOBJECTEXTENSION_H diff --git a/src/App/DocumentObjectExtensionPy.xml b/src/App/DocumentObjectExtensionPy.xml new file mode 100644 index 000000000..858ebc5fc --- /dev/null +++ b/src/App/DocumentObjectExtensionPy.xml @@ -0,0 +1,18 @@ + + + + + + Base class for all document object extensions + + + + diff --git a/src/App/DocumentObjectExtensionPyImp.cpp b/src/App/DocumentObjectExtensionPyImp.cpp new file mode 100644 index 000000000..ddf255afc --- /dev/null +++ b/src/App/DocumentObjectExtensionPyImp.cpp @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (c) Stefan Tröger (stefantroeger@gmx.net) 2016 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + +// inclution of the generated files (generated out of PropertyContainerPy.xml) +#include "DocumentObjectExtensionPy.h" +#include "DocumentObjectExtensionPy.cpp" + +using namespace App; + +// returns a string which represent the object e.g. when printed in python +std::string DocumentObjectExtensionPy::representation(void) const +{ + return std::string(""); +} + +PyObject *DocumentObjectExtensionPy::getCustomAttributes(const char* attr) const +{ + return 0; +} + +int DocumentObjectExtensionPy::setCustomAttributes(const char* attr, PyObject *obj) +{ + return 0; +} diff --git a/src/App/DocumentObjectGroup.cpp b/src/App/DocumentObjectGroup.cpp index 946d039a7..1e6e7b6a8 100644 --- a/src/App/DocumentObjectGroup.cpp +++ b/src/App/DocumentObjectGroup.cpp @@ -34,7 +34,7 @@ using namespace App; -PROPERTY_SOURCE(App::GroupExtension, App::Extension) +PROPERTY_SOURCE(App::GroupExtension, App::DocumentObjectExtension) GroupExtension::GroupExtension() { @@ -89,7 +89,7 @@ void GroupExtension::removeObjectFromDocument(DocumentObject* obj) { // remove all children if (obj->hasExtension(GroupExtension::getClassTypeId())) { - GroupExtension *grp = static_cast(obj->getExtension(GroupExtension::getClassTypeId())); + GroupExtension *grp = static_cast(obj->getExtension(GroupExtension::getClassTypeId())); // recursive call to remove all subgroups grp->removeObjectsFromDocument(); } @@ -112,7 +112,7 @@ bool GroupExtension::hasObject(const DocumentObject* obj, bool recursive) const if (*it == obj) { return true; } else if ( recursive && (*it)->hasExtension(GroupExtension::getClassTypeId()) ) { - App::GroupExtension *subGroup = static_cast ((*it)->getExtension(GroupExtension::getClassTypeId())); + App::GroupExtension *subGroup = static_cast ((*it)->getExtension(GroupExtension::getClassTypeId())); if (subGroup->hasObject (obj, recursive)) { return true; } @@ -129,7 +129,7 @@ bool GroupExtension::isChildOf(const GroupExtension* group) const if (*it == getExtendedObject()) return true; if ((*it)->hasExtension(GroupExtension::getClassTypeId())) { - if (this->isChildOf(static_cast((*it)->getExtension(GroupExtension::getClassTypeId())))) + if (this->isChildOf(static_cast((*it)->getExtension(GroupExtension::getClassTypeId())))) return true; } } diff --git a/src/App/DocumentObjectGroup.h b/src/App/DocumentObjectGroup.h index 6af8fcd5c..7dd4ee63d 100644 --- a/src/App/DocumentObjectGroup.h +++ b/src/App/DocumentObjectGroup.h @@ -27,7 +27,7 @@ #include "FeaturePython.h" #include "DocumentObject.h" #include "PropertyLinks.h" -#include "Extension.h" +#include "DocumentObjectExtension.h" #include @@ -36,7 +36,7 @@ namespace App class DocumentObjectGroup; class GroupExtensionPy; -class AppExport GroupExtension : public Extension +class AppExport GroupExtension : public DocumentObjectExtension { PROPERTY_HEADER(App::GroupExtension); diff --git a/src/App/Extension.cpp b/src/App/Extension.cpp index 07ef8af4c..cf3ee329a 100644 --- a/src/App/Extension.cpp +++ b/src/App/Extension.cpp @@ -177,3 +177,14 @@ Extension* ExtensionContainer::getExtension(const char* name) { } return nullptr; } + +std::vector< Extension* > ExtensionContainer::getExtensionsDerivedFrom(Base::Type type) const { + + std::vector vec; + //and for types derived from it, as they can be cast to the extension + for(auto entry : _extensions) { + if(entry.first.isDerivedFrom(type)) + vec.push_back(entry.second); + } + return vec; +} diff --git a/src/App/Extension.h b/src/App/Extension.h index f8875f497..3237adb4e 100644 --- a/src/App/Extension.h +++ b/src/App/Extension.h @@ -21,8 +21,8 @@ ***************************************************************************/ -#ifndef APP_DOCUMENTOBJECTEXTENSION_H -#define APP_DOCUMENTOBJECTEXTENSION_H +#ifndef APP_EXTENSION_H +#define APP_EXTENSION_H #include "PropertyContainer.h" #include "PropertyPythonObject.h" @@ -119,9 +119,21 @@ public: bool hasExtension(const char* name) const; //this version does not check derived classes App::Extension* getExtension(Base::Type); App::Extension* getExtension(const char* name); //this version does not check derived classes - template - Extension* getExtensionByType() { - return dynamic_cast(getExtension(Extension::getClassTypeId())); + template + ExtensionT* getExtensionByType() { + return dynamic_cast(getExtension(ExtensionT::getClassTypeId())); + }; + + //get all extensions which have the given base class + std::vector getExtensionsDerivedFrom(Base::Type type) const; + template + std::vector getExtensionsDerivedFromType() const { + auto vec = getExtensionsDerivedFrom(ExtensionT::getClassTypeId()); + std::vector typevec; + for(auto ext : vec) + typevec.push_back(dynamic_cast(ext)); + + return typevec; }; ExtensionIterator extensionBegin() {return _extensions.begin();}; @@ -134,4 +146,4 @@ private: } //App -#endif // APP_DOCUMENTOBJECTEXTENSION_H +#endif // APP_EXTENSION_H diff --git a/src/App/ExtensionContainerPyImp.cpp b/src/App/ExtensionContainerPyImp.cpp index 5e15b42a3..dea412492 100644 --- a/src/App/ExtensionContainerPyImp.cpp +++ b/src/App/ExtensionContainerPyImp.cpp @@ -71,14 +71,12 @@ int ExtensionContainerPy::initialisation() { PyObject* ExtensionContainerPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper { // create a new instance of @self.export.Name@ and the Twin object - Base::Console().Message("Make\n"); return 0; } // constructor method int ExtensionContainerPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) { - Base::Console().Message("Init\n"); return 0; } diff --git a/src/App/ExtensionPy.xml b/src/App/ExtensionPy.xml index 8bc059ce7..a499639e3 100644 --- a/src/App/ExtensionPy.xml +++ b/src/App/ExtensionPy.xml @@ -11,7 +11,7 @@ FatherNamespace="Base"> - Base class for all document object extensions + Base class for all extensions diff --git a/src/App/OriginGroup.cpp b/src/App/OriginGroup.cpp index a04498e41..cb1276a6d 100644 --- a/src/App/OriginGroup.cpp +++ b/src/App/OriginGroup.cpp @@ -83,45 +83,44 @@ App::DocumentObject *OriginGroupExtension::getGroupOfObject (const DocumentObjec return 0; } -/* -short OriginGroupExtension::mustExecute() const { + +short OriginGroupExtension::extensionMustExecute() const { if (Origin.isTouched ()) { return 1; } else { - return GeoFeatureGroup::mustExecute(); + return GeoFeatureGroupExtension::extensionMustExecute(); } } -App::DocumentObjectExecReturn *OriginGroupExtension::execute() { +App::DocumentObjectExecReturn *OriginGroupExtension::extensionExecute() { try { // try to find all base axis and planes in the origin getOrigin (); } catch (const Base::Exception &ex) { - setError (); + //getExtendedObject()->setError (); return new App::DocumentObjectExecReturn ( ex.what () ); } - return GeoFeatureGroup::execute (); + return GeoFeatureGroupExtension::extensionExecute (); } -void OriginGroupExtension::setupObject () { - App::Document *doc = getDocument (); +void OriginGroupExtension::onExtendedSetupObject () { + App::Document *doc = getExtendedObject()->getDocument (); - std::string objName = std::string ( getNameInDocument()).append ( "Origin" ); + std::string objName = std::string ( getExtendedObject()->getNameInDocument()).append ( "Origin" ); App::DocumentObject *originObj = doc->addObject ( "App::Origin", objName.c_str () ); assert ( originObj && originObj->isDerivedFrom ( App::Origin::getClassTypeId () ) ); Origin.setValue (originObj); - GeoFeatureGroup::setupObject (); + GeoFeatureGroupExtension::onExtendedSetupObject (); } -void OriginGroupExtension::unsetupObject () { +void OriginGroupExtension::onExtendedUnsetupObject () { App::DocumentObject *origin = Origin.getValue (); if (origin && !origin->isDeleting ()) { origin->getDocument ()->remObject (origin->getNameInDocument()); } - GeoFeatureGroup::unsetupObject (); -} -*/ \ No newline at end of file + GeoFeatureGroupExtension::onExtendedUnsetupObject (); +} \ No newline at end of file diff --git a/src/App/OriginGroup.h b/src/App/OriginGroup.h index 982f36338..f8c3f6fdc 100644 --- a/src/App/OriginGroup.h +++ b/src/App/OriginGroup.h @@ -57,18 +57,18 @@ public: static DocumentObject* getGroupOfObject (const DocumentObject* obj, bool indirect=true); /// Returns true on changing OriginFeature set - //virtual short mustExecute () const; + virtual short extensionMustExecute () const override; /// Origin linked to the group PropertyLink Origin; protected: /// Checks integrity of the Origin - //virtual App::DocumentObjectExecReturn *execute (); + virtual App::DocumentObjectExecReturn *extensionExecute () override; /// Creates the corresponding Origin object - //virtual void setupObject (); + virtual void onExtendedSetupObject () override; /// Removes all planes and axis if they are still linked to the document - //virtual void unsetupObject (); + virtual void onExtendedUnsetupObject () override; }; } /* App */