Extensions: special calls for document object extensions

This commit is contained in:
Stefan Tröger 2016-06-02 06:29:05 +02:00 committed by wmayer
parent 4c42181e34
commit a8d0accdad
17 changed files with 732 additions and 38 deletions

View File

@ -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

View File

@ -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

View File

@ -33,6 +33,7 @@
#include "DocumentObjectGroup.h"
#include "PropertyLinks.h"
#include "PropertyExpressionEngine.h"
#include "DocumentObjectExtension.h"
#include <App/DocumentObjectPy.h>
#include <boost/signals/connection.hpp>
#include <boost/bind.hpp>
@ -92,12 +93,28 @@ App::DocumentObjectExecReturn *DocumentObject::recompute(void)
DocumentObjectExecReturn *DocumentObject::execute(void)
{
//call all extensions
auto vector = getExtensionsDerivedFromType<App::DocumentObjectExtension>();
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<App::DocumentObjectExtension>();
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<App::DocumentObjectExtension>();
for(auto ext : vector)
ext->onExtendedSettingDocument();
}
void DocumentObject::setupObject() {
//call all extensions
auto vector = getExtensionsDerivedFromType<App::DocumentObjectExtension>();
for(auto ext : vector)
ext->onExtendedSetupObject();
}
void DocumentObject::unsetupObject() {
//call all extensions
auto vector = getExtensionsDerivedFromType<App::DocumentObjectExtension>();
for(auto ext : vector)
ext->onExtendedUnsetupObject();
}

View File

@ -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 <Base/Writer.h>
#include "Document.h"
#include "DocumentObject.h"
#include "DocumentObjectGroup.h"
#include "PropertyLinks.h"
#include "PropertyExpressionEngine.h"
<<<<<<< d634f3384aa4e6436c7df203435de3895700be84
#include <App/DocumentObjectPy.h>
=======
#include "DocumentObjectExtension.h"
>>>>>>> Special calls for document object extensions
#include <boost/signals/connection.hpp>
#include <boost/bind.hpp>
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<App::DocumentObjectExtension>();
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<App::DocumentObjectExtension>();
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*> DocumentObject::getOutList(void) const
{
std::vector<Property*> List;
std::vector<DocumentObject*> ret;
getPropertyList(List);
for (std::vector<Property*>::const_iterator It = List.begin();It != List.end(); ++It) {
if ((*It)->isDerivedFrom(PropertyLinkList::getClassTypeId())) {
const std::vector<DocumentObject*> &OutList = static_cast<PropertyLinkList*>(*It)->getValues();
for (std::vector<DocumentObject*>::const_iterator It2 = OutList.begin();It2 != OutList.end(); ++It2) {
if (*It2)
ret.push_back(*It2);
}
}
else if ((*It)->isDerivedFrom(PropertyLinkSubList::getClassTypeId())) {
const std::vector<DocumentObject*> &OutList = static_cast<PropertyLinkSubList*>(*It)->getValues();
for (std::vector<DocumentObject*>::const_iterator It2 = OutList.begin();It2 != OutList.end(); ++It2) {
if (*It2)
ret.push_back(*It2);
}
}
else if ((*It)->isDerivedFrom(PropertyLink::getClassTypeId())) {
if (static_cast<PropertyLink*>(*It)->getValue())
ret.push_back(static_cast<PropertyLink*>(*It)->getValue());
}
else if ((*It)->isDerivedFrom(PropertyLinkSub::getClassTypeId())) {
if (static_cast<PropertyLinkSub*>(*It)->getValue())
ret.push_back(static_cast<PropertyLinkSub*>(*It)->getValue());
}
}
// Get document objects that this document object relies on
ExpressionEngine.getDocumentObjectDeps(ret);
return ret;
}
std::vector<App::DocumentObject*> DocumentObject::getInList(void) const
{
if (_pDoc)
return _pDoc->getInList(this);
else
return std::vector<App::DocumentObject*>();
}
DocumentObjectGroup* DocumentObject::getGroup() const
{
return dynamic_cast<DocumentObjectGroup*>(GroupExtension::getGroupOfObject(this));
}
bool DocumentObject::testIfLinkDAGCompatible(DocumentObject *linkTo) const
{
std::vector<App::DocumentObject*> linkTo_in_vector;
linkTo_in_vector.push_back(linkTo);
return this->testIfLinkDAGCompatible(linkTo_in_vector);
}
bool DocumentObject::testIfLinkDAGCompatible(const std::vector<DocumentObject *> &linksTo) const
{
Document* doc = this->getDocument();
if (!doc)
throw Base::Exception("DocumentObject::testIfLinkIsDAG: object is not in any document.");
std::vector<App::DocumentObject*> 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<App::DocumentObject*> &linksTo_in_vector = linksTo.getValues();
return this->testIfLinkDAGCompatible(linksTo_in_vector);
}
bool DocumentObject::testIfLinkDAGCompatible(PropertyLinkSub &linkTo) const
{
std::vector<App::DocumentObject*> 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<PyObject *> DocumentObject::getPySubObjects(const std::vector<std::string>&) const
{
// default implementation returns nothing
return std::vector<PyObject *>();
}
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<Expression> 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<PropertyExpressionEngine::ExpressionInfo>(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<ObjectIdentifier, ObjectIdentifier> &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<App::DocumentObjectExtension>();
for(auto ext : vector)
ext->onExtendedSettingDocument();
}
void DocumentObject::setupObject() {
//call all extensions
auto vector = getExtensionsDerivedFromType<App::DocumentObjectExtension>();
for(auto ext : vector)
ext->onExtendedSetupObject();
}
void DocumentObject::unsetupObject() {
//call all extensions
auto vector = getExtensionsDerivedFromType<App::DocumentObjectExtension>();
for(auto ext : vector)
ext->onExtendedUnsetupObject();
}

View File

@ -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

View File

@ -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 <cassert>
# include <algorithm>
#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);
}

View File

@ -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

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="ExtensionPy"
Name="DocumentObjectExtensionPy"
TwinPointer="DocumentObjectExtension"
Twin="DocumentObjectExtension"
Include="App/DocumentObjectExtension.h"
Namespace="App"
FatherInclude="App/ExtensionPy.h"
FatherNamespace="App">
<Documentation>
<Author Licence="LGPL" Name="Stefan Troeger" EMail="stefantroeger@gmx.net" />
<UserDocu>Base class for all document object extensions</UserDocu>
</Documentation>
<CustomAttributes />
</PythonExport>
</GenerateModel>

View File

@ -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 <sstream>
#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("<document object extension>");
}
PyObject *DocumentObjectExtensionPy::getCustomAttributes(const char* attr) const
{
return 0;
}
int DocumentObjectExtensionPy::setCustomAttributes(const char* attr, PyObject *obj)
{
return 0;
}

View File

@ -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<GroupExtension*>(obj->getExtension(GroupExtension::getClassTypeId()));
GroupExtension *grp = static_cast<GroupExtension*>(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<App::GroupExtension *> ((*it)->getExtension(GroupExtension::getClassTypeId()));
App::GroupExtension *subGroup = static_cast<App::GroupExtension *> ((*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<GroupExtension*>((*it)->getExtension(GroupExtension::getClassTypeId()))))
if (this->isChildOf(static_cast<GroupExtension*>((*it)->getExtension(GroupExtension::getClassTypeId()))))
return true;
}
}

View File

@ -27,7 +27,7 @@
#include "FeaturePython.h"
#include "DocumentObject.h"
#include "PropertyLinks.h"
#include "Extension.h"
#include "DocumentObjectExtension.h"
#include <vector>
@ -36,7 +36,7 @@ namespace App
class DocumentObjectGroup;
class GroupExtensionPy;
class AppExport GroupExtension : public Extension
class AppExport GroupExtension : public DocumentObjectExtension
{
PROPERTY_HEADER(App::GroupExtension);

View File

@ -177,3 +177,14 @@ Extension* ExtensionContainer::getExtension(const char* name) {
}
return nullptr;
}
std::vector< Extension* > ExtensionContainer::getExtensionsDerivedFrom(Base::Type type) const {
std::vector<Extension*> 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;
}

View File

@ -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<typename Extension>
Extension* getExtensionByType() {
return dynamic_cast<Extension*>(getExtension(Extension::getClassTypeId()));
template<typename ExtensionT>
ExtensionT* getExtensionByType() {
return dynamic_cast<ExtensionT*>(getExtension(ExtensionT::getClassTypeId()));
};
//get all extensions which have the given base class
std::vector<Extension*> getExtensionsDerivedFrom(Base::Type type) const;
template<typename ExtensionT>
std::vector<ExtensionT*> getExtensionsDerivedFromType() const {
auto vec = getExtensionsDerivedFrom(ExtensionT::getClassTypeId());
std::vector<ExtensionT*> typevec;
for(auto ext : vec)
typevec.push_back(dynamic_cast<ExtensionT*>(ext));
return typevec;
};
ExtensionIterator extensionBegin() {return _extensions.begin();};
@ -134,4 +146,4 @@ private:
} //App
#endif // APP_DOCUMENTOBJECTEXTENSION_H
#endif // APP_EXTENSION_H

View File

@ -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;
}

View File

@ -11,7 +11,7 @@
FatherNamespace="Base">
<Documentation>
<Author Licence="LGPL" Name="Stefan Troeger" EMail="stefantroeger@gmx.net" />
<UserDocu>Base class for all document object extensions</UserDocu>
<UserDocu>Base class for all extensions</UserDocu>
</Documentation>
<CustomAttributes />
</PythonExport>

View File

@ -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 ();
}
*/
GeoFeatureGroupExtension::onExtendedUnsetupObject ();
}

View File

@ -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 */