Extensions: special calls for document object extensions
This commit is contained in:
parent
4c42181e34
commit
a8d0accdad
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
416
src/App/DocumentObject.cpp.orig
Normal file
416
src/App/DocumentObject.cpp.orig
Normal 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();
|
||||
}
|
|
@ -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
|
||||
|
|
79
src/App/DocumentObjectExtension.cpp
Normal file
79
src/App/DocumentObjectExtension.cpp
Normal 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);
|
||||
}
|
||||
|
||||
|
65
src/App/DocumentObjectExtension.h
Normal file
65
src/App/DocumentObjectExtension.h
Normal 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
|
18
src/App/DocumentObjectExtensionPy.xml
Normal file
18
src/App/DocumentObjectExtensionPy.xml
Normal 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>
|
50
src/App/DocumentObjectExtensionPyImp.cpp
Normal file
50
src/App/DocumentObjectExtensionPyImp.cpp
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 ();
|
||||
}
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue
Block a user